diff --git a/.gitignore b/.gitignore index a2570c1a..bbf526bc 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,12 @@ tools/waf-sig* *.gz *.zip *.7z +*.stats + +# spelling +dictionary.dic +file.log* +lex.txt __pycache__ .mypy_cache/ @@ -48,7 +54,8 @@ __pycache__ *.~* *.~$* -**/foxbms-2_axivion_report.json +**/foxbms-2_axivion_report*.json +spa-artifacts/ *.exe @@ -56,3 +63,5 @@ __pycache__ # CAN log files *.asc + +*.tmp diff --git a/CITATION.cff b/CITATION.cff index aaf08d9c..db8197db 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -46,5 +46,5 @@ keywords: - "BMS" message: "If the foxBMS project contributes to a project that leads to a scientific publication, please acknowledge this fact by citing." title: "foxBMS - The Most Advanced Open Source BMS Platform: foxBMS 2" -version: "1.5.1" -date-released: 2023-02-23 +version: "1.6.0" +date-released: 2023-10-12 diff --git a/conf/bms/schema/slave.schema.json b/conf/bms/schema/slave.schema.json index e6868009..b268d156 100644 --- a/conf/bms/schema/slave.schema.json +++ b/conf/bms/schema/slave.schema.json @@ -24,7 +24,9 @@ "ltc", "maxim", "nxp", - "debug" + "debug", + "adi", + "ti" ] }, "ic": { @@ -111,6 +113,44 @@ ] } } + }, + "else": { + "if": { + "properties": { + "manufacturer": { + "enum": [ + "adi" + ] + } + } + }, + "then": { + "properties": { + "ic": { + "enum": [ + "ades1830" + ] + } + } + }, + "else": { + "if": { + "properties": { + "manufacturer": { + "enum": [ + "ti" + ] + } + } + }, + "properties": { + "ic": { + "enum": [ + "dummy" + ] + } + } + } } } } @@ -185,7 +225,7 @@ "properties": { "model": { "enum": [ - "ncu15xh103f6sxx" + "ncxxxxh103" ] } } diff --git a/conf/env/paths_win32.txt b/conf/env/paths_win32.txt index 62f4ceb9..e725463d 100644 --- a/conf/env/paths_win32.txt +++ b/conf/env/paths_win32.txt @@ -5,6 +5,6 @@ C:\ti\ccs1200\ccs\utils\cygwin C:\ti\ccs1200\ccs\utils\tiobj2bin C:\ti\Hercules\HALCoGen\v04.07.01 C:\Program Files\LLVM\13.0.0\bin -C:\Ruby\Ruby272-x64\bin +C:\Ruby\Ruby3.1.3-x64\bin C:\MinGW64\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\mingw64\bin C:\Bauhaus\7.5.2\bin diff --git a/conf/guidelines/rules.json b/conf/guidelines/rules.json index 95516a37..aa11336e 100644 --- a/conf/guidelines/rules.json +++ b/conf/guidelines/rules.json @@ -3,39 +3,45 @@ "7z", "coverage", "exe", - "svg", - "pyc", - "png", "gif", "ico", + "jpg", "o", - "vsdx", + "png", + "pptx", + "pyc", "pyc", + "stats", + "svg", "svg", "tar", "tar.bz2", "tar.gz", "vsdx", - "~vsdx", - "zip" + "vsdx", + "zip", + "~pptx", + "~vsdx" ], "global": [ "**/**.log", + "**/*.asc", "**/*~", + "**/.lock-waf_*_build", + "**/.vscode/**", "**/__pycache__/**", "**/foxbms-2_axivion_report.json", - "**/*.asc", - "**/.lock-waf_*_build", + "**/foxbms_spa_report.json", ".git/**", ".mypy_cache/**", - ".vscode/**", - "build/**", "build-tools-tests/**", + "build/**", "conf/hcg/include/*", "conf/hcg/source/*", "docs/_ext/**", "foxbms/**", "libbuild/**", + "spa-artifacts/**", "src/app/driver/afe/nxp/mc33775a/vendor/**", "src/app/driver/sbc/fs8x_driver/**", "src/os/freertos/**/*.asm", @@ -45,32 +51,34 @@ "src/os/freertos/GitHub-FreeRTOS-Kernel-Home.url", "src/os/freertos/History.txt", "src/os/freertos/LICENSE.md", - "src/os/freertos/portable/memmang/ReadMe.url", - "src/os/freertos/portable/readme.txt", "src/os/freertos/Quick_Start_Guide.url", "src/os/freertos/README.md", + "src/os/freertos/portable/memmang/ReadMe.url", + "src/os/freertos/portable/readme.txt", "src/os/safertos/**/*.asm", "src/os/safertos/**/*.c", "src/os/safertos/**/*.h", "tests/axivion/compiler-errata/ti-cgt-arm*/**", "tests/axivion/qualification-test/qualification-kit/**", - "tests/unit/build/**", "tests/scripts/waf-core/general/**", "tests/scripts/waf-core/init/**", "tests/scripts/waf-core/install/**", "tests/scripts/waf-core/install_group/**", "tests/scripts/waf-core/preproc/**", "tests/scripts/waf-tools/f_guidelines/tests/**", + "tests/unit/build/**", "tools/.waf3-**", + "tools/dbc/third-party/**", "tools/vendor/**", "tools/waf", - "tools/waf3-**", - "tools/waf-verify-sig.py" + "tools/waf-verify-sig.py", + "tools/waf3-**" ], "file_names": { "name": "GENERAL:001", "regex": "^[a-z0-9_\\-.]*$", "exclude": [ + "**/*.py1.stats", "**/*.~vsdx", "**/LICENSE.md", "**/README.md", @@ -94,13 +102,18 @@ "**/.clang-format", "**/.dummy", "**/.gitignore", + "**/README.md", "**/__init__.py", "**/__main__.py", - "**/README.md", + "**/dir_exists", + "**/misc.py", "**/wscript", "tests/axivion/addon-test/**/ok.c", - "tests/axivion/addon-test/test_unique_filename/**", "tests/axivion/addon-test/test_*/**", + "tests/axivion/addon-test/test_unique_filename/**", + "tests/unit/axivion/axivion_config.json", + "tests/unit/axivion/ci_config.json", + "tests/unit/axivion/compiler_config.json", "tools/gui/LICENSE.md" ] }, @@ -167,8 +180,8 @@ "header": { "name": "C:002", "exclude": [ - "src/app/driver/sbc/fs8x_driver/**", - "src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.*" + "src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.*", + "src/app/driver/sbc/fs8x_driver/**" ], "text": [ "/**", @@ -282,8 +295,8 @@ "source": { "exclude": [ "conf/tpl/test_c.c", - "docs/software/unit-tests/test_abc.c", "docs/developer-manual/style-guide/examples/c-006-test.c", + "docs/software/unit-tests/test_abc.c", "src/app/driver/config/can_cfg.c", "src/app/engine/config/diag_cfg.c", "src/app/engine/config/sys_mon_cfg.c", @@ -304,6 +317,14 @@ "test_header": { "exclude": [ "conf/tpl/c.h", + "docs/developer-manual/style-guide/examples/c-005.h", + "docs/developer-manual/style-guide/examples/c-006-source.h", + "docs/developer-manual/style-guide/examples/c-007_abc.h", + "docs/developer-manual/style-guide/examples/c-007_abc_cfg.h", + "docs/developer-manual/style-guide/examples/c-008.h", + "docs/developer-manual/style-guide/examples/c-011.h", + "docs/developer-manual/style-guide/examples/c-013.h", + "docs/developer-manual/style-guide/examples/c-015.h", "docs/developer-manual/style-guide/state-machine-example/state-machine.h", "docs/software/build-process/misc/libproject-example.h", "docs/software/unit-tests/abc.h", @@ -312,6 +333,7 @@ ], "sections": [ "/*========== Includes =======================================================*/", + "/*========== Unit Testing Framework Directives ==============================*/", "/*========== Macros and Definitions =========================================*/" ] }, @@ -352,10 +374,13 @@ "docs/software/unit-tests/run_abc.c", "src/**", "tests/c-std/c-std-test.c", - "tests/variants/lib-build/*" + "tests/variants/lib-build/*", + "tools/crc/crc-10_0x48f.c", + "tools/crc/crc-15_0xc599.c" ], "sections": [ "/*========== Includes =======================================================*/", + "/*========== Unit Testing Framework Directives ==============================*/", "/*========== Definitions and Implementations for Unit Test ==================*/", "/*========== Setup and Teardown =============================================*/", "/*========== Test Cases =====================================================*/" @@ -510,7 +535,8 @@ }, "YAML": { "exclude": [ - "conf/env/conda_env_*.yaml" + "conf/env/conda_env_*.yaml", + "tests/hil/hil-env.yaml" ], "files": [ "**/*.dot", diff --git a/conf/spa/.pylintrc b/conf/spa/.pylintrc index d7eea16c..66ddf264 100644 --- a/conf/spa/.pylintrc +++ b/conf/spa/.pylintrc @@ -16,7 +16,7 @@ ignore-patterns= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). -init-hook='import sys; sys.path.extend(["tools/waf3-2.0.22-1241519b19b496207abef1f72bbf61c2", "tools/.waf3-2.0.22-1241519b19b496207abef1f72bbf61c2", "tools/gui"])' +init-hook='import sys; sys.path.extend(["tools/waf3-2.0.22-1241519b19b496207abef1f72bbf61c2", "tools/.waf3-2.0.22-1241519b19b496207abef1f72bbf61c2", "tools/gui", "tests/hil"])' # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the # number of processors available to use. diff --git a/conf/spell/README.md b/conf/spell/README.md new file mode 100644 index 00000000..8cafb597 --- /dev/null +++ b/conf/spell/README.md @@ -0,0 +1,16 @@ +# Spelling Checking Configuration + +## Setup + +- Install aspell 0.60.8 or later +- Install englisch dictionary +- Install conda environment + +## Usage + +```bash +$ # activate conda base environment +$ conda activate pyspell-2-8-2 +$ cd path/to/foxbms-2 +$ pyspelling -c conf/spell/pyspell_cfg.yml +``` diff --git a/conf/spell/check_dicts.py b/conf/spell/check_dicts.py new file mode 100644 index 00000000..7112138c --- /dev/null +++ b/conf/spell/check_dicts.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Template for Python scripts""" + +import argparse +import logging +import sys + +from pathlib import Path + +SCRIPT_DIR = Path(__file__).parent.resolve() +ROOT_DIR = Path(__file__).parent.parent.parent + + +def main(): + """This script does this and that""" + parser = argparse.ArgumentParser() + parser.add_argument( + "-v", + "--verbosity", + dest="verbosity", + action="count", + default=0, + help="set verbosity level", + ) + args = parser.parse_args() + + if args.verbosity == 1: + logging.basicConfig(level=logging.INFO) + elif args.verbosity > 1: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.ERROR) + + dict_files = (SCRIPT_DIR / "dicts").glob("*.txt") + err = 0 + dicts = {} + for i in dict_files: + txt = i.read_text(encoding="utf-8") + if not txt: + err += 1 + logging.error( + f"Found empty dictionary: {i.absolute()}. " + "Empty dicts are not allowed." + ) + words = txt.splitlines() + if not words == sorted(words): + logging.error( + f"Found unsorted dictionary: {i.absolute()}. " + "Word lists must be alphabetically sorted." + ) + err += 1 + if not len(words) == len(set(words)): + logging.error( + f"Found duplicate entries in dictionary: {i.absolute()}. " + "Words must be unique per file." + ) + err += 1 + for word in words: + for source, known_words in dicts.items(): + if word in known_words: + logging.error( + f"Dictionary {i.relative_to(ROOT_DIR)} contains word " + f"'{word}' which is already in the word list " + f"provided by '{source.relative_to(ROOT_DIR)}'." + ) + # now we are good to add the words to the global dictionary + dicts[i] = words + sys.exit(err) + + +if __name__ == "__main__": + main() diff --git a/conf/spell/conda_env_spelling_linux.yaml b/conf/spell/conda_env_spelling_linux.yaml new file mode 100644 index 00000000..0b41ca3b --- /dev/null +++ b/conf/spell/conda_env_spelling_linux.yaml @@ -0,0 +1,76 @@ +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +name: pyspell-2-8-2 +channels: + - defaults + - conda-forge +dependencies: + - _libgcc_mutex=0.1=main + - _openmp_mutex=5.1=1_gnu + - bzip2=1.0.8=h7b6447c_0 + - ca-certificates=2023.01.10=h06a4308_0 + - ld_impl_linux-64=2.38=h1181459_1 + - libffi=3.4.4=h6a678d5_0 + - libgcc-ng=11.2.0=h1234567_1 + - libgomp=11.2.0=h1234567_1 + - libstdcxx-ng=11.2.0=h1234567_1 + - libuuid=1.41.5=h5eee18b_0 + - ncurses=6.4=h6a678d5_0 + - openssl=1.1.1t=h7f8727e_0 + - python=3.10.11=h7a1cb2a_2 + - readline=8.2=h5eee18b_0 + - sqlite=3.41.2=h5eee18b_0 + - tk=8.6.12=h1ccaba5_0 + - tzdata=2023c=h04d1e81_0 + - xz=5.4.2=h5eee18b_0 + - zlib=1.2.13=h5eee18b_0 + - pip: + - beautifulsoup4==4.12.2 + - bracex==2.3.post1 + - html5lib==1.1 + - lxml==4.9.2 + - markdown==3.4.3 + - pip==23.0.1 + - pyspelling==2.8.2 + - pyyaml==6.0 + - setuptools==67.8.0 + - six==1.16.0 + - soupsieve==2.4.1 + - wcmatch==8.4.1 + - webencodings==0.5.1 + - wheel==0.38.4 diff --git a/conf/spell/dicts/lan_c.txt b/conf/spell/dicts/lan_c.txt new file mode 100644 index 00000000..6872e763 --- /dev/null +++ b/conf/spell/dicts/lan_c.txt @@ -0,0 +1,11 @@ +bool +cdefs +curpc +endif +goto +ifdef +ifndef +mktime +printf +struct +uint diff --git a/conf/spell/dicts/lan_py.txt b/conf/spell/dicts/lan_py.txt new file mode 100644 index 00000000..812a0296 --- /dev/null +++ b/conf/spell/dicts/lan_py.txt @@ -0,0 +1,23 @@ +abspath +elif +endswith +environ +getattr +hasattr +hexsha +isdir +isfile +isinstance +len +linenos +linesep +mkdir +pathlib +pathsep +shlex +shutil +splitlines +startswith +subprocess +tarfile +tempfile diff --git a/conf/spell/dicts/module_prefix.txt b/conf/spell/dicts/module_prefix.txt new file mode 100644 index 00000000..90d9eb57 --- /dev/null +++ b/conf/spell/dicts/module_prefix.txt @@ -0,0 +1,74 @@ +ABC +ADC +ADI +AFE +ALGO +BAL +BALS +BC +BETA +BMS +BS +CAN +CANRX +CANTX +CHK +CONT +CRC +DATA +DIAG +DMA +DX +EG +FAKE +FAS +FRAM +FS85 +FSYS +FTSK +GEN +HTSEN +I165C +I2C +ILCK +IMD +IO +IR155 +LED +LTC +MATH +MCU +MEAS +MINFO +MRC +MXM +N775 +NOIMD +NONE +NXP +OS +PEX +PL +PWM +RTC +SBC +SE +SOA +SOC +SOE +SOF +SOH +SPI +SPS +STD +STU +SUPER +SYS +SYSM +TEST +TODO +TS +TSEN +TSI +UTIL +VER diff --git a/conf/spell/pyspell_cfg.yml b/conf/spell/pyspell_cfg.yml new file mode 100644 index 00000000..129772bc --- /dev/null +++ b/conf/spell/pyspell_cfg.yml @@ -0,0 +1,271 @@ +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +matrix: + - name: c + group: code + sources: + # third party is not checked and files with heavy usage of names from the + # data sheet (e.g., AFE drivers) are checked seperately to not pollute + # general dictionaries. + - ./**/*.c|!./src/os/freertos/**/*|!./src/os/safertos/**/*|!./src/app/driver/afe/adi/**/*|!./tests/unit/app/driver/afe/adi/**/*|!./src/app/driver/afe/maxim/**/*|!./src/app/driver/afe/ltc/**/*|!./tests/unit/app/driver/afe/ltc/**/*|!./tests/unit/app/driver/afe/maxim/**/*|!./tools/vendor/**/*|!./tests/axivion/qualification-test/**/*|!./tests/axivion/compiler-errata/**/*|!./src/app/driver/sbc/fs8x_driver/* + - ./**/*.h|!./src/os/freertos/**/*|!./src/os/safertos/**/*|!./src/app/driver/afe/adi/**/*|!./tests/unit/app/driver/afe/adi/**/*|!./src/app/driver/afe/maxim/**/*|!./src/app/driver/afe/ltc/**/*|!./tests/unit/app/driver/afe/ltc/**/*|!./tests/unit/app/driver/afe/maxim/**/*|!./tools/vendor/**/*|!./tests/axivion/qualification-test/**/*|!./tests/axivion/compiler-errata/**/*|!./src/app/driver/sbc/fs8x_driver/*|!./src/app/driver/afe/nxp/mc33775a/vendor/MC33775A.h|!./tests/axivion/axivion_preinc.h + pipeline: + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: '0[xX][a-fA-F0-9]{2,8}' # hex numbers + close: '[u| |\)]?' + - open: 'kpk[A-Za-z0-9]*' # const pointer const + close: '[\(|\s]' + aspell: + lang: en + camel-case: 1 + dictionary: + wordlists: + - ./conf/spell/dicts/lan_c.txt + - ./conf/spell/dicts/names.txt + - ./conf/spell/dicts/funs-and-vars.txt + - ./conf/spell/dicts/abbreviations.txt + - ./conf/spell/dicts/words.txt + - ./conf/spell/dicts/units.txt + - ./conf/spell/dicts/other.txt + - ./conf/spell/dicts/driver-ti.txt + - ./conf/spell/dicts/prefixes.txt + - ./conf/spell/dicts/freertos.txt + - name: c-adi + group: code + sources: + - ./src/app/driver/afe/adi/**/*.c + - ./src/app/driver/afe/adi/**/*.h + - ./tests/unit/app/driver/afe/adi/**/*.c + - ./tests/unit/app/driver/afe/adi/**/*.h + pipeline: + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: '0[xX][a-fA-F0-9]{2,8}' # hex numbers + close: '[u| |\)]?' + - open: '(test_)?adi[_|-]ad[A-Za-z0-9_.-]*' # ADI files + close: '[:\s\)\"$"]' + - open: 'RunSm[A-Za-z0-9]*' + close: '[\(|\s]' + - open: 'kpk[A-Za-z0-9]*' # const pointer const + close: '[\(|\s]' + aspell: + lang: en + camel-case: 1 + dictionary: + wordlists: + - ./conf/spell/dicts/lan_c.txt + - ./conf/spell/dicts/names.txt + - ./conf/spell/dicts/funs-and-vars.txt + - ./conf/spell/dicts/abbreviations.txt + - ./conf/spell/dicts/words.txt + - ./conf/spell/dicts/units.txt + - ./conf/spell/dicts/other.txt + - ./conf/spell/dicts/driver-adi.txt + - ./conf/spell/dicts/prefixes.txt + - ./conf/spell/dicts/freertos.txt + - name: c-maxim + group: code + sources: + - ./src/app/driver/afe/maxim/**/*.c + - ./src/app/driver/afe/maxim/**/*.h + - ./tests/unit/app/driver/afe/maxim/**/*.c + - ./tests/unit/app/driver/afe/maxim/**/*.h + pipeline: + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: '0[xX][a-fA-F0-9]{2,8}' # hex numbers + close: '[u| |\)]?' + - open: '(test_)?adi[_|-]ad[A-Za-z0-9_.-]*' # ADI files + close: '[:\s\)\"$"]' + - open: 'RunSm[A-Za-z0-9]*' + close: '[\(|\s]' + - open: 'kpk[A-Za-z0-9]*' # const pointer const + close: '[\(|\s]' + aspell: + lang: en + camel-case: 1 + dictionary: + wordlists: + - ./conf/spell/dicts/lan_c.txt + - ./conf/spell/dicts/names.txt + - ./conf/spell/dicts/funs-and-vars.txt + - ./conf/spell/dicts/abbreviations.txt + - ./conf/spell/dicts/words.txt + - ./conf/spell/dicts/units.txt + - ./conf/spell/dicts/other.txt + - ./conf/spell/dicts/driver-adi.txt + - ./conf/spell/dicts/prefixes.txt + - ./conf/spell/dicts/freertos.txt + - name: c-ltc + group: code + sources: + - ./src/app/driver/afe/ltc/**/*.c + - ./src/app/driver/afe/ltc/**/*.h + - ./tests/unit/app/driver/afe/ltc/**/*.c + - ./tests/unit/app/driver/afe/ltc/**/*.h + pipeline: + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: '0[xX][a-fA-F0-9]{2,8}' # hex numbers + close: '[u| |\)]?' + - open: 'kpk[A-Za-z0-9]*' # const pointer const + close: '[\(|\s]' + aspell: + lang: en + camel-case: 1 + dictionary: + wordlists: + - ./conf/spell/dicts/lan_c.txt + - ./conf/spell/dicts/names.txt + - ./conf/spell/dicts/funs-and-vars.txt + - ./conf/spell/dicts/abbreviations.txt + - ./conf/spell/dicts/words.txt + - ./conf/spell/dicts/units.txt + - ./conf/spell/dicts/other.txt + - ./conf/spell/dicts/driver-ltc.txt + - ./conf/spell/dicts/prefixes.txt + - ./conf/spell/dicts/freertos.txt + - name: py + group: code + sources: + - ./**/*.py|!./src/os/freertos/**/*|!./tools/vendor/**/*|!./tests/axivion/qualification-test/**/*|!./tests/axivion/compiler-errata/**/*|!./tools/gui/fgui/misc/logo.py|!./tests/env/packages/**/*|!./tests/scripts/waf-core/**/* + - ./**/wscript|!./src/os/freertos/**/*|!./tools/vendor/**/*|!./tests/axivion/qualification-test/**/*|!./tests/axivion/compiler-errata/**/*|!./tests/scripts/waf-core/**/* + pipeline: + - pyspelling.filters.url: + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: '0[xX][a-fA-F0-9]{2,4}' + close: '[u| |\)]?' + - open: '(test_)?adi[_|-]ad[A-Za-z0-9_.-]*' + close: '[:\s\)\"$"]' + aspell: + lang: en + camel-case: 1 + dictionary: + wordlists: + - ./conf/spell/dicts/lan_py.txt + - ./conf/spell/dicts/names.txt + - ./conf/spell/dicts/abbreviations.txt + - ./conf/spell/dicts/words.txt + - ./conf/spell/dicts/units.txt + - ./conf/spell/dicts/other.txt + - ./conf/spell/dicts/prefixes.txt + - name: docs + group: text + pipeline: + - pyspelling.filters.url: + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: '0[xX][a-fA-F0-9]{2,4}' + close: '[u| |\)]?' + - open: '(test_)?adi[_|-]ad[A-Za-z0-9_.-]*' + close: '[:\s\)\"$"]' + sources: + - docs/**/*.rst + aspell: + lang: en + camel-case: 1 + dictionary: + wordlists: + - ./conf/spell/dicts/docs.txt + - ./conf/spell/dicts/names.txt + - ./conf/spell/dicts/abbreviations.txt + - ./conf/spell/dicts/words.txt + - ./conf/spell/dicts/units.txt + - ./conf/spell/dicts/other.txt + - ./conf/spell/dicts/prefixes.txt + - ./conf/spell/dicts/freertos.txt + - name: readme + group: text + pipeline: + - pyspelling.filters.url: + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: '0[xX][a-fA-F0-9]{2,4}' + close: '[u| |\)]?' + - open: '(test_)?adi[_|-]ad[A-Za-z0-9_.-]*' + close: '[:\s\)\"$"]' + sources: + - ./**/*.md|!./src/os/freertos/**/*|!./tools/vendor/**/*|!./tests/axivion/qualification-test/**/*|!./tests/axivion/compiler-errata/**/* + aspell: + lang: en + camel-case: 1 + dictionary: + wordlists: + - ./conf/spell/dicts/docs.txt + - ./conf/spell/dicts/names.txt + - ./conf/spell/dicts/abbreviations.txt + - ./conf/spell/dicts/words.txt + - ./conf/spell/dicts/units.txt + - ./conf/spell/dicts/other.txt + - ./conf/spell/dicts/prefixes.txt + - ./conf/spell/dicts/freertos.txt + - name: txt + group: text + pipeline: + - pyspelling.filters.url: + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: '0[xX][a-fA-F0-9]{2,4}' + close: '[u| |\)]?' + - open: '(test_)?adi[_|-]ad[A-Za-z0-9_.-]*' + close: '[:\s\)\"$"]' + sources: + - ./**/*.txt|!./src/os/freertos/**/*|!./tools/vendor/**/*|!./tests/axivion/qualification-test/**/*|!./tests/axivion/compiler-errata/**/*|!./conf/spell/dicts/*|!./docs/software/configuration/fstartup.c-check.txt|!./docs/macros.txt|!./docs/general/license-tables/license-packages-conda-env-spelling.txt + aspell: + lang: en + camel-case: 1 + dictionary: + wordlists: + - ./conf/spell/dicts/docs.txt + - ./conf/spell/dicts/names.txt + - ./conf/spell/dicts/abbreviations.txt + - ./conf/spell/dicts/words.txt + - ./conf/spell/dicts/units.txt + - ./conf/spell/dicts/other.txt + - ./conf/spell/dicts/prefixes.txt + - ./conf/spell/dicts/freertos.txt diff --git a/conf/tpl/c.c b/conf/tpl/c.c index 13b208b0..e193fbeb 100644 --- a/conf/tpl/c.c +++ b/conf/tpl/c.c @@ -43,8 +43,8 @@ * @file c.c * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SOME_GROUP * @prefix ABC * diff --git a/conf/tpl/c.h b/conf/tpl/c.h index ee3e028c..f7c0855c 100644 --- a/conf/tpl/c.h +++ b/conf/tpl/c.h @@ -43,8 +43,8 @@ * @file c.h * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SOME_GROUP * @prefix ABC * diff --git a/conf/tpl/test_c.c b/conf/tpl/test_c.c index a02abad0..aadcc41e 100644 --- a/conf/tpl/test_c.c +++ b/conf/tpl/test_c.c @@ -43,8 +43,8 @@ * @file test_c.c * @author foxBMS Team * @date 2020-08-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -55,7 +55,8 @@ /*========== Includes =======================================================*/ #include "unity.h" -TEST_FILE("c.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("c.c") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/conf/tpl/test_c.h b/conf/tpl/test_c.h index d86facfb..4442f080 100644 --- a/conf/tpl/test_c.h +++ b/conf/tpl/test_c.h @@ -43,8 +43,8 @@ * @file test_c.h * @author foxBMS Team * @date 2020-08-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,8 @@ /*========== Includes =======================================================*/ +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Macros and Definitions =========================================*/ #endif /* FOXBMS__TEST_C_H_ */ diff --git a/conf/unit/ceedling.cmd b/conf/unit/ceedling.cmd index d50de3a6..d19af4c9 100644 --- a/conf/unit/ceedling.cmd +++ b/conf/unit/ceedling.cmd @@ -35,4 +35,4 @@ @REM - "This product includes parts of foxBMS®" @REM - "This product is derived from foxBMS®" -ruby ..\..\tools\vendor\ceedling\bin\ceedling %* +@ruby ..\..\tools\vendor\ceedling\bin\ceedling %* diff --git a/conf/unit/ceedling.sh b/conf/unit/ceedling.sh new file mode 100644 index 00000000..439c736b --- /dev/null +++ b/conf/unit/ceedling.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +set -e + +SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +pushd $SCRIPTDIR +ruby ../../tools/vendor/ceedling/bin/ceedling $@ +popd diff --git a/conf/unit/project_posix.yml b/conf/unit/project_posix.yml new file mode 100644 index 00000000..ceb2913f --- /dev/null +++ b/conf/unit/project_posix.yml @@ -0,0 +1,192 @@ +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +--- +############################################################################## +# Important: # +# Paths must be given as seen from the build variant root directory # +############################################################################## + +:project: + :use_exceptions: TRUE + :use_test_preprocessor: TRUE + :use_mocks: TRUE + :use_auxiliary_dependencies: TRUE + :build_root: . + :test_file_prefix: test_ + :which_ceedling: ../../tools/vendor/ceedling + :ceedling_version: 0.32.0 + :default_tasks: + - test:all + :test_threads: 8 + :compile_threads: 8 + +:environment: [] + +:extension: + :executable: .out + +:paths: + :test: + - +:../../tests/unit/** + - -:../../tests/unit/support + :source: + - ../../src/app/** + - ../../src/opt/** + :include: + - +:./include/** + - +:./../../src/os/freertos/include + - +:./../../src/os/freertos/portable/ccs/arm_cortex-r5 + - +:./../../src/app/main/include + - +:./../../src/app/main/include/config + - +:./../../src/app/application/config + - +:./../../src/app/engine/config + - +:./../../src/app/engine/database + - +:./../../src/app/driver/mcu + - +:./../../src/app/task/os + :support: + - ../../tests/unit/support/** + +:flags: + :test: + :compile: + :*: + - -std=c11 + - -Wextra + - -Wall + - -pedantic + - -include test_ignore_list.h + - -Werror + +:defines: + :test: &config-test-defines + :*: &match-all-tests + - UNITY_UNIT_TEST + - FAS_ASSERT_LEVEL=2 + - UNITY_INCLUDE_EXEC_TIME + - FOXBMS_USES_FREERTOS=1 + - _POSIX_C_SOURCE=200809L + :test_adi_ades1830*: + - FOXBMS_AFE_DRIVER_ADI_ADES1830=1u + :preprocess: + <<: *config-test-defines + :*: + - *match-all-tests + - INC_FREERTOS_H + +:cmock: + :when_no_prototypes: :warn + :enforce_strict_ordering: TRUE + :mock_prefix: Mock + :weak: "" + :strippables: + [ + "(.FREERTOS_SYSTEM_CALL)", + "(.PRIVILEGED_FUNCTION)", + "(portDONT_DISCARD)", + "(?:TEST_LTC_DECLARE_GET\\s*\\(+.*?\\)+)", + "(?:TEST_LTC_DEFINE_GET\\s*\\(+.*?\\)+)", + ] + :includes: + - "FreeRTOSConfig.h" + - "FreeRTOS.h" + - "portmacro.h" + - "mpu_wrappers.h" + - "portable.h" + - "task.h" + - "queue.h" + - "semphr.h" + - "stream_buffer.h" + - "event_groups.h" + - "string.h" + :plugins: + - :ignore + - :callback + - :ignore_arg + - :return_thru_ptr + :treat_externs: :include + :treat_as: + uint8: HEX8 + uint16: HEX16 + uint32: UINT32 + int8: INT8 + bool: UINT8 + +#:tools: +# Ceedling defaults to using gcc for compiling, linking, etc. +# As [:tools] is blank, gcc will be used (so long as it's in your system path) +# See documentation to configure a given toolchain for use + +:tools_test_linker: + :arguments: + - -lm + - -flto +:tools_gcov_linker: + :arguments: + - -lm + - -flto +:gcov: + :utilities: + - gcovr + :reports: + - HtmlDetailed + - Text + - Cobertura + :gcovr: + :report_root: "../../" + :report_exclude: ".*vendor.*|.*build.*|.*test.*|.*tests.*|.*lib.*|.*Test.*|.*src.hal.*|.*src.os.*" + :exclude_directories: ".*tests.*|.*src.os.*|.*build.*|.*src.app.driver.sbc.fs8x_driver." + :sort_percentage: true + :sort_uncovered: false + :html_medium_threshold: 60 + :html_high_threshold: 85 + :print_summary: true + :threads: 8 + :keep: false + +:junit_tests_report: + :artifact_filename: report_junit.xml + +:plugins: + :load_paths: + - ../../tools/vendor/ceedling/plugins + :enabled: + - gcov + - stdout_pretty_tests_report + - module_generator + - xml_tests_report + - junit_tests_report diff --git a/conf/unit/project.yml b/conf/unit/project_win32.yml similarity index 82% rename from conf/unit/project.yml rename to conf/unit/project_win32.yml index f6a825ce..52d7cc1a 100644 --- a/conf/unit/project.yml +++ b/conf/unit/project_win32.yml @@ -49,9 +49,11 @@ :build_root: . :test_file_prefix: test_ :which_ceedling: ../../tools/vendor/ceedling - :ceedling_version: 0.31.1 + :ceedling_version: 0.32.0 :default_tasks: - test:all + :test_threads: 8 + :compile_threads: 8 :environment: [] @@ -67,23 +69,43 @@ - ../../src/opt/** :include: - +:./include/** - - +:../../src/** - - -:../../src/app/** - - -:../../src/opt/** + - +:./../../src/os/freertos/include + - +:./../../src/os/freertos/portable/ccs/arm_cortex-r5 + - +:./../../src/app/main/include + - +:./../../src/app/main/include/config + - +:./../../src/app/application/config + - +:./../../src/app/engine/config + - +:./../../src/app/engine/database + - +:./../../src/app/driver/mcu + - +:./../../src/app/task/os :support: - ../../tests/unit/support/** -:defines: - :common: &common_defines - - UNITY_UNIT_TEST - - FAS_ASSERT_LEVEL=2 - - UNITY_INCLUDE_EXEC_TIME - - FOXBMS_USES_FREERTOS=1 +:flags: :test: - - *common_defines - :test_preprocess: - - *common_defines - - INC_FREERTOS_H + :compile: + :*: + - -std=c11 + - -Wextra + - -Wall + - -pedantic + - -include test_ignore_list.h + - -Werror + +:defines: + :test: &config-test-defines + :*: &match-all-tests + - UNITY_UNIT_TEST + - FAS_ASSERT_LEVEL=2 + - UNITY_INCLUDE_EXEC_TIME + - FOXBMS_USES_FREERTOS=1 + :test_adi_ades1830*: + - FOXBMS_AFE_DRIVER_ADI_ADES1830=1u + :preprocess: + <<: *config-test-defines + :*: + - *match-all-tests + - INC_FREERTOS_H :cmock: :when_no_prototypes: :warn @@ -143,15 +165,6 @@ - HtmlDetailed - Text - Cobertura - :abort_on_uncovered: true - :uncovered_ignore_list: - - "../../src/app/driver/imd/bender/ir155/bender_ir155.c" - - "../../src/app/driver/imd/bender/iso165c/bender_iso165c.c" - - "../../src/app/driver/afe/nxp/mc33775a/vendor/uc_msg_t.c" - - "../../src/app/driver/sbc/fs8x_driver/sbc_fs8x.c" - - "../../src/app/driver/sbc/fs8x_driver/sbc_fs8x_communication.c" - - "../../src/app/main/main.c" - - "../../src/app/main/fstartup.c" :gcovr: :report_root: "../../" :report_exclude: ".*vendor.*|.*build.*|.*test.*|.*tests.*|.*lib.*|.*Test.*|.*src.hal.*|.*src.os.*" @@ -161,7 +174,7 @@ :html_medium_threshold: 60 :html_high_threshold: 85 :print_summary: true - :num_parallel_threads: 4 + :threads: 8 :keep: false :junit_tests_report: diff --git a/docs/conf.py b/docs/conf.py index 0766a5b4..c1f374fa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -131,6 +131,8 @@ linkcheck_ignore = [ r".*_static\/doxygen", + "https://docs.foxbms.org", + r"https:\/\/iisb-foxbms\.iisb\.fraunhofer\.de\/.*[\d|z]\/", # linkcheck can not handle the line highlighting "https://gitlab.com/ita1024/waf/-/blob/3536dfecf8061c6d99bac338837997c4862ee89b/waflib/TaskGen.py#L495-527", "https://gitlab.com/ita1024/waf/-/blob/3f8bb163290eb8fbfc3b26d61dd04aa5a6a29d4a/waf-light#L6-30", @@ -139,6 +141,7 @@ "../_images/battery-system-setup-pack.png", "../_images/battery-system-setup-bjb.png", "../_images/battery-system-setup-single-string.png", + "../_images/battery-system-precharging.png", ] html_theme_options = { diff --git a/docs/developer-manual/hardware-developer-manual.rst b/docs/developer-manual/hardware-developer-manual.rst index 2085debe..ac22090c 100644 --- a/docs/developer-manual/hardware-developer-manual.rst +++ b/docs/developer-manual/hardware-developer-manual.rst @@ -16,9 +16,10 @@ A design **MUST** have a name that clearly distinguishes it from other designs. The name **SHOULD** be constructed from the project acronym, the type or family of design and an identifier. -As an example the master board of a BMS in the project XMPL could be named -``xmpl-master``. If necessary an additional identifier could be added if -several similar designs exist. +As an example the master board of a BMS in the project **EXAMPLE** could be +named ``example-master``. +If necessary an additional identifier could be added if several similar designs +exist. Design and development process ------------------------------ @@ -31,7 +32,6 @@ changes are committed and that no design rule violations remain. Violations should only be waived or suppressed in justified cases. This justification **MUST** be noted in the waived rule. - .. _RELEASE_PROCESS: Release process @@ -49,7 +49,6 @@ The release process has the following steps: #. Store the release in a pre-defined location so that it can be found. #. Mark the released version in version control with a tag. - Modification process -------------------- @@ -63,7 +62,6 @@ be followed: #. Enter the hardware release process :numref:`RELEASE_PROCESS` with these changes. - Checklist for releases ---------------------- diff --git a/docs/developer-manual/preface.rst b/docs/developer-manual/preface.rst index 5a5edfe8..2b051f95 100644 --- a/docs/developer-manual/preface.rst +++ b/docs/developer-manual/preface.rst @@ -20,7 +20,6 @@ This document is separated into a :ref:`general style-guide`, a :ref:`software developer manual` and a :ref:`hardware developer manual`. - Terminology ----------- @@ -33,7 +32,6 @@ and only when, they appear in all capitals and bold, as shown here. This terminology is used throughout all technical documents associated with |foxbms|. - Version control --------------- diff --git a/docs/developer-manual/public-release-process.rst b/docs/developer-manual/public-release-process.rst index d03d933e..cd78f4b1 100644 --- a/docs/developer-manual/public-release-process.rst +++ b/docs/developer-manual/public-release-process.rst @@ -85,7 +85,6 @@ Defining release status of repository C:\release-bot\foxbms-2>git push origin master --follow-tags - Creation of the release branch ++++++++++++++++++++++++++++++ @@ -119,7 +118,6 @@ Creation of the release branch C:\release-bot\foxbms-2>git clean -xdf - Publication of the release branch +++++++++++++++++++++++++++++++++ diff --git a/docs/developer-manual/software/software-tools.rst b/docs/developer-manual/software/software-tools.rst index bc8d777d..0dfd5acb 100644 --- a/docs/developer-manual/software/software-tools.rst +++ b/docs/developer-manual/software/software-tools.rst @@ -54,7 +54,7 @@ The following tools are shown in :numref:`mapping-of-third-party-tools`. +-----------------+-------------------------+-------------+----------------------------------------+ | VS Code | text editor | T1 | | +-----------------+-------------------------+-------------+----------------------------------------+ - | waf | build automation system | T3 | controls build process; generates | + | Waf | build automation system | T3 | controls build process; generates | | | | | version dependent code | +-----------------+-------------------------+-------------+----------------------------------------+ | Axivion Suite | static program | T2 | | diff --git a/docs/developer-manual/style-guide/examples/c-004.c b/docs/developer-manual/style-guide/examples/c-004.c index 51af33e6..c9e93be8 100644 --- a/docs/developer-manual/style-guide/examples/c-004.c +++ b/docs/developer-manual/style-guide/examples/c-004.c @@ -43,8 +43,8 @@ * @file c-004.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-005.c b/docs/developer-manual/style-guide/examples/c-005.c index c9dba562..a018c523 100644 --- a/docs/developer-manual/style-guide/examples/c-005.c +++ b/docs/developer-manual/style-guide/examples/c-005.c @@ -43,8 +43,8 @@ * @file c-005.c * @author foxBMS Team * @date 2023-01-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-005.h b/docs/developer-manual/style-guide/examples/c-005.h index 298d9e26..a3259e44 100644 --- a/docs/developer-manual/style-guide/examples/c-005.h +++ b/docs/developer-manual/style-guide/examples/c-005.h @@ -43,8 +43,8 @@ * @file c-005.h * @author foxBMS Team * @date 2023-01-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-006-source.c b/docs/developer-manual/style-guide/examples/c-006-source.c index 2bbdadc4..cde625e2 100644 --- a/docs/developer-manual/style-guide/examples/c-006-source.c +++ b/docs/developer-manual/style-guide/examples/c-006-source.c @@ -43,8 +43,8 @@ * @file c-006-source.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-006-source.h b/docs/developer-manual/style-guide/examples/c-006-source.h index 761fa024..ebcedf4a 100644 --- a/docs/developer-manual/style-guide/examples/c-006-source.h +++ b/docs/developer-manual/style-guide/examples/c-006-source.h @@ -43,8 +43,8 @@ * @file c-006-source.h * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-006-test.c b/docs/developer-manual/style-guide/examples/c-006-test.c index 32044c8a..2e98c8c8 100644 --- a/docs/developer-manual/style-guide/examples/c-006-test.c +++ b/docs/developer-manual/style-guide/examples/c-006-test.c @@ -43,8 +43,8 @@ * @file c-006-test.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * @@ -58,6 +58,8 @@ /*========== Includes =======================================================*/ +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/docs/developer-manual/style-guide/examples/c-006-test.h b/docs/developer-manual/style-guide/examples/c-006-test.h index 7fb54f49..ed049e9e 100644 --- a/docs/developer-manual/style-guide/examples/c-006-test.h +++ b/docs/developer-manual/style-guide/examples/c-006-test.h @@ -43,8 +43,8 @@ * @file c-006-test.h * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * @@ -58,6 +58,8 @@ /*========== Includes =======================================================*/ +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Macros and Definitions =========================================*/ #endif /* FOXBMS__C_006_TEST_H_ */ diff --git a/docs/developer-manual/style-guide/examples/c-007_abc.c b/docs/developer-manual/style-guide/examples/c-007_abc.c index 928909e1..50fb5428 100644 --- a/docs/developer-manual/style-guide/examples/c-007_abc.c +++ b/docs/developer-manual/style-guide/examples/c-007_abc.c @@ -43,8 +43,8 @@ * @file c-007_abc.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-007_abc.h b/docs/developer-manual/style-guide/examples/c-007_abc.h index 1c6521f8..f046c92d 100644 --- a/docs/developer-manual/style-guide/examples/c-007_abc.h +++ b/docs/developer-manual/style-guide/examples/c-007_abc.h @@ -43,8 +43,8 @@ * @file c-007_abc.h * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-007_abc_cfg.c b/docs/developer-manual/style-guide/examples/c-007_abc_cfg.c index 432476c2..996162c2 100644 --- a/docs/developer-manual/style-guide/examples/c-007_abc_cfg.c +++ b/docs/developer-manual/style-guide/examples/c-007_abc_cfg.c @@ -43,8 +43,8 @@ * @file c-007_abc_cfg.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-007_abc_cfg.h b/docs/developer-manual/style-guide/examples/c-007_abc_cfg.h index 20dc29e4..21f3d92c 100644 --- a/docs/developer-manual/style-guide/examples/c-007_abc_cfg.h +++ b/docs/developer-manual/style-guide/examples/c-007_abc_cfg.h @@ -43,8 +43,8 @@ * @file c-007_abc_cfg.h * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-008.c b/docs/developer-manual/style-guide/examples/c-008.c index 77e983f1..b7c3e58d 100644 --- a/docs/developer-manual/style-guide/examples/c-008.c +++ b/docs/developer-manual/style-guide/examples/c-008.c @@ -43,8 +43,8 @@ * @file c-008.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-008.h b/docs/developer-manual/style-guide/examples/c-008.h index ada5895d..5c4a50c5 100644 --- a/docs/developer-manual/style-guide/examples/c-008.h +++ b/docs/developer-manual/style-guide/examples/c-008.h @@ -43,8 +43,8 @@ * @file c-008.h * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-009.c b/docs/developer-manual/style-guide/examples/c-009.c index 7b3b61de..1012db32 100644 --- a/docs/developer-manual/style-guide/examples/c-009.c +++ b/docs/developer-manual/style-guide/examples/c-009.c @@ -43,8 +43,8 @@ * @file c-009.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-011.c b/docs/developer-manual/style-guide/examples/c-011.c index d686e833..bfe48472 100644 --- a/docs/developer-manual/style-guide/examples/c-011.c +++ b/docs/developer-manual/style-guide/examples/c-011.c @@ -43,8 +43,8 @@ * @file c-011.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-011.h b/docs/developer-manual/style-guide/examples/c-011.h index 51288d39..91a6eb0f 100644 --- a/docs/developer-manual/style-guide/examples/c-011.h +++ b/docs/developer-manual/style-guide/examples/c-011.h @@ -43,8 +43,8 @@ * @file c-011.h * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-012.c b/docs/developer-manual/style-guide/examples/c-012.c index 699f5c65..f02f59d3 100644 --- a/docs/developer-manual/style-guide/examples/c-012.c +++ b/docs/developer-manual/style-guide/examples/c-012.c @@ -43,8 +43,8 @@ * @file c-012.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-013.c b/docs/developer-manual/style-guide/examples/c-013.c index 6dd302ff..34e5ee5f 100644 --- a/docs/developer-manual/style-guide/examples/c-013.c +++ b/docs/developer-manual/style-guide/examples/c-013.c @@ -43,8 +43,8 @@ * @file c-013.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-013.h b/docs/developer-manual/style-guide/examples/c-013.h index a0fcb0ac..3825a653 100644 --- a/docs/developer-manual/style-guide/examples/c-013.h +++ b/docs/developer-manual/style-guide/examples/c-013.h @@ -43,8 +43,8 @@ * @file c-013.h * @author foxBMS Team * @date 2023-01-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix NONE * diff --git a/docs/developer-manual/style-guide/examples/c-015.c b/docs/developer-manual/style-guide/examples/c-015.c index 5dba58e0..51871bf2 100644 --- a/docs/developer-manual/style-guide/examples/c-015.c +++ b/docs/developer-manual/style-guide/examples/c-015.c @@ -43,8 +43,8 @@ * @file c-015.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-015.h b/docs/developer-manual/style-guide/examples/c-015.h index fbfbbd34..e768be2e 100644 --- a/docs/developer-manual/style-guide/examples/c-015.h +++ b/docs/developer-manual/style-guide/examples/c-015.h @@ -46,8 +46,8 @@ * @file c-015.h * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-016.c b/docs/developer-manual/style-guide/examples/c-016.c index 8f6794a2..36a890bc 100644 --- a/docs/developer-manual/style-guide/examples/c-016.c +++ b/docs/developer-manual/style-guide/examples/c-016.c @@ -43,8 +43,8 @@ * @file c-016.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-017.c b/docs/developer-manual/style-guide/examples/c-017.c index fdd57a70..69a31bca 100644 --- a/docs/developer-manual/style-guide/examples/c-017.c +++ b/docs/developer-manual/style-guide/examples/c-017.c @@ -43,8 +43,8 @@ * @file c-017.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-018.c b/docs/developer-manual/style-guide/examples/c-018.c index 6d3913f5..fa8f81e3 100644 --- a/docs/developer-manual/style-guide/examples/c-018.c +++ b/docs/developer-manual/style-guide/examples/c-018.c @@ -43,8 +43,8 @@ * @file c-018.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-019.c b/docs/developer-manual/style-guide/examples/c-019.c index af6de3af..7a88b566 100644 --- a/docs/developer-manual/style-guide/examples/c-019.c +++ b/docs/developer-manual/style-guide/examples/c-019.c @@ -43,8 +43,8 @@ * @file c-019.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * @@ -90,7 +90,7 @@ uint8_t abc_myArrayA[] = {1, 2, 3}; /* Array has type uint8_t[3] and holds 1,2, uint8_t abc_myArrayC[5] = {0}; /* Array has type uint8_t[5] and holds 0,0,0,0,0 */ uint8_t abc_myArrayD[4][3] = { - /* array of 4 arrays of 3 uint8_t's each (4x3 matrix) */ + /* array of 4 arrays of 3 uint8_t each (4x3 matrix) */ {1}, /* row 0 initialized to {1, 0, 0} */ {0, 1}, /* row 1 initialized to {0, 1, 0} */ {[2] = 1}, /* row 2 initialized to {0, 0, 1} */ diff --git a/docs/developer-manual/style-guide/examples/c-020.c b/docs/developer-manual/style-guide/examples/c-020.c index 6d3dec62..14b09f8f 100644 --- a/docs/developer-manual/style-guide/examples/c-020.c +++ b/docs/developer-manual/style-guide/examples/c-020.c @@ -43,8 +43,8 @@ * @file c-020.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-021.c b/docs/developer-manual/style-guide/examples/c-021.c index debbd5c1..3aeeb277 100644 --- a/docs/developer-manual/style-guide/examples/c-021.c +++ b/docs/developer-manual/style-guide/examples/c-021.c @@ -43,8 +43,8 @@ * @file c-021.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-022.c b/docs/developer-manual/style-guide/examples/c-022.c index 165c0776..de0aa2c4 100644 --- a/docs/developer-manual/style-guide/examples/c-022.c +++ b/docs/developer-manual/style-guide/examples/c-022.c @@ -43,8 +43,8 @@ * @file c-022.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * @@ -61,7 +61,7 @@ /** Symbolic names for battery system state */ typedef struct { uint16_t year; /*!< year */ - uint8_t month; /*!< month (1: january ... 12: december) */ + uint8_t month; /*!< month (1: January ... 12: December) */ uint8_t day; /*!< day of the month */ } ABC_DATE_s; diff --git a/docs/developer-manual/style-guide/examples/c-023.c b/docs/developer-manual/style-guide/examples/c-023.c index e3397a8d..9fedd147 100644 --- a/docs/developer-manual/style-guide/examples/c-023.c +++ b/docs/developer-manual/style-guide/examples/c-023.c @@ -43,8 +43,8 @@ * @file c-023.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-024.c b/docs/developer-manual/style-guide/examples/c-024.c index 1c34e184..970d0304 100644 --- a/docs/developer-manual/style-guide/examples/c-024.c +++ b/docs/developer-manual/style-guide/examples/c-024.c @@ -43,8 +43,8 @@ * @file c-024.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * @@ -75,7 +75,7 @@ static void ABC_CallTheCallback(void); static uint32_t ABC_BuildSum(uint32_t varA, uint32_t varB); /* Function prototype */ /* local variable of type CALLBACK_FUNCTION_POINTER_t - The variable can not be initalized in the section where all other static + The variable can not be initialized in the section where all other static variables are introduced, since the function is not known at that time. */ static ABC_CALLBACK_FUNCTION_POINTER_t abc_callback = &ABC_BuildSum; diff --git a/docs/developer-manual/style-guide/examples/c-025.c b/docs/developer-manual/style-guide/examples/c-025.c index 16a37807..a09dcaa0 100644 --- a/docs/developer-manual/style-guide/examples/c-025.c +++ b/docs/developer-manual/style-guide/examples/c-025.c @@ -43,8 +43,8 @@ * @file c-025.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-026.c b/docs/developer-manual/style-guide/examples/c-026.c index e3801f7b..d342530e 100644 --- a/docs/developer-manual/style-guide/examples/c-026.c +++ b/docs/developer-manual/style-guide/examples/c-026.c @@ -43,8 +43,8 @@ * @file c-026.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-027.c b/docs/developer-manual/style-guide/examples/c-027.c index 75ab25a6..d68de1d0 100644 --- a/docs/developer-manual/style-guide/examples/c-027.c +++ b/docs/developer-manual/style-guide/examples/c-027.c @@ -43,8 +43,8 @@ * @file c-027.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/examples/c-028-battery-defines.c b/docs/developer-manual/style-guide/examples/c-028-battery-defines.c index cb7cc8e9..7648548f 100644 --- a/docs/developer-manual/style-guide/examples/c-028-battery-defines.c +++ b/docs/developer-manual/style-guide/examples/c-028-battery-defines.c @@ -43,8 +43,8 @@ * @file c-028-battery-defines.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * @@ -75,7 +75,7 @@ static void C28_BatteriesLoop(void) { /* string related code */ for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { /* module related code */ - for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { /* cell related code */ } } diff --git a/docs/developer-manual/style-guide/examples/c-028.c b/docs/developer-manual/style-guide/examples/c-028.c index 7ce573a3..22722992 100644 --- a/docs/developer-manual/style-guide/examples/c-028.c +++ b/docs/developer-manual/style-guide/examples/c-028.c @@ -43,8 +43,8 @@ * @file c-028.c * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GUIDELINES * @prefix ABC * diff --git a/docs/developer-manual/style-guide/guidelines_batch_shell.rst b/docs/developer-manual/style-guide/guidelines_batch_shell.rst index 74dc0f55..3d7abce3 100644 --- a/docs/developer-manual/style-guide/guidelines_batch_shell.rst +++ b/docs/developer-manual/style-guide/guidelines_batch_shell.rst @@ -92,7 +92,6 @@ Header (``SHELL:002``) :caption: File header for shell scripts. :name: file-header-shell - File Templates -------------- diff --git a/docs/developer-manual/style-guide/guidelines_c.rst b/docs/developer-manual/style-guide/guidelines_c.rst index 9a761817..3ddad72b 100644 --- a/docs/developer-manual/style-guide/guidelines_c.rst +++ b/docs/developer-manual/style-guide/guidelines_c.rst @@ -9,7 +9,7 @@ C Coding Guidelines These coding guidelines **MUST** be applied to all ``C`` source and header files. -The source files **MUST** be successfully checked by running the waf command +The source files **MUST** be successfully checked by running the Waf command ``check_guidelines`` before files can be merged into the master branch of the repository. @@ -80,12 +80,12 @@ Header (``C:002``) :caption: File header for all ``.c`` and ``.h`` files. :name: file-header-c-and-h -.. _rule_c_linelength: +.. _rule_c_line_length: -Linelength (``C:003``) ----------------------- +Line length (``C:003``) +----------------------- -.. admonition:: Linelength rules +.. admonition:: Line length rules - Each line of text in your code **SHOULD** be at most 120 characters long. A line **MAY** exceed 120 characters if it is @@ -107,7 +107,6 @@ Linelength (``C:003``) or - a raw-string literal with content that exceeds 80 characters. - .. _rule_c_file_level_doxygen: File level doxygen (``C:004``) @@ -283,7 +282,6 @@ They distinguish if the software module provides configuration files or not. #. A blank line #. All other required headers except Mocks - :numref:`includes-c-007_abc_cfg-h`, :numref:`includes-c-007_abc_cfg-c`, :numref:`includes-c-007_abc-h` and :numref:`includes-c-007_abc-c` show how includes **MUST** be added. @@ -306,7 +304,7 @@ includes **MUST** be added. :language: C :lines: 60-63 :linenos: - :caption: Include oder for ``c-007_abc.h`` + :caption: Include order for ``c-007_abc.h`` :name: includes-c-007_abc-h .. literalinclude:: ./examples/c-007_abc.c @@ -541,7 +539,7 @@ Function parameter checking (``C:015``) - If no assertion can be made for the parameter (e.g., if the parameter intentionally accepts all possible values), the parameter **MUST** be marked like this at the start of the function context: - ``/* AXIVION Routine Generic-MissingParameterAssert: *ENTITYNAME*: *RATIONALE* */``. + ``/* AXIVION Routine Generic-MissingParameterAssert: *ENTITY_NAME*: *RATIONALE* */``. Parameter checking is shown in :numref:`function-input-check`. @@ -614,7 +612,14 @@ Pointer rules (``C:018``) - Variables used for pointers **MUST** be prefixed with a leading ``p`` in the case of a pointer to a variable and ``fp`` in the case of a function pointer, followed by camel Case. - When declaring a pointer variable or argument, the asterisk **MUST** be + - The const rules also still apply to pointers + (:ref:`rule_c_constant_names`), i.e., + + - for a const pointer the prefix is ``kp``, + - for a pointer to a const the prefix is ``pk``, and + - for a const pointer to a const the prefix is ``kpk``. + + - When declaring a pointer variable or argument, the asterisk **MUST** be placed adjacent to the variable name. - As function-pointer syntax can get complicated and lead to errors, a function pointer **MUST** use a typedef. @@ -648,7 +653,6 @@ Variable initialization (``C:019``) - Pointers **MUST** be initialized with ``NULL_PTR`` if no other valid initialization is possible. - .. _table-init-rules: .. table:: Variable initialization suffixes @@ -711,7 +715,6 @@ Floating-point values (``C:021``) - ``float`` types **SHOULD** be used wherever possible as the float operations are performed in hardware while double operations are not. - .. _table-floating-point-init-rules: .. table:: Floating-point literal initialization suffixes @@ -898,7 +901,6 @@ loop Statements (``C:028``) :linenos: :caption: Correct usage of spaces and parentheses in loop statements. - There are three defines that are typically looped over: the number of strings (``BS_NR_OF_STRINGS``), the number of modules (``BS_NR_OF_MODULES_PER_STRING``) and the number of batteries per module (``BS_NR_OF_CELL_BLOCKS_PER_MODULE``). @@ -911,15 +913,17 @@ These loops **MUST** follow the pattern as shown in :name: special-counter-variables :widths: grid - +-------------------------------------+-------------------+ - | Define | Counter variable | - +=====================================+===================+ - | ``BS_NR_OF_STRINGS`` | ``s`` | - +-------------------------------------+-------------------+ - | ``BS_NR_OF_MODULES_PER_STRING`` | ``m`` | - +-------------------------------------+-------------------+ - | ``BS_NR_OF_CELL_BLOCKS_PER_MODULE`` | ``c`` | - +-------------------------------------+-------------------+ + +--------------------------------------+-------------------+ + | Define | Counter variable | + +======================================+===================+ + | ``BS_NR_OF_STRINGS`` | ``s`` | + +--------------------------------------+-------------------+ + | ``BS_NR_OF_MODULES_PER_STRING`` | ``m`` | + +--------------------------------------+-------------------+ + | ``BS_NR_OF_CELL_BLOCKS_PER_MODULE`` | ``cb`` | + +--------------------------------------+-------------------+ + | ``BS_NR_OF_TEMP_SENSORS_PER_MODULE`` | ``ts`` | + +--------------------------------------+-------------------+ .. literalinclude:: ./examples/c-028-battery-defines.c :language: C @@ -968,6 +972,14 @@ State machines (``C:032``) If a driver (or similar) requires to be implemented in a state machine there are some hints found in :ref:`HOW_TO_WRITE_STATE_MACHINES`. +.. _rule_c_unit_testing_framework_directives: + +Unit Testing Framework Directives (``C:033``) +--------------------------------------------- + +If a driver (or similar) requires to be implemented in a state machine there +are some hints found in :ref:`HOW_TO_WRITE_STATE_MACHINES`. + File Templates -------------- diff --git a/docs/developer-manual/style-guide/guidelines_general.rst b/docs/developer-manual/style-guide/guidelines_general.rst index 15570571..d6e497a8 100644 --- a/docs/developer-manual/style-guide/guidelines_general.rst +++ b/docs/developer-manual/style-guide/guidelines_general.rst @@ -16,7 +16,6 @@ General Rules xBB xBF - The following rules generally apply and follow the naming schema ``GENERAL:``. @@ -130,7 +129,7 @@ Further General Rules would write in English without internal spaces. This includes abbreviations and acronyms; e.g., for "camel case" or "Pascal case," in which the first letter of each word is capitalized, use a name like - ``StartRpc()``, not ``StartRPC()``. + ``StartAbc()``, not ``StartABC()``. - Non-ASCII characters should be rare, and **MUST** use ``UTF-8`` encoding. You **SHOULD NOT** hard-code user-facing text in source code, even English, so use of non-ASCII characters should be rare. However, in certain cases it is diff --git a/docs/developer-manual/style-guide/guidelines_overview.rst b/docs/developer-manual/style-guide/guidelines_overview.rst index e49c6d72..8ce9f2e0 100644 --- a/docs/developer-manual/style-guide/guidelines_overview.rst +++ b/docs/developer-manual/style-guide/guidelines_overview.rst @@ -9,157 +9,42 @@ Table of Rules General ------- -+-------------+--------------------------------------------+-----------------+ -| Rule | Link | Automated Check | -+-------------+--------------------------------------------+-----------------+ -| GENERAL:001 | :ref:`rule_general_filenames` | Yes | -+-------------+--------------------------------------------+-----------------+ -| GENERAL:002 | :ref:`rule_general_filename_uniqueness` | Yes | -+-------------+--------------------------------------------+-----------------+ -| GENERAL:003 | :ref:`rule_general_text_file_encoding` | Yes | -+-------------+--------------------------------------------+-----------------+ -| GENERAL:004 | :ref:`rule_general_eof` | Yes | -+-------------+--------------------------------------------+-----------------+ -| GENERAL:005 | :ref:`rule_general_no_trailing_whitespace` | Yes | -+-------------+--------------------------------------------+-----------------+ -| GENERAL:006 | :ref:`rule_general_indentation` | Yes | -+-------------+--------------------------------------------+-----------------+ +.. csv-table:: + :delim: ; + :file: ./guidelines_overview_general.csv C-Rules ------- -+-------------+----------------------------------------------+-----------------+ -| Rule | Link | Automated Check | -+-------------+----------------------------------------------+-----------------+ -| C:001 | :ref:`rule_c_filenames` | No | -+-------------+----------------------------------------------+-----------------+ -| C:002 | :ref:`rule_c_header` | Yes | -+-------------+----------------------------------------------+-----------------+ -| C:003 | :ref:`rule_c_linelength` | No | -+-------------+----------------------------------------------+-----------------+ -| C:004 | :ref:`rule_c_file_level_doxygen` | Yes | -+-------------+----------------------------------------------+-----------------+ -| C:005 | :ref:`rule_c_include_guard` | Yes | -+-------------+----------------------------------------------+-----------------+ -| C:006 | :ref:`rule_c_sections` | Yes | -+-------------+----------------------------------------------+-----------------+ -| C:007 | :ref:`rule_c_includes` | No | -+-------------+----------------------------------------------+-----------------+ -| C:008 | :ref:`rule_c_scoping` | No | -+-------------+----------------------------------------------+-----------------+ -| C:009 | :ref:`rule_c_function_names` | No | -+-------------+----------------------------------------------+-----------------+ -| C:010 | :ref:`rule_c_function_scopes` | No | -+-------------+----------------------------------------------+-----------------+ -| C:011 | :ref:`rule_c_function_doxygen_documentation` | No | -+-------------+----------------------------------------------+-----------------+ -| C:012 | :ref:`rule_c_function_return_value` | No | -+-------------+----------------------------------------------+-----------------+ -| C:013 | :ref:`rule_c_function_calls` | No | -+-------------+----------------------------------------------+-----------------+ -| C:014 | :ref:`rule_c_additional_function_rules` | No | -+-------------+----------------------------------------------+-----------------+ -| C:015 | :ref:`rule_c_function_parameter_checking` | No | -+-------------+----------------------------------------------+-----------------+ -| C:016 | :ref:`rule_c_variable_names` | No | -+-------------+----------------------------------------------+-----------------+ -| C:017 | :ref:`rule_c_constant_names` | No | -+-------------+----------------------------------------------+-----------------+ -| C:018 | :ref:`rule_c_pointer_rules` | No | -+-------------+----------------------------------------------+-----------------+ -| C:019 | :ref:`rule_c_variable_initialization` | No | -+-------------+----------------------------------------------+-----------------+ -| C:020 | :ref:`rule_c_hexadecimal` | No | -+-------------+----------------------------------------------+-----------------+ -| C:021 | :ref:`rule_c_floating_point` | No | -+-------------+----------------------------------------------+-----------------+ -| C:022 | :ref:`rule_c_structs` | No | -+-------------+----------------------------------------------+-----------------+ -| C:023 | :ref:`rule_c_enums` | No | -+-------------+----------------------------------------------+-----------------+ -| C:024 | :ref:`rule_c_typedefs` | No | -+-------------+----------------------------------------------+-----------------+ -| C:025 | :ref:`rule_c_macros` | No | -+-------------+----------------------------------------------+-----------------+ -| C:026 | :ref:`rule_c_conditionals` | No | -+-------------+----------------------------------------------+-----------------+ -| C:027 | :ref:`rule_c_switch` | No | -+-------------+----------------------------------------------+-----------------+ -| C:028 | :ref:`rule_c_loop` | No | -+-------------+----------------------------------------------+-----------------+ -| C:029 | :ref:`rule_c_comment_style` | Yes | -+-------------+----------------------------------------------+-----------------+ -| C:030 | :ref:`rule_c_hints` | NO | -+-------------+----------------------------------------------+-----------------+ -| C:031 | :ref:`rule_c_formatting` | NO | -+-------------+----------------------------------------------+-----------------+ +.. csv-table:: + :delim: ; + :file: ./guidelines_overview_c.csv Python-Rules ------------ -+-------------+----------------------------------------+-----------------+ -| Rule | Link | Automated Check | -+-------------+----------------------------------------+-----------------+ -| PYTHON:001 | :ref:`rule_python_filenames` | No | -+-------------+----------------------------------------+-----------------+ -| PYTHON:002 | :ref:`rule_python_header` | Yes | -+-------------+----------------------------------------+-----------------+ -| PYTHON:003 | :ref:`rule_python_syntax` | No | -+-------------+----------------------------------------+-----------------+ -| PYTHON:004 | :ref:`rule_python_formatting` | No | -+-------------+----------------------------------------+-----------------+ -| PYTHON:005 | :ref:`rule_python_spa` | No | -+-------------+----------------------------------------+-----------------+ -| PYTHON:006 | :ref:`rule_no_platform_specific_code` | No | -+-------------+----------------------------------------+-----------------+ -| PYTHON:007 | :ref:`rule_python_wscript_rules` | No | -+-------------+----------------------------------------+-----------------+ - +.. csv-table:: + :delim: ; + :file: ./guidelines_overview_python.csv reStructuredText-Rules ---------------------- -+-------------+------------------------------------+-----------------+ -| Rule | Link | Automated Check | -+-------------+------------------------------------+-----------------+ -| RST:001 | :ref:`rule_rst_filenames` | No | -+-------------+------------------------------------+-----------------+ -| RST:002 | :ref:`rule_rst_linelength` | No | -+-------------+------------------------------------+-----------------+ -| RST:003 | :ref:`rule_rst_include` | Yes | -+-------------+------------------------------------+-----------------+ -| RST:004 | :ref:`rule_rst_links` | Yes | -+-------------+------------------------------------+-----------------+ -| RST:005 | :ref:`rule_rst_headings` | Yes | -+-------------+------------------------------------+-----------------+ -| RST:006 | :ref:`rule_rst_orphan` | Yes | -+-------------+------------------------------------+-----------------+ -| RST:007 | :ref:`rule_rst_sentence` | No | -+-------------+------------------------------------+-----------------+ +.. csv-table:: + :delim: ; + :file: ./guidelines_overview_rst.csv Batch and Shell-Rules --------------------- -+-------------+----------------------------------------+-----------------+ -| Rule | Link | Automated Check | -+-------------+----------------------------------------+-----------------+ -| BATCH:001 | :ref:`rule_batch_filenames` | No | -+-------------+----------------------------------------+-----------------+ -| BATCH:002 | :ref:`rule_batch_header` | Yes | -+-------------+----------------------------------------+-----------------+ -| SHELL:001 | :ref:`rule_shell_filenames` | No | -+-------------+----------------------------------------+-----------------+ -| SHELL:002 | :ref:`rule_shell_header` | Yes | -+-------------+----------------------------------------+-----------------+ +.. csv-table:: + :delim: ; + :file: ./guidelines_overview_sh.csv YAML-Rules ---------- -+-------------+----------------------------------------+-----------------+ -| Rule | Link | automated check | -+-------------+----------------------------------------+-----------------+ -| YAML:001 | :ref:`rule_yaml_filenames` | No | -+-------------+----------------------------------------+-----------------+ -| YAML:002 | :ref:`rule_yaml_header` | Yes | -+-------------+----------------------------------------+-----------------+ +.. csv-table:: + :delim: ; + :file: ./guidelines_overview_yaml.csv diff --git a/docs/developer-manual/style-guide/guidelines_overview_c.csv b/docs/developer-manual/style-guide/guidelines_overview_c.csv new file mode 100644 index 00000000..f1b04553 --- /dev/null +++ b/docs/developer-manual/style-guide/guidelines_overview_c.csv @@ -0,0 +1,35 @@ + +Rule ; Link ; Automated Check +C:001 ; :ref:`rule_c_filenames` ; No +C:002 ; :ref:`rule_c_header` ; Yes +C:003 ; :ref:`rule_c_line_length` ; No +C:004 ; :ref:`rule_c_file_level_doxygen` ; Yes +C:005 ; :ref:`rule_c_include_guard` ; Yes +C:006 ; :ref:`rule_c_sections` ; Yes +C:007 ; :ref:`rule_c_includes` ; No +C:008 ; :ref:`rule_c_scoping` ; No +C:009 ; :ref:`rule_c_function_names` ; No +C:010 ; :ref:`rule_c_function_scopes` ; No +C:011 ; :ref:`rule_c_function_doxygen_documentation` ; No +C:012 ; :ref:`rule_c_function_return_value` ; No +C:013 ; :ref:`rule_c_function_calls` ; No +C:014 ; :ref:`rule_c_additional_function_rules` ; No +C:015 ; :ref:`rule_c_function_parameter_checking` ; No +C:016 ; :ref:`rule_c_variable_names` ; No +C:017 ; :ref:`rule_c_constant_names` ; No +C:018 ; :ref:`rule_c_pointer_rules` ; No +C:019 ; :ref:`rule_c_variable_initialization` ; No +C:020 ; :ref:`rule_c_hexadecimal` ; No +C:021 ; :ref:`rule_c_floating_point` ; No +C:022 ; :ref:`rule_c_structs` ; No +C:023 ; :ref:`rule_c_enums` ; No +C:024 ; :ref:`rule_c_typedefs` ; No +C:025 ; :ref:`rule_c_macros` ; No +C:026 ; :ref:`rule_c_conditionals` ; No +C:027 ; :ref:`rule_c_switch` ; No +C:028 ; :ref:`rule_c_loop` ; No +C:029 ; :ref:`rule_c_comment_style` ; Yes +C:030 ; :ref:`rule_c_hints` ; No +C:031 ; :ref:`rule_c_formatting` ; No +C:032 ; :ref:`rule_c_state_machines` ; No +C:033 ; :ref:`rule_c_unit_testing_framework_directives` ; No diff --git a/docs/developer-manual/style-guide/guidelines_overview_general.csv b/docs/developer-manual/style-guide/guidelines_overview_general.csv new file mode 100644 index 00000000..5f35c5dd --- /dev/null +++ b/docs/developer-manual/style-guide/guidelines_overview_general.csv @@ -0,0 +1,7 @@ +Rule ; Link ; Automated Check +GENERAL:001 ; :ref:`rule_general_filenames` ; Yes +GENERAL:002 ; :ref:`rule_general_filename_uniqueness` ; Yes +GENERAL:003 ; :ref:`rule_general_text_file_encoding` ; Yes +GENERAL:004 ; :ref:`rule_general_eof` ; Yes +GENERAL:005 ; :ref:`rule_general_no_trailing_whitespace` ; Yes +GENERAL:006 ; :ref:`rule_general_indentation` ; Yes diff --git a/docs/developer-manual/style-guide/guidelines_overview_python.csv b/docs/developer-manual/style-guide/guidelines_overview_python.csv new file mode 100644 index 00000000..dc25db99 --- /dev/null +++ b/docs/developer-manual/style-guide/guidelines_overview_python.csv @@ -0,0 +1,9 @@ + +Rule ; Link ; Automated Check +PYTHON:001 ; :ref:`rule_python_filenames` ; No +PYTHON:002 ; :ref:`rule_python_header` ; Yes +PYTHON:003 ; :ref:`rule_python_syntax` ; No +PYTHON:004 ; :ref:`rule_python_formatting` ; No +PYTHON:005 ; :ref:`rule_python_spa` ; No +PYTHON:006 ; :ref:`rule_no_platform_specific_code` ; No +PYTHON:007 ; :ref:`rule_python_wscript_rules` ; No diff --git a/docs/developer-manual/style-guide/guidelines_overview_rst.csv b/docs/developer-manual/style-guide/guidelines_overview_rst.csv new file mode 100644 index 00000000..a5ca8e2b --- /dev/null +++ b/docs/developer-manual/style-guide/guidelines_overview_rst.csv @@ -0,0 +1,8 @@ +Rule ; Link ; Automated Check +RST:001 ; :ref:`rule_rst_filenames` ; No +RST:002 ; :ref:`rule_rst_line_length` ; No +RST:003 ; :ref:`rule_rst_include` ; Yes +RST:004 ; :ref:`rule_rst_links` ; Yes +RST:005 ; :ref:`rule_rst_headings` ; Yes +RST:006 ; :ref:`rule_rst_orphan` ; Yes +RST:007 ; :ref:`rule_rst_sentence` ; No diff --git a/docs/developer-manual/style-guide/guidelines_overview_sh.csv b/docs/developer-manual/style-guide/guidelines_overview_sh.csv new file mode 100644 index 00000000..8561dbe7 --- /dev/null +++ b/docs/developer-manual/style-guide/guidelines_overview_sh.csv @@ -0,0 +1,5 @@ +Rule ; Link ; Automated Check +BATCH:001 ; :ref:`rule_batch_filenames` ; No +BATCH:002 ; :ref:`rule_batch_header` ; Yes +SHELL:001 ; :ref:`rule_shell_filenames` ; No +SHELL:002 ; :ref:`rule_shell_header` ; Yes diff --git a/docs/developer-manual/style-guide/guidelines_overview_yaml.csv b/docs/developer-manual/style-guide/guidelines_overview_yaml.csv new file mode 100644 index 00000000..2c3f9a88 --- /dev/null +++ b/docs/developer-manual/style-guide/guidelines_overview_yaml.csv @@ -0,0 +1,3 @@ +Rule ; Link | automated check +YAML:001 ; :ref:`rule_yaml_filenames` | No +YAML:002 ; :ref:`rule_yaml_header` | Yes diff --git a/docs/developer-manual/style-guide/guidelines_python.rst b/docs/developer-manual/style-guide/guidelines_python.rst index 71544957..be28435c 100644 --- a/docs/developer-manual/style-guide/guidelines_python.rst +++ b/docs/developer-manual/style-guide/guidelines_python.rst @@ -8,7 +8,7 @@ Python Coding Guidelines These coding guidelines **MUST** be applied to all ``Python`` files. -The source files **MUST** be successfully checked by running the waf command +The source files **MUST** be successfully checked by running the Waf command ``check_guidelines`` before files can be merged into the master branch of the repository. @@ -27,7 +27,7 @@ The following rules apply for filenames of Python scripts. - The general file naming rules **MUST** be applied (see :numref:`rule_general_filenames`), except that dashes (``-``) **SHOULD** not be used. - - Python scripts **MUST** use ``.py`` as file extension, except for waf + - Python scripts **MUST** use ``.py`` as file extension, except for Waf build scripts which use ``wscript`` as file name. For example the valid file names for batch scripts are @@ -52,7 +52,6 @@ Header (``PYTHON:002``) :caption: File header for ``.py`` files. :name: file-header-py - .. _rule_python_syntax: Syntax (``PYTHON:003``) @@ -101,7 +100,6 @@ No platform specific code (``PYTHON:006``) Python scripts **MUST** use platform independent code where ever possible. If platform specific is required, it **MUST** be guarded. - Example :numref:`platform-specific-code` shows how to write platform acceptable platform specific code. diff --git a/docs/developer-manual/style-guide/guidelines_rst.rst b/docs/developer-manual/style-guide/guidelines_rst.rst index 6088121b..5cb92fe3 100644 --- a/docs/developer-manual/style-guide/guidelines_rst.rst +++ b/docs/developer-manual/style-guide/guidelines_rst.rst @@ -30,10 +30,10 @@ For example the valid file names for a reStructuredText sources are - ``macros.txt`` - ``software-installation.rst`` -.. _rule_rst_linelength: +.. _rule_rst_line_length: -Linelength (``RST:002``) ------------------------- +Line length (``RST:002``) +------------------------- Each line of text in your code **SHOULD** be at most 80 characters long. diff --git a/docs/developer-manual/style-guide/state-machine-example/state-machine.c b/docs/developer-manual/style-guide/state-machine-example/state-machine.c index cc9047e6..751abc79 100644 --- a/docs/developer-manual/style-guide/state-machine-example/state-machine.c +++ b/docs/developer-manual/style-guide/state-machine-example/state-machine.c @@ -43,8 +43,8 @@ * @file state-machine.c * @author foxBMS Team * @date 2020-10-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup STATE_MACHINE * @prefix EG * @@ -241,8 +241,8 @@ static void EG_SetState( if ((pEgState->currentState == nextState) && (pEgState->currentSubstate == nextSubstate)) { /* Next state and next substate equal to current state and substate: nothing to do */ - pEgState->nextState = EG_FSM_STATE_DUMMY; /* no state transistion required -> reset */ - pEgState->nextSubstate = EG_FSM_SUBSTATE_DUMMY; /* no substate transistion required -> reset */ + pEgState->nextState = EG_FSM_STATE_DUMMY; /* no state transition required -> reset */ + pEgState->nextSubstate = EG_FSM_SUBSTATE_DUMMY; /* no substate transition required -> reset */ earlyExit = true; } @@ -253,8 +253,8 @@ static void EG_SetState( pEgState->currentState = nextState; pEgState->previousSubstate = pEgState->currentSubstate; pEgState->currentSubstate = EG_FSM_SUBSTATE_ENTRY; /* Use entry state after a top level state change */ - pEgState->nextState = EG_FSM_STATE_DUMMY; /* no state transistion required -> reset */ - pEgState->nextSubstate = EG_FSM_SUBSTATE_DUMMY; /* no substate transistion required -> reset */ + pEgState->nextState = EG_FSM_STATE_DUMMY; /* no state transition required -> reset */ + pEgState->nextSubstate = EG_FSM_SUBSTATE_DUMMY; /* no substate transition required -> reset */ } else if (pEgState->currentSubstate != nextSubstate) { /* Only the next substate is different, switch to it */ EG_SetSubstate(pEgState, nextSubstate, idleTime); diff --git a/docs/developer-manual/style-guide/state-machine-example/state-machine.h b/docs/developer-manual/style-guide/state-machine-example/state-machine.h index 8da621e9..3ef3149d 100644 --- a/docs/developer-manual/style-guide/state-machine-example/state-machine.h +++ b/docs/developer-manual/style-guide/state-machine-example/state-machine.h @@ -43,8 +43,8 @@ * @file state-machine.h * @author foxBMS Team * @date 2020-10-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup STATE_MACHINE * @prefix EG * @@ -67,7 +67,7 @@ typedef enum { EG_FSM_STATE_HAS_NEVER_RUN, /*!< never run state - always the second state */ EG_FSM_STATE_UNINITIALIZED, /*!< uninitialized state */ EG_FSM_STATE_INITIALIZATION, /*!< initializing the state machine */ - EG_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ + EG_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ EG_FSM_STATE_ERROR, /*!< state for error processing */ } EG_FSM_STATES_e; diff --git a/docs/developer-manual/style-guide/state-machines_how-to.rst b/docs/developer-manual/style-guide/state-machines_how-to.rst index 7dac6ce3..cd6e6bd3 100644 --- a/docs/developer-manual/style-guide/state-machines_how-to.rst +++ b/docs/developer-manual/style-guide/state-machines_how-to.rst @@ -93,11 +93,10 @@ Basics All states **MUST** be put into an enum describing the states. There are four states in the example (|state_uninitialized|, |state_initialization|, |state_running|, |state_error|) plus the boilerplate of the state machine (a -dummy state called ``Dummy`` and a state indicating that the state machine has -never run called ``Has_never_run``). The enum entries **MUST** use +dummy state called ``DUMMY`` and a state indicating that the state machine has +never run called ``HAS_NEVER_RUN``). The enum entries **MUST** use ``FSM_STATE`` as infix after the module prefix. Taking all these rules into -account, the enum for the states used in this example looks like this: - +account, the enum for the states used in this example look like this: .. code-block:: c :linenos: @@ -109,7 +108,7 @@ account, the enum for the states used in this example looks like this: EG_FSM_STATE_HAS_NEVER_RUN, /*!< never run state - always the second state */ EG_FSM_STATE_UNINITIALIZED, /*!< uninitialized state */ EG_FSM_STATE_INITIALIZATION, /*!< initializing the state machine */ - EG_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ + EG_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ EG_FSM_STATE_ERROR, /*!< state for error processing */ } EG_FSM_STATES_e; @@ -117,7 +116,7 @@ A similar pattern has to be applied for the substates. For the boilerplate, a dummy substate called ``Dummy`` (as in the state) and an additional substate called ``Entry`` have to be defined. The enum entries **MUST** use ``FSM_SUBSTATE`` as infix after the module prefix. Taking all these rules into -account, the enum for the substates used in this example looks like this: +account, the enum for the substates used in this example look like this: .. code-block:: c :linenos: @@ -231,10 +230,10 @@ before continuing. Waiting is implemented via the variable ``timer`` which is a member of the state variable. It must be decremented one time every time the trigger function is called. Two cases can happen: - - If it has the value zero, it stays at zero and the content of the state - machine is processed further. - - If is has a non-zero value, it is decremented and the trigger function - exits without processing the state machine. +- If it has the value zero, it stays at zero and the content of the state + machine is processed further. +- If is has a non-zero value, it is decremented and the trigger function + exits without processing the state machine. To wait a definite amount of time, the ``time`` variable must only be assigned a non-zero value. The time to wait will depend on the periodicity with which @@ -396,7 +395,6 @@ in state processing functions. :ref:`state_processing_functions` explains what state processing functions are and how they work. For now it is sufficient to know that state processing functions need to exist. - If an error occurs in any of the substates of the state |state_initialization| the state machine needs to transfer to the state |state_error|. The transitions based on the states and substates would not be clearly visible in such a @@ -524,7 +522,6 @@ this function traps. break; } - ``EG_FSM_STATE_DUMMY`` """""""""""""""""""""" @@ -611,7 +608,6 @@ as the function ``EG_ProcessInitializationState()`` process the state At next the state processing functions ``EG_ProcessInitializationState()`` and ``EG_ProcessRunningState()`` are explained. - ``EG_ProcessInitializationState()`` """"""""""""""""""""""""""""""""""" @@ -714,7 +710,6 @@ implementation: } } - The ``default`` case is implemented to assert on illegal substates: .. code-block:: c diff --git a/docs/general/changelog.rst b/docs/general/changelog.rst index 70bd0c29..c82c3347 100644 --- a/docs/general/changelog.rst +++ b/docs/general/changelog.rst @@ -16,6 +16,8 @@ Changelog JUnit is a test system (originally for Java) matcher as in `problem matcher` Cppcheck is a static program analysis tools + Werror gcc + Wextra gcc xxxx is the dummy date for x.y.z .. spelling:: @@ -26,8 +28,10 @@ Changelog JUnit matcher Cppcheck + Werror + Wextra xxxx - + ba All notable changes to this project will be documented in this file. @@ -44,6 +48,117 @@ Versioning follows then these rules: - increasing ``PATCH`` introduces minor changes, that only require minor and straight forward work to update a project to this version. +******************** +[1.6.0] - 2023-10-12 +******************** + +Starting with this release, |foxbms| now supports the ADI ADES1830 AFE. + +This release updates the unit testing framework ``Ceedling`` to 0.32.0-52ba9d2 +and requires an update of Ruby. +To update Ruby and the required Gems see :ref:`ruby_install_and_gem_install`. +For information on the unit testing framework see (:ref:`UNIT_TESTS`). + +Added +===== + +- Support for the ADI ADES1830 AFE (see :ref:`ADI_ADES1830`). +- The GUI (:ref:`FOXBMS_2_GUI`) now also displays the *BMS state*. +- Documentation of the precharging process (:ref:`PRECHARGING`). +- The temperature sensor Vishay NTCLE413E2103F102L has been implemented. +- A logging file is created in a post-build process that shows the stack + consumption of each function. + This file is created in the variant build directory + (``build/bin/foxbms.stacks.json``). +- Clamp 15 wake-up behavior. The BMS is now correctly switched on/off, + depending on clamp 15 signal. However, resistor R1101 *MUST* not be populated + to correctly work and currently only MCU SBC is switched off. +- Added dummy AFE implementation to enable a future support of TI AFEs. +- Add a README.md that explains the AFE implementation for the TI AFEs. + The README.md is found at ``src/app/driver/afe/ti/README.md``. +- The git commit hash can now be requested and transmitted via CAN. +- Added a driver for the HONEYWELL BAS6C-X00 aerosol sensor. +- The unit testing framework is now supported on Linux + (see :ref:`linux_specific_usage`). + +Changed +======= + +- Updated to ``Ceedling`` 0.32.2-86f6b27. +- The default behavior in FreeRTOS is now to check for stack overflows. + The type of checking has been set to variant ``2``. + See https://www.freertos.org/Stacks-and-stack-overflow-checking.html for the + FreeRTOS internal details. +- The function ``FTSK_InitializeUserCodeEngine`` used an outdated enum value + to check for a correct startup. + As the outdated enum was still defined in the HAL (generated by HALCoGen) + this did not lead to an error. +- Split SOX database entries into dedicated SOC, SOH and SOE database entries. +- Improved code quality of the unit tests (``tests/unit``). +- The unit tests are now compiled more strictly with respect to warnings + (``-Wall``, ``-Wextra``, ``-Werror``), are required to be strictly ISO C + conforming (``-pedantic``). + Furthermore the unit test are now compiled with the correct C standard + version (``std=c11``). +- Improved assertions for invalid CAN configurations. +- Improved code organization and style guide conformance of the NXP MC33775A + driver (:ref:`NXP_MC33775A`). +- Added check for successful transmission of CAN messages and try to resend + them if transmission failed. +- The rules file must be sorted. +- Fixed several Axivion findings. +- Removed the Axivion compiler workaround for ``_Imaginary`` as this is + supported since Axivion 7.5.2 (which is the current |foxbms| default + configuration). +- Lauterbach debugger configuration: + + - The automatically created Lauterbach configuration now loads the symbol + table of default binary (``build/bin/foxbms.elf``) automatically on + startup. + - The script file that contains list of macros and their values is + automatically load on debugger startup. + This script is created based on the compiler output files + (``build/bin/**/*.ppm``) and the configuration script in + ``tools/debugger/lauterbach/load_macro_values.cmm.in``. + To recreate this table after a new build the + ``tools\debugger\lauterbach\get_macro_values.py`` script needs to be run. + After that, the created file needs to be loaded again in the Lauterbach + command line by ``do /build/load_macro_values.cmm``. + +- Renamed driver for *Murata NCU15XH103F6Sxx* temperature sensor to + *NCxxxXH103* as the temperature characteristic is identical for multiple + sensors +- Renamed define ``BS_NR_OF_PARALLEL_CELLS_PER_MODULE`` to + ``BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK`` +- Changed database definition in struct ``DATA_BLOCK_CELL_VOLTAGE_s`` for + ``cellVoltage_mV`` from a two-dimensional array + (``cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_CELL_BLOCKS_PER_STRING]``) to + three-dimensional array + (``cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING][BS_NR_OF_CELL_BLOCKS_PER_MODULE]``) + +Deprecated +========== + +Removed +======= + +- Removed unused empty files from the repository. + +Fixed +===== + +- Fixed a bug in MRC module that string power was not calculated correctly. +- Fixed a bug that precharging the battery system has been re-tried for an + infinite number of tries regardless of the configuration of + ``BMS_PRECHARGE_TRIES``. +- Fixed a bug in CAN module that periodic messages would not be sent correctly + after the BMS had been running continuously for 50 days. +- Fixed a bug that stack size for I2C and AFE tasks were sized incorrectly. + They were defined as words, whereas the define states a stack size in byte. + This lead to stack overflows for some configurations. +- ``BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK`` is now considered calculating the + allowed continuous current limits. + ******************** [1.5.1] - 2023-02-23 ******************** @@ -56,7 +171,6 @@ Added Changed ======= - - Update the static code analysis to Axivion 7.5.2 (from 7.5.0). - Simplified the conda development environment. @@ -182,7 +296,7 @@ Fixed - Fixed the hardware readme as it referenced the wrong |master| version. - Fixed the regular expression for checking the validity of macro names. - Fixed wrong configured chip select pin for MCU SBC. Chip select 1 instead of - chip select was configured. + chip select 0 was configured. ******************** [1.4.1] - 2022-10-27 @@ -205,7 +319,7 @@ Changed - Updated the hardware design files (e.g., schematics, layout, BOM and STEP file etc.) of the |bms-master| to ``v1.1.5`` (see :ref:`CHANGELOG_FOR_MASTER_TMS570_V1_1_5`). -- Updated documentation of the interface using the |max17841b| transceiver +- Updated documentation of the interface using the |max-max17841b| transceiver chip. - The implementation of the CAN driver has been changed to simplify adding new messages. @@ -257,7 +371,7 @@ Added - the |foxbms| license header - literal suffixes for numerical assignments - Added test cases for the Axivion rules (see ``tests/axivion/addon-test``) -- The foxBMS GUI wrapper is now implemented as a module. +- The |foxbms| GUI wrapper is now implemented as a module. - Added a driver for the NXP MC33775A monitoring IC. The driver measures cell voltages, cell temperatures via an I2C multiplexer and controls cell balancing. @@ -376,8 +490,8 @@ Changed This change simplifies the integration of the build into Axivion. - |freertos| configuration is now validated in ``os_freertos_config-validation.h``. -- Updated the documentation of the of the LTC-based interface |ltc6820| version - 1.0.3 (see :ref:`INTERFACE_LTC_6820___V1_0_3__`). +- Updated the documentation of the of the LTC-based interface |ltc-ltc6820| + version 1.0.3 (see :ref:`INTERFACE_LTC_6820___V1_0_3__`). - Updated LLVM to version 13.0.0. - Updated the pinout documentation for the |bms-master| version 1.1.1 (see :ref:`MASTER_TMS570___V1_1_1__`). @@ -555,7 +669,7 @@ Added - Added stubs for the Bender IR155 insulation monitoring device driver (i.e. **driver is non-functional**). - Extended the documentation with a render of the architecture against which - the foxBMS implementation is checked. + the |foxbms| implementation is checked. - Added driver for I2C communication for MCU. - Added driver for I2C port expander. - Added driver for I2C humidity/temperature sensor. @@ -665,7 +779,7 @@ Removed Fixed ===== -- When HALCoGen was not available, the waf tool nevertheless tried to set the +- When HALCoGen was not available, the Waf tool nevertheless tried to set the respective include path, which lead to exception in Python. This has been fixed by not trying to set the include path when HALCoGen is not available. @@ -740,7 +854,7 @@ Added - Instructions on how to reference to |foxbms| - Added handling of I2C multiplexers to the Maxim monitoring IC driver. -- Added a flash tool to the waf toolchain. It is based on SEGGER J-Flash and +- Added a flash tool to the Waf toolchain. It is based on SEGGER J-Flash and can be invoked by calling ``waf install_bin`` or running the ``Flash:Binary`` task in |code|. - Added a short note on the installation of PEAK-Drivers (for CAN @@ -787,12 +901,12 @@ Changed that keeps the volatile keyword on the register. - Dropped the requirement for an internal library (``pyhameg``) in the HIL test. -- Updated the unit test framework ``ceedling`` to version ``0.31.1``. +- Updated the unit test framework ``Ceedling`` to version ``0.31.1``. - Simplified the configuration of the Cppcheck tool. - Improved several function names in the ``ftask`` module. - All required Queues are now created in one function (``FTSK_CreateQueues``) before the scheduler starts. -- Split the waf compiler tool into smaller sub-tools to simplify maintenance +- Split the Waf compiler tool into smaller sub-tools to simplify maintenance and tests. Deprecated @@ -817,8 +931,8 @@ Fixed - Fixed bug in SOC/SOE counting module that extrapolated for cell voltages below lookup-table range - Fixed bug that caused current sensor scaling values to be only recalibrated - after startup and not while recalibrating SOC/SOE values via LUT when BMS is - at rest. + after startup and not while recalibrating SOC/SOE values via look up tables + when BMS is at rest. - A race condition between the SOC and SOE calculation lead to a mutual overwriting of the state estimation values. - Added documentation for the CAN module. @@ -896,7 +1010,7 @@ Changed when building the documentation. - Moved code examples in developer manual to separate source files. - The shebang in Python files has been updated from ``python`` to ``python3``. -- Updated waf to version 2.0.22 (from 2.0.21). +- Updated Waf to version 2.0.22 (from 2.0.21). - Updated database documentation. - Updated information on tracing with Segger J-Trace probes. @@ -916,7 +1030,7 @@ Fixed - ``without-halcogen_diff-includes.diff`` was unintentionally excluded by the regex in ``.gitignore``. - Fixed repository name in the documentation. -- Fixed available waf commands and put the table in a separate csv file. +- Fixed available Waf commands and put the table in a separate csv file. - Fixed comments in LTC driver build scripts - Includes directories were not correctly set for the drivers *LTC 6811-1* and *LTC 6812-1*. @@ -1135,7 +1249,7 @@ Changed take longer for computation, the algorithm module has been moved into its own task with a lower priority. - Updated |freertos| to version 10.4.3 (from 10.3.0). -- Updated waf to version 2.0.21 (from 2.0.20). +- Updated Waf to version 2.0.21 (from 2.0.20). - Consequently uses deci degree Celsius as integer-value (instead of degree Celsius floats) in the Temperature Sensor Interface (TSI). - Moved the ``slaveplausibility``-modules into one central module in the MIC @@ -1149,13 +1263,13 @@ Changed - Source files are no longer needed to be added manually to the documentation, instead sources are linked into the documentation based on the Doxygen generated documentation. -- Sets ``UNITY_INCLUDE_EXEC_TIME`` in the ceedling configuration in order to - tell unity to track the time that a single test takes. This information is +- Sets ``UNITY_INCLUDE_EXEC_TIME`` in the ``Ceedling`` configuration in order + to tell unity to track the time that a single test takes. This information is aggregated in the JUnit test report that is generated. -- Updated the unit test framework ``ceedling`` to version ``0.31.0`` and - vendored the ``ceedling`` release with the repository in order to have more +- Updated the unit test framework ``Ceedling`` to version ``0.31.0`` and + vendored the ``Ceedling`` release with the repository in order to have more control over the executed version. Simplified the installation of Ruby in - order to to reflect these changes. Simplified the ``f_unit_test`` waf-tool. + order to to reflect these changes. Simplified the ``f_unit_test`` Waf tool. Deprecated ========== @@ -1185,8 +1299,9 @@ Fixed version information is now properly passed to the documentation build. - The top of every documentation page began with ``orphan:``. - Fixed implicitly defined functions. -- Fixed the unit test documentation on how to use ceedling directly. The old - version mentioned a wrong path for the ``project.yml`` used by ceedling. +- Fixed the unit test documentation on how to use ``Ceedling`` directly. + The old version mentioned a wrong path for the ``project.yml`` used by + ``Ceedling``. ******************** [0.1.0] - 2020-11-17 diff --git a/docs/general/commit-msgs/release-v1.6.0.txt b/docs/general/commit-msgs/release-v1.6.0.txt new file mode 100644 index 00000000..e79ca963 --- /dev/null +++ b/docs/general/commit-msgs/release-v1.6.0.txt @@ -0,0 +1,15 @@ +Minor release of foxBMS 2 (v1.6.0) + +* foxBMS now supports the ADI ADES1830 AFE. +* The default FreeRTOS behavior for foxBMS 2 is now to check for stack + overflows. The BMS still tries to send a CAN message about the occurred + problem. +* The BMS tried to precharge a infinite times. This setting is now controlled + by setting `BMS_PRECHARGE_TRIES` to a meaningful, finite number (needs to + be defined by the user as part of the application setup) +* The calculation of the string power has been fixed. +* The SOX database entry has been split into SOC, SOH, and SOE to simplify + adding further estimations. + +For a detailed list of changes, please refer to the documentation at +https://iisb-foxbms.iisb.fraunhofer.de/foxbms/gen2/docs/html/v1.6.0/general/changelog.html. diff --git a/docs/general/license.rst b/docs/general/license.rst index b9e0accf..5d936b77 100644 --- a/docs/general/license.rst +++ b/docs/general/license.rst @@ -99,7 +99,6 @@ BSD 3-Clause License (BSD 3-Clause "New" or "Revised" License) .. literalinclude:: ./../../BSD-3-Clause.txt :language: none - .. _CREATIVE_COMMONS_ATTRIBUTION_4_0_INTERNATIONAL_LICENSE: Creative Commons Attribution 4.0 International License @@ -108,7 +107,6 @@ Creative Commons Attribution 4.0 International License .. literalinclude:: ./../../CC-BY-4.0.txt :language: none - ******************** Third Party Licenses ******************** diff --git a/docs/general/motivation.rst b/docs/general/motivation.rst index a1065e71..4e0ed5dd 100644 --- a/docs/general/motivation.rst +++ b/docs/general/motivation.rst @@ -17,17 +17,16 @@ hardware and software for potentially any kind of mobile and stationary application that uses modern rechargeable electrochemical energy storage systems (e.g., lithium-ion batteries, redox-flow batteries, supercapacitors): - - |foxbms| Hardware: the schematics and the layout of all electronic boards - are available for download and the design is based on commonly available - components and devices, that do not require non-disclosure agreements (NDA) - or confidentiality agreements. - - |foxbms| Software: the software toolchain uses only own developed open - source and free of charge components or free of charge third-party - software, and the entire BMS source code is provided online with its own - development environment and configuration files, thus enabling immediate - use on Windows operating systems. Please contact us if you are on Mac or - Linux. - +- |foxbms| Hardware: the schematics and the layout of all electronic boards + are available for download and the design is based on commonly available + components and devices, that do not require non-disclosure agreements (NDA) + or confidentiality agreements. +- |foxbms| Software: the software toolchain uses only own developed open + source and free of charge components or free of charge third-party + software, and the entire BMS source code is provided online with its own + development environment and configuration files, thus enabling immediate + use on Windows operating systems. Please contact us if you are on Mac or + Linux. What is |foxbms| designed for? ------------------------------ @@ -62,14 +61,14 @@ identifier: BSD-3-Clause). This means, |foxbms| parts can be utilized unrestrictedly, including commercial use. The |foxbms| platform addresses especially: - - R&D and test engineers requiring a smart and powerful, well documented BMS - platform - - Engineering companies requiring a maintained and supported BMS for their - developments - - Small enterprises requiring a flexible and future proof BMS for developing - their products - - Large enterprises requiring a reliable and safe BMS for testing their - prototypes - - Research organizations requiring a simple and universal BMS development - platform - - Students looking for a free and open BMS software development toolchain +- R&D and test engineers requiring a smart and powerful, well documented BMS + platform +- Engineering companies requiring a maintained and supported BMS for their + developments +- Small enterprises requiring a flexible and future proof BMS for developing + their products +- Large enterprises requiring a reliable and safe BMS for testing their + prototypes +- Research organizations requiring a simple and universal BMS development + platform +- Students looking for a free and open BMS software development toolchain diff --git a/docs/general/releases.csv b/docs/general/releases.csv index 0b268793..80f85e17 100644 --- a/docs/general/releases.csv +++ b/docs/general/releases.csv @@ -1,4 +1,5 @@ foxBMS 2; Release Date; Permanent link to documentation +v1.6.0; 2023-10-12; https://iisb-foxbms.iisb.fraunhofer.de/foxbms/gen2/docs/html/v1.6.0/ v1.5.1; 2023-02-23; https://iisb-foxbms.iisb.fraunhofer.de/foxbms/gen2/docs/html/v1.5.1/ v1.5.0; 2023-02-03; https://iisb-foxbms.iisb.fraunhofer.de/foxbms/gen2/docs/html/v1.5.0/ v1.4.1; 2022-10-27; https://iisb-foxbms.iisb.fraunhofer.de/foxbms/gen2/docs/html/v1.4.1/ diff --git a/docs/general/safety/safety.rst b/docs/general/safety/safety.rst index 34dca6c1..ccb93a82 100644 --- a/docs/general/safety/safety.rst +++ b/docs/general/safety/safety.rst @@ -10,12 +10,13 @@ Risk Assessment --------------- Depending on the countries of the target application, there are different -standards to regard. In the European Union, the applicable directives lead to -different safety requirements. -These have a variety of risk graphs for the risk assessment. Although they are -only slightly different they are not adaptable to each other. Since the target -country and use of |foxbms| is unknown, the users of the system need to do a -risk assessment on their own according to their concerns. +standards to regard. +In the European Union, the applicable directives lead to different safety +requirements. +These have a variety of risk graphs for the risk assessment. +Although they are only slightly different they are not adaptable to each other. +Since the target country and use of |foxbms| is unknown, the users of the +system need to do a risk assessment on their own according to their concerns. Some European directives that can be relevant for the |foxbms| users: @@ -39,7 +40,6 @@ A list of standards that might fit to the target application can be found here: - https://www.mpoweruk.com/standards.htm - Standards --------- @@ -72,7 +72,6 @@ Safety Instructions Before Using |foxbms| 60364-4-41, IEC 60364-6, IEC 60529 (DIN VDE 0100-410, DIN VDE 0100-600, VDE 0470-1). - .. danger:: .. W012, M009 .. image:: ./signs/mandatory/m009_handschutz_benutzen.png @@ -89,7 +88,6 @@ Safety Instructions Before Using |foxbms| order to work with the battery system and assemble it. Wear personal insulating protective equipment. - .. danger:: .. W002, W016, W021, W023, W026, W028 .. image:: ./signs/warning/w002_explosionsgefaehrliche_stoffe.png @@ -113,14 +111,12 @@ Safety Instructions Before Using |foxbms| :alt: alternate text :align: right - Risk of fire, explosion and chemical hazards through the battery cells. You need to be a battery skilled person in order to work with the battery system and assemble it. Use safe cells with CID, PTC and OPD. Use the battery system in a confined area. Keep sand, water and fire extinguisher close to the system to fight fire. Regard local fire safety regulations. - .. danger:: .. M008, M009, M010, M013, M014 .. image:: ./signs/mandatory/m008_fussschutz_benutzen.png @@ -153,7 +149,6 @@ Safety Instructions Before Using |foxbms| protection, protection glasses, protection gloves). Keep other persons in a safe distance. - .. danger:: .. W012, W026 .. image:: ./signs/warning/w012_elektrische_spannung.png @@ -172,7 +167,6 @@ Safety Instructions Before Using |foxbms| shortage. A fire might start or other hazards can occur. Leave enough room between the cells and use locknuts. - .. danger:: .. W012, W026 .. image:: ./signs/warning/w012_elektrische_spannung.png @@ -188,7 +182,6 @@ Safety Instructions Before Using |foxbms| can occur. Be cautious and prevent battery cells and batteries from wrong connection. - .. danger:: .. W023, W026, M004, M009 .. image:: ./signs/mandatory/m004_augenschutz_benutzen.png @@ -214,7 +207,6 @@ Safety Instructions Before Using |foxbms| electrolyte. Regard material safety data sheet (MSDS) from the battery cell manufacturer. - .. danger:: .. W012, W026 .. image:: ./signs/warning/w012_elektrische_spannung.png @@ -235,7 +227,6 @@ Safety Instructions Before Using |foxbms| Do not mix cells within the battery. Use only one type of cell throughout the whole system. - .. warning:: .. W016, W021, W026, W028 .. image:: ./signs/warning/w016_giftige_stoffe.png @@ -260,7 +251,6 @@ Safety Instructions Before Using |foxbms| environment to ensure flammable and toxic gases will be removed in case of degassing of a battery cell. - .. warning:: .. W012 .. image:: ./signs/warning/w012_elektrische_spannung.png @@ -274,7 +264,6 @@ Safety Instructions Before Using |foxbms| amount of 12 cells with a voltage sum between 11V and 55V. Beware of the amount of cells and the cell voltage. - .. warning:: .. W023, M004, M009 .. image:: ./signs/mandatory/m004_augenschutz_benutzen.png @@ -294,7 +283,6 @@ Safety Instructions Before Using |foxbms| chemicals and wear chemical protective gloves and safety goggles. Regard material safety data sheet (MSDS) from the battery cell manufacturer. - .. warning:: .. W012, W026 .. image:: ./signs/warning/w012_elektrische_spannung.png @@ -310,7 +298,6 @@ Safety Instructions Before Using |foxbms| solder anything directly to the cells or battery. Follow the mounting instructions of the manufacturer. - .. warning:: .. W026 .. image:: ./signs/warning/w026_gefahren_batterien.png @@ -323,7 +310,6 @@ Safety Instructions Before Using |foxbms| to detect over temperature and keep a fire extinguisher close to the battery system. Do not use damaged cells or batteries. - .. warning:: .. W012 .. image:: ./signs/warning/w012_elektrische_spannung.png @@ -335,7 +321,6 @@ Safety Instructions Before Using |foxbms| over temperature that bring other hazards with them. Assemble breaking elements between parallel cells to avoid the short current. - .. warning:: .. W012 .. image:: ./signs/warning/w012_elektrische_spannung.png @@ -348,7 +333,6 @@ Safety Instructions Before Using |foxbms| the batteries and avoid heavy loads and rapid charges and discharges. Remove fully charged battery packs from the charger. - .. warning:: .. W012, P008 .. image:: ./signs/prohibition/p008_metallteile_uhren_verboten.png @@ -364,7 +348,6 @@ Safety Instructions Before Using |foxbms| fault detector or an insulation monitor and regard IEC 60364-4-41 and IEC 60364-6 (DIN VDE 0100-410, DIN VDE 0100-600). - .. warning:: .. W012, P008 .. image:: ./signs/prohibition/p008_metallteile_uhren_verboten.png @@ -380,7 +363,6 @@ Safety Instructions Before Using |foxbms| tools while assembling, disassembling, maintaining, servicing or dismantling the battery system. Never open battery cells. - .. warning:: .. P003 .. image:: ./signs/prohibition/p003_keine_offene_flamme.png @@ -392,7 +374,6 @@ Safety Instructions Before Using |foxbms| system can start burning or explode. Do not use the battery system in an explosive environment. - .. warning:: .. W026, M016, M017 .. image:: ./signs/mandatory/m016_maske_benutzen.png @@ -413,7 +394,6 @@ Safety Instructions Before Using |foxbms| Assemble and disassemble the system carefully and keep gas mask or breathing aid in close environment. - .. caution:: .. M008, M009 .. image:: ./signs/mandatory/m008_fussschutz_benutzen.png @@ -429,7 +409,6 @@ Safety Instructions Before Using |foxbms| you. Use solid housing and add handles. Wear personal protective equipment, gloves, shoes and other clothes for working. - .. caution:: .. M003 .. image:: ./signs/mandatory/m003_gehoerschutz_benutzen.png @@ -441,7 +420,6 @@ Safety Instructions Before Using |foxbms| ear muffs with other personal protective equipment. Stay out and keep other persons out of the testing area. - .. caution:: .. M009 .. image:: ./signs/mandatory/m009_handschutz_benutzen.png @@ -453,7 +431,6 @@ Safety Instructions Before Using |foxbms| or threaten your health. Wear gloves while working with soldering materials and wash hands properly afterwards. - .. caution:: .. M001 .. image:: ./signs/mandatory/m001_allgemeines_gebotszeichen.png @@ -466,7 +443,6 @@ Safety Instructions Before Using |foxbms| responsible parts may lead to other hazards. Keep the battery system in a dry and clean environment and away from corrosive materials. - .. note:: .. W023, W026, M004, M009 @@ -491,7 +467,6 @@ Safety Instructions Before Using |foxbms| pouch battery cells are used and the pouch bag has been damaged. Put a basin underneath for dripping the electrolyte. - .. note:: .. W026 @@ -504,7 +479,6 @@ Safety Instructions Before Using |foxbms| discharge. Never charge and use again battery cells or batteries after deep discharge has occurred. - .. note:: .. M001 @@ -518,7 +492,6 @@ Safety Instructions Before Using |foxbms| valid temperature range. Keep the cells and batteries out of the sun and use heating or cooling to keep the safe temperature range. - .. note:: .. M001, P008, W012 diff --git a/docs/getting-started/getting-started.rst b/docs/getting-started/getting-started.rst index fb7dbd1b..cfb9f172 100644 --- a/docs/getting-started/getting-started.rst +++ b/docs/getting-started/getting-started.rst @@ -33,7 +33,6 @@ They must be read as they are used throughout the whole documentation. Software Installation ********************* - The :ref:`SOFTWARE_INSTALLATION` part of the documentation explains how to install and configure the toolchain that is used for working on the embedded software. diff --git a/docs/getting-started/repository-structure.rst b/docs/getting-started/repository-structure.rst index ac2c861d..04a08551 100644 --- a/docs/getting-started/repository-structure.rst +++ b/docs/getting-started/repository-structure.rst @@ -48,7 +48,6 @@ repository structure and avoid long command lines during build steps. | | | work with |foxbms| | +-----------------+-----------------------------+--------------------------------------+ - Configuration directory ``conf`` ================================ @@ -59,33 +58,33 @@ The ``conf`` directory is structured into the following parts (see :name: introduction-repository-structure-conf-details :widths: grid - +-----------------+-----------------------------+--------------------------------------+ - | directory | long name | content description | - +=================+=============================+======================================+ - | ``conf/bms`` | Battery Management System | configuration of the BMS | - | | | (e.g., which AFE is used) | - +-----------------+-----------------------------+--------------------------------------+ - | ``conf/cc`` | C compiler | compiler configuration | - | | | (e.g., compiler flags) | - +-----------------+-----------------------------+--------------------------------------+ - | ``conf/env`` | Environment | environment specifications | - | | | configuration files | - | | | (e.g., Conda package dependencies) | - +-----------------+-----------------------------+--------------------------------------+ - | ``conf/fmt`` | Formatting | formatting rules for source files | - +-----------------+-----------------------------+--------------------------------------+ - | ``conf/gl`` | Guidelines | Guideline check configuration | - +-----------------+-----------------------------+--------------------------------------+ - | ``conf/hcg`` | |halcogen| | |halcogen| configuration files for | - | | | the Hardware Abstraction Layer | - +-----------------+-----------------------------+--------------------------------------+ - | ``conf/spa`` | Static Program Analysis | configuration and template files for | - | | | static program analysis | - +-----------------+-----------------------------+--------------------------------------+ - | ``conf/tpl`` | Templates | template files for source files | - +-----------------+-----------------------------+--------------------------------------+ - | ``conf/unit`` | Unit tests | unit test configuration files | - +-----------------+-----------------------------+--------------------------------------+ + +-----------------------+-----------------------------+--------------------------------------+ + | directory | long name | content description | + +=======================+=============================+======================================+ + | ``conf/bms`` | Battery Management System | configuration of the BMS | + | | | (e.g., which AFE is used) | + +-----------------------+-----------------------------+--------------------------------------+ + | ``conf/cc`` | C compiler | compiler configuration | + | | | (e.g., compiler flags) | + +-----------------------+-----------------------------+--------------------------------------+ + | ``conf/env`` | Environment | environment specifications | + | | | configuration files | + | | | (e.g., Conda package dependencies) | + +-----------------------+-----------------------------+--------------------------------------+ + | ``conf/fmt`` | Formatting | formatting rules for source files | + +-----------------------+-----------------------------+--------------------------------------+ + | ``conf/guidelines`` | Guidelines | Guideline check configuration | + +-----------------------+-----------------------------+--------------------------------------+ + | ``conf/hcg`` | |halcogen| | |halcogen| configuration files for | + | | | the Hardware Abstraction Layer | + +-----------------------+-----------------------------+--------------------------------------+ + | ``conf/spa`` | Static Program Analysis | configuration and template files for | + | | | static program analysis | + +-----------------------+-----------------------------+--------------------------------------+ + | ``conf/tpl`` | Templates | template files for source files | + +-----------------------+-----------------------------+--------------------------------------+ + | ``conf/unit`` | Unit tests | unit test configuration files | + +-----------------------+-----------------------------+--------------------------------------+ Documentation directory ``docs`` ================================ @@ -144,6 +143,9 @@ The ``tests`` directory is structured into the following parts (see | | | configurations are stored here | | | | (e.g., MISRA-C) | +--------------------+--------------------------+--------------------------------------+ + | ``tests/hil`` | Hardware in the Loop | scripts and configurations to run | + | | | HIL tests | + +--------------------+--------------------------+--------------------------------------+ | ``tests/scripts`` | scripts | unit test of scripts (e.g., Python, | | | | shell) | +--------------------+--------------------------+--------------------------------------+ @@ -176,8 +178,8 @@ The ``tools`` directory is structured into the following parts (see +---------------------+----------------------------+--------------------------------------+ | ``tools/utils`` | utils | unspecific helper tools and scripts | +---------------------+----------------------------+--------------------------------------+ - | ``tools/waf-tools`` | waf tools | waf tools that are not part of | - | | | vendored waf | + | ``tools/waf-tools`` | Waf tools | Waf tools that are not part of | + | | | vendored Waf | +---------------------+----------------------------+--------------------------------------+ - | ``tools/waf`` | waf | waf binary | + | ``tools/waf`` | Waf | Waf binary | +---------------------+----------------------------+--------------------------------------+ diff --git a/docs/getting-started/ruby-installation/ruby-installation.rst b/docs/getting-started/ruby-installation/ruby-installation.rst index 9096e5fc..1ea2215e 100644 --- a/docs/getting-started/ruby-installation/ruby-installation.rst +++ b/docs/getting-started/ruby-installation/ruby-installation.rst @@ -17,9 +17,9 @@ Manual Ruby Installation temporary folder, and then can be copied back into ``C:\Ruby\RubyX.Y.Z.`` after the installation has finished. -#. Download the |ruby| installer version ``2.7.2`` including the Devkit from +#. Download the |ruby| installer version ``3.1.3-x64`` without the Devkit from `rubyinstaller.org `_. Use - ``C:\Ruby\Ruby272-x64`` as installation directory and do not add Ruby to + ``C:\Ruby\Ruby3.1.3-x64`` as installation directory and do not add Ruby to ``PATH``. .. figure:: img/ruby-installer-0.png @@ -34,7 +34,7 @@ Manual Ruby Installation :caption: Installing required gems for Ceedling C:\Users\vulpes\Documents\foxbms-2>cd tools\vendor\ceedling - C:\Users\vulpes\Documents\foxbms-2>C:\Ruby\Ruby272-x64\bin\bundle install + C:\Users\vulpes\Documents\foxbms-2>C:\Ruby\Ruby3.1.3-x64\bin\bundle install Add ``--http-proxy=http://user:password@server:port`` (adapted to your settings) to the shown command if you are behind a proxy. diff --git a/docs/getting-started/software-installation.rst b/docs/getting-started/software-installation.rst index 1c857aeb..1f377671 100644 --- a/docs/getting-started/software-installation.rst +++ b/docs/getting-started/software-installation.rst @@ -68,9 +68,9 @@ later steps of this manual. :caption: Downloading a release :name: download-foxbms-2 - C:\Users\vulpes\Documents>curl -Ss -L -o foxbms-2-v1.5.1.zip https://github.com/foxBMS/foxbms-2/archive/v1.5.1.zip - C:\Users\vulpes\Documents>tar -x -f foxbms-2-v1.5.1.zip - C:\Users\vulpes\Documents>ren foxbms-2-1.5.1 foxbms-2 + C:\Users\vulpes\Documents>curl --silent --show-error -L -o foxbms-2-v1.6.0.zip https://github.com/foxBMS/foxbms-2/archive/v1.6.0.zip + C:\Users\vulpes\Documents>tar -x -f foxbms-2-v1.6.0.zip + C:\Users\vulpes\Documents>ren foxbms-2-1.6.0 foxbms-2 C:\Users\vulpes\Documents>cd foxbms-2 .. note:: @@ -145,7 +145,6 @@ Installing |halcogen| may take a while. Installing Miniconda and Configuration ====================================== - .. note:: If you already have installed miniconda3 in one of the default miniconda3 @@ -210,6 +209,8 @@ Installing LLVM | | | +--------------------------------------------------------------------------------+-----------------------------------------+ +.. _ruby_install_and_gem_install: + Installing Ruby and Required Gems ================================= diff --git a/docs/getting-started/workspace.rst b/docs/getting-started/workspace.rst index dc395e53..03e6ee27 100644 --- a/docs/getting-started/workspace.rst +++ b/docs/getting-started/workspace.rst @@ -10,7 +10,6 @@ If |code| is available, a ``.vscode`` directory with all needed configurations is generated when running ``waf configure``. The generated workspace is properly configured. - Launching |code| ---------------- @@ -25,7 +24,6 @@ taken into account: #. Open |code|. #. Goto ``File->Open Folder`` and select the cloned |foxbms| repository. - Build Tasks ----------- Build commands are executed by running ``Build Tasks``. A ``Build Task`` is diff --git a/docs/hardware/img/connectors_molex_microfit.vsdx b/docs/hardware/img/connectors_molex_microfit.vsdx index 77d8622c..4084014f 100644 Binary files a/docs/hardware/img/connectors_molex_microfit.vsdx and b/docs/hardware/img/connectors_molex_microfit.vsdx differ diff --git a/docs/hardware/img/molex_connector-20pin.png b/docs/hardware/img/molex_connector-20pin.png new file mode 100644 index 00000000..7b7aebdc Binary files /dev/null and b/docs/hardware/img/molex_connector-20pin.png differ diff --git a/docs/hardware/interfaces.rst b/docs/hardware/interfaces.rst index 6b399680..71e2a4d0 100644 --- a/docs/hardware/interfaces.rst +++ b/docs/hardware/interfaces.rst @@ -9,14 +9,14 @@ Interfaces Overview LTC-based Interfaces -------------------- -The changelog for the |ltc6820|\ -based interfaces can be found at: +The changelog for the |ltc-ltc6820|\ -based interfaces can be found at: .. toctree:: :maxdepth: 1 ./interfaces/ltc-ltc6820-vx.x.x/ltc-ltc6820-changelog -The documentation for the different versions of the |ltc6820|\ -based +The documentation for the different versions of the |ltc-ltc6820|\ -based interfaces can be found at: .. toctree:: @@ -27,14 +27,14 @@ interfaces can be found at: NXP-based Interfaces -------------------- -The changelog for the |mc33664|\ -based interfaces can be found at: +The changelog for the |nxp-mc33664|\ -based interfaces can be found at: .. toctree:: :maxdepth: 1 ./interfaces/nxp-mc33664-vx.x.x/nxp-mc33664-changelog -The documentation for the different versions of the |mc33664|\ -based +The documentation for the different versions of the |nxp-mc33664|\ -based interfaces can be found at: .. toctree:: @@ -45,14 +45,14 @@ interfaces can be found at: MAXIM-based Interfaces ---------------------- -The changelog for the |max17841b|\ -based interfaces can be found at: +The changelog for the |max-max17841b|\ -based interfaces can be found at: .. toctree:: :maxdepth: 1 ./interfaces/maxim-max17841b-vx.x.x/maxim-max17841b-changelog -The documentation for the different versions of the |max17841b|\ -based +The documentation for the different versions of the |max-max17841b|\ -based interfaces can be found at: .. toctree:: diff --git a/docs/hardware/interfaces/ltc-ltc6820-vx.x.x/ltc-ltc6820-v1.0.3.rst b/docs/hardware/interfaces/ltc-ltc6820-vx.x.x/ltc-ltc6820-v1.0.3.rst index f05867dd..060e6848 100644 --- a/docs/hardware/interfaces/ltc-ltc6820-vx.x.x/ltc-ltc6820-v1.0.3.rst +++ b/docs/hardware/interfaces/ltc-ltc6820-vx.x.x/ltc-ltc6820-v1.0.3.rst @@ -14,7 +14,7 @@ Overview .. important:: - The following description only applies for the |ltc6820|\ -based + The following description only applies for the |ltc-ltc6820|\ -based |bms-interface| hardware version |local_interface_version|. .. hint:: @@ -83,9 +83,9 @@ A block diagram of the |bms-interface| is shown in Block diagram of the |bms-interface| -Each of the four isoSPI channels uses one |ltc6820| communication chip from +Each of the four isoSPI channels uses one |ltc-ltc6820| communication chip from |adi| and an insulation transformer. -The |ltc6820| chips are directly connected to the MCU via |spi|. +The |ltc-ltc6820| chips are directly connected to the MCU via |spi|. ^^^^^^^^^^^^^^^^^^^^^^^^^^ Schematic and Board Layout @@ -105,8 +105,8 @@ isoSPI communication ^^^^^^^^^^^^^^^^^^^^ The |bms-interface| offers up to four isolated isoSPI communication channels -using the |ltc6820| transceiver chip from |adi|. -The |ltc6820| transceivers are controlled by the SPI signals from the +using the |ltc-ltc6820| transceiver chip from |adi|. +The |ltc-ltc6820| transceivers are controlled by the SPI signals from the |bms-master|. The isoSPI signals are available on the connectors J101, J102, J103 and J104. The pinout of these connectors is described in diff --git a/docs/hardware/interfaces/ltc-ltc6820-vx.x.x/ltc-ltc6820-v1.0.3/ltc-ltc6820-v1.0.3_master_connector.csv b/docs/hardware/interfaces/ltc-ltc6820-vx.x.x/ltc-ltc6820-v1.0.3/ltc-ltc6820-v1.0.3_master_connector.csv index ece424a5..a6456428 100644 --- a/docs/hardware/interfaces/ltc-ltc6820-vx.x.x/ltc-ltc6820-v1.0.3/ltc-ltc6820-v1.0.3_master_connector.csv +++ b/docs/hardware/interfaces/ltc-ltc6820-vx.x.x/ltc-ltc6820-v1.0.3/ltc-ltc6820-v1.0.3_master_connector.csv @@ -22,14 +22,14 @@ Pin; Signal; Description; 21; ``IF_INT1``; Interrupt pin, connected to MCU GIOA_3; \- 22; ``IF_INT2``; Interrupt pin, connected to MCU GIOA_4; \- 23; ``IF_INT3``; Interrupt pin, connected to MCU GIOA_6; \- -24; ``IF_GPIO.0``; GPIO pin, connected to port expander 3 IO1_0; isoSPI channel 1 |ltc6820| enable -25; ``IF_GPIO.1``; GPIO pin, connected to port expander 3 IO1_1; isoSPI channel 1 |ltc6820| master -26; ``IF_GPIO.2``; GPIO pin, connected to port expander 3 IO1_2; isoSPI channel 2 |ltc6820| enable -27; ``IF_GPIO.3``; GPIO pin, connected to port expander 3 IO1_3; isoSPI channel 2 |ltc6820| master -28; ``IF_GPIO.4``; GPIO pin, connected to port expander 3 IO1_4; isoSPI channel 3 |ltc6820| enable -29; ``IF_GPIO.5``; GPIO pin, connected to port expander 3 IO1_5; isoSPI channel 3 |ltc6820| master -30; ``IF_GPIO.6``; GPIO pin, connected to port expander 3 IO1_6; isoSPI channel 4 |ltc6820| enable -31; ``IF_GPIO.7``; GPIO pin, connected to port expander 3 IO1_7; isoSPI channel 4 |ltc6820| master +24; ``IF_GPIO.0``; GPIO pin, connected to port expander 3 IO1_0; isoSPI channel 1 |ltc-ltc6820| enable +25; ``IF_GPIO.1``; GPIO pin, connected to port expander 3 IO1_1; isoSPI channel 1 |ltc-ltc6820| master +26; ``IF_GPIO.2``; GPIO pin, connected to port expander 3 IO1_2; isoSPI channel 2 |ltc-ltc6820| enable +27; ``IF_GPIO.3``; GPIO pin, connected to port expander 3 IO1_3; isoSPI channel 2 |ltc-ltc6820| master +28; ``IF_GPIO.4``; GPIO pin, connected to port expander 3 IO1_4; isoSPI channel 3 |ltc-ltc6820| enable +29; ``IF_GPIO.5``; GPIO pin, connected to port expander 3 IO1_5; isoSPI channel 3 |ltc-ltc6820| master +30; ``IF_GPIO.6``; GPIO pin, connected to port expander 3 IO1_6; isoSPI channel 4 |ltc-ltc6820| enable +31; ``IF_GPIO.7``; GPIO pin, connected to port expander 3 IO1_7; isoSPI channel 4 |ltc-ltc6820| master 32; ``GND``; Power supply ground; Power supply ground 33; ``GND``; Power supply ground; Power supply ground 34; ``PER_3.3V``; 3.3 |_| V from peripheral SBC; 3.3 |_| V power supply diff --git a/docs/hardware/interfaces/maxim-max17841b-vx.x.x/maxim-max17841b-v1.0.0.rst b/docs/hardware/interfaces/maxim-max17841b-vx.x.x/maxim-max17841b-v1.0.0.rst index c15bbc15..6e7ea7c2 100644 --- a/docs/hardware/interfaces/maxim-max17841b-vx.x.x/maxim-max17841b-v1.0.0.rst +++ b/docs/hardware/interfaces/maxim-max17841b-vx.x.x/maxim-max17841b-v1.0.0.rst @@ -14,7 +14,7 @@ Overview .. important:: - The following description only applies for the |max17841b|\ -based + The following description only applies for the |max-max17841b|\ -based |bms-interface| hardware version |local_interface_version|. .. hint:: @@ -70,7 +70,6 @@ The PCB design complies with the following parameters: - Clearance: 1.3 |_| |mm| - Creepage distance: 12.5 |_| |mm| - ^^^^^^^^^^^^^ Block Diagram ^^^^^^^^^^^^^ @@ -84,10 +83,10 @@ A block diagram of the |bms-interface| is shown in Block diagram of the |bms-interface| -Each |max17841b| communication chip from |mxm| provides one UART channel. +Each |max-max17841b| communication chip from |mxm| provides one UART channel. Each channel is comprised of a RX and a TX signal, each using one insulation transformer. -The |max17841b| chips are directly connected to the MCU via |spi|. +The |max-max17841b| chips are directly connected to the MCU via |spi|. ^^^^^^^^^^^^^^^^^^^^^^^^^^ Schematic and Board Layout @@ -109,8 +108,8 @@ Maxim Battery Management UART communication ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The |bms-interface| offers up to two isolated Maxim Battery Management UART -communication channels using the |max17841b| transceiver chip from |mxm|. -The |max17841b| transceivers are controlled by the SPI signals from the +communication channels using the |max-max17841b| transceiver chip from |mxm|. +The |max-max17841b| transceivers are controlled by the SPI signals from the |bms-master|. The UART RX signals are available on the connectors J102 and J104. The pinout of the connectors is described in diff --git a/docs/hardware/interfaces/nxp-mc33664-vx.x.x/nxp-mc33664-v1.0.2.rst b/docs/hardware/interfaces/nxp-mc33664-vx.x.x/nxp-mc33664-v1.0.2.rst index ea4f6f64..0a588604 100644 --- a/docs/hardware/interfaces/nxp-mc33664-vx.x.x/nxp-mc33664-v1.0.2.rst +++ b/docs/hardware/interfaces/nxp-mc33664-vx.x.x/nxp-mc33664-v1.0.2.rst @@ -14,7 +14,7 @@ Overview .. important:: - The following description only applies for the |mc33664|\ -based + The following description only applies for the |nxp-mc33664|\ -based |bms-interface| hardware version |local_interface_version|. .. hint:: @@ -41,7 +41,7 @@ The mechanical dimensions of this |BMS-Interface| are shown in :name: nxp-mc33664-v1.0.2_mechanical-dimensions :width: 50 % - Mechanical dimensions of the |mc33664|\ -based |bms-interface| hardware + Mechanical dimensions of the |nxp-mc33664|\ -based |bms-interface| hardware (version |local_interface_version|). ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/hardware/master.rst b/docs/hardware/master.rst index d545dfa6..a1d7afdd 100644 --- a/docs/hardware/master.rst +++ b/docs/hardware/master.rst @@ -9,14 +9,14 @@ Master Overview TI-based Masters ---------------- -The changelog for the |tms570lc4357|\ -based masters can be found at: +The changelog for the |ti-tms570lc4357|\ -based masters can be found at: .. toctree:: :maxdepth: 1 ./master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-changelog.rst -The documentation for the different versions of the |tms570lc4357|\ -based +The documentation for the different versions of the |ti-tms570lc4357|\ -based masters can be found at: .. toctree:: diff --git a/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-changelog.rst b/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-changelog.rst index d904d8c7..f37a8119 100644 --- a/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-changelog.rst +++ b/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-changelog.rst @@ -48,7 +48,6 @@ v1.1.2 - replaced Ethernet socket J2001 due to availability issues (old part number: Wuerth 615008185121, new part number: Wuerth 615008137421) - .. _CHANGELOG_FOR_MASTER_TMS570_V1_1_1: v1.1.1 @@ -71,7 +70,7 @@ v1.1.1 - modified all mounting holes to fit Wuerth SMT spacers (outer diameter = 6mm) - removed interlock high-side switch from default component variant due to availability issues -- added HW board version coding using IO1_0 to IO1_7 of port-expander1 +- added hardware board version coding using IO1_0 to IO1_7 of port-expander1 .. _CHANGELOG_FOR_MASTER_TMS570_V1_1_0: @@ -84,7 +83,7 @@ v1.1.0 - changed value of all I2C pull-up resistors from 5.1 |kOhm| to 2.49 |kOhm| - removed buck-boost converter IC from "default" component variant due to availability issues -- removed Ethernet phy IC from "default" component variant due to availability +- removed Ethernet PHY IC from "default" component variant due to availability issues - finalized PCB layout - added mechanical dimensions to draftman document @@ -107,7 +106,7 @@ v1.0.2 v1.0.1 ------ -- corrected the supply of Vdd of the smart power switch (from 12V to 5V) +- corrected the supply of V:sub:`dd` of the smart power switch (from 12V to 5V) .. _CHANGELOG_FOR_MASTER_TMS570_V1_0_0: diff --git a/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-v1.1.1.rst b/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-v1.1.1.rst index 2db6ae33..4e7af126 100644 --- a/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-v1.1.1.rst +++ b/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-v1.1.1.rst @@ -43,7 +43,6 @@ Height 13 mm Weight 129 g ================================================== ======= ======= - .. toctree:: :maxdepth: 1 diff --git a/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-v1.1.1/ti-tms570lc4357-v1.1.1_pinout.rst b/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-v1.1.1/ti-tms570lc4357-v1.1.1_pinout.rst index 9c2e0e08..1db6317c 100644 --- a/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-v1.1.1/ti-tms570lc4357-v1.1.1_pinout.rst +++ b/docs/hardware/master/ti-tms570lc4357-vx.x.x/ti-tms570lc4357-v1.1.1/ti-tms570lc4357-v1.1.1_pinout.rst @@ -90,7 +90,6 @@ The pinout is depicted in :numref:`Table %s `. :delim: , :file: ./pinout/ti-tms570lc4357-v1.1.1_interlock.csv - Smart Power Switches #################### diff --git a/docs/hardware/slaves.rst b/docs/hardware/slaves.rst index caf806b6..ebb43335 100644 --- a/docs/hardware/slaves.rst +++ b/docs/hardware/slaves.rst @@ -12,10 +12,10 @@ LTC-based Slaves LTC6804-1-based Slaves ++++++++++++++++++++++ -No changelog available for |ltc6804-1|\ - based slaves. +No changelog available for |ltc-ltc6804-1|\ - based slaves. -The documentation for the different versions of the |ltc6804-1|\ -based slaves -can be found at: +The documentation for the different versions of the |ltc-ltc6804-1|\ -based +slaves can be found at: .. toctree:: :maxdepth: 1 @@ -25,15 +25,15 @@ can be found at: LTC6811-1-based Slaves ++++++++++++++++++++++ -The changelog for the |ltc6811-1|\ -based slaves can be found at: +The changelog for the |ltc-ltc6811-1|\ -based slaves can be found at: .. toctree:: :maxdepth: 1 ./slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-changelog -The documentation for the different versions of the |ltc6811-1|\ -based slaves -can be found at: +The documentation for the different versions of the |ltc-ltc6811-1|\ -based +slaves can be found at: .. toctree:: :maxdepth: 1 @@ -45,15 +45,15 @@ can be found at: LTC6813-1-based Slaves ++++++++++++++++++++++ -The changelog for the |ltc6813-1|\ -based slaves can be found at: +The changelog for the |ltc-ltc6813-1|\ -based slaves can be found at: .. toctree:: :maxdepth: 1 ./slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-changelog -The documentation for the different versions of the |ltc6813-1|\ -based slaves -can be found at: +The documentation for the different versions of the |ltc-ltc6813-1|\ -based +slaves can be found at: .. toctree:: :maxdepth: 1 @@ -68,21 +68,42 @@ NXP-based Slaves MC33775A-based Slaves ++++++++++++++++++++++ -The changelog for the |mc33775a|\ -based slaves can be found at +The changelog for the |nxp-mc33775a|\ -based slaves can be found at .. toctree:: :maxdepth: 1 ./slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-changelog -The documentation for the different versions of the |mc33775a|\ -based slaves -can be found at: +The documentation for the different versions of the |nxp-mc33775a|\ -based +slaves can be found at: .. toctree:: :maxdepth: 1 ./slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-v1.0.0 +ADI-based Slaves +---------------- + +ADI ADES1830-based Slaves ++++++++++++++++++++++++++ + +The changelog for the |adi-ades1830|\ -based slaves can be found at: + +.. toctree:: + :maxdepth: 1 + + ./slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-changelog + +The documentation for the different versions of the |adi-ades1830|\ -based +slaves can be found at: + +.. toctree:: + :maxdepth: 1 + + ./slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0 + MAXIM-based Slaves ------------------ diff --git a/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x.rst b/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x.rst index e6bd6d8b..7c6a28b0 100644 --- a/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x.rst +++ b/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x.rst @@ -6,7 +6,6 @@ LTC6804-1-based 12-Cell Slave ``v1.x.x`` ======================================== - .. |local_slave_version| replace:: ``1.x.x`` -------- @@ -15,9 +14,8 @@ Overview .. important:: - The following description only applies for the |ltc6804-1|\ -based 12 cell - |BMS-Slave| hardware versions |local_slave_version|. - + The following description only applies for the |ltc-ltc6804-1|\ -based 12 + cell |BMS-Slave| hardware versions |local_slave_version|. .. hint:: @@ -61,7 +59,7 @@ The size of the PCB is 160x100mm. .. note:: This connector pin out is only valid for use of a foxBMS Master Interface - board for the |ltc6804-1| monitoring IC. + board for the |ltc-ltc6804-1| monitoring IC. On the |BMS-Slave|, the connectors indicated as ``Primary Daisy Chain connector`` and ``Secondary Daisy Chain connector`` in @@ -94,7 +92,7 @@ The connector indicated as ``Battery cell connector (16 pin)`` in :numref:`Fig. %s ` has two purposes: * Supply of the |BMS-Slave| - * Input of the cell voltages to the |ltc6804-1| analog front-end + * Input of the cell voltages to the |ltc-ltc6804-1| analog front-end The layout of the connector is described in :numref:`Table %s `. @@ -102,12 +100,19 @@ Up to 12 battery cells can be connected in series, between |VBAT+| and |VBAT-|. The |BMS-Slave| is supplied by |VBAT+| and |VBAT-|. The total voltage of all cells in series must be between 11V and 55V (see [ltc_data_sheet_6804]_ and [ltc_data_sheet_6811]_). -0- correspond to the negative pole of cell 0, 0+ to the positive pole of cell 0, 1- correspond to the negative pole of cell 1, 1+ to the positive pole of cell 1 and so one till 11+, the positive pole of cell 11. As the cells are connected in series, the positive pole of one cell is connected to the negative pole of the next cell: 0+ to 1-, 1+ to 2+ and so on. +0- correspond to the negative pole of cell 0, +0+ to the positive pole of cell 0, +1- correspond to the negative pole of cell 1, +1+ to the positive pole of cell 1 and so one +till 11+, the positive pole of cell 11. +As the cells are connected in series, the positive pole of one cell is +connected to the negative pole of the next cell: +0+ to 1-, 1+ to 2+ and so on. The poles should be connected to the cell voltage connector as shown in :numref:`Table %s `. If less than 12 battery cells are used, information on how to connect them can -be found |ltc6804-1| data sheets ([ltc_data_sheet_6804]_ and +be found |ltc-ltc6804-1| data sheets ([ltc_data_sheet_6804]_ and [ltc_data_sheet_6811]_). .. _cell_voltage_connector_layout: @@ -160,11 +165,11 @@ connector. Temperature sensor circuit. -The voltage VREF (3V) is generated by the |ltc6804-1| chip. +The voltage VREF (3V) is generated by the |ltc-ltc6804-1| chip. A temperature-dependent resistor must be added to build a voltage divider (drawn as a dashed line in :numref:`Fig. %s `, not delivered with the |bms-slaves|). -The resulting voltage is measured by the |ltc6804-1| chip. +The resulting voltage is measured by the |ltc-ltc6804-1| chip. Knowing the temperature dependence of the resistor, the relation between measured voltage and temperature can be determined. diff --git a/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x/12-ltc-ltc6804-1-v1.x.x_master_daisy_connector.csv b/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x/12-ltc-ltc6804-1-v1.x.x_master_daisy_connector.csv index d0ec477a..7745bded 100644 --- a/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x/12-ltc-ltc6804-1-v1.x.x_master_daisy_connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x/12-ltc-ltc6804-1-v1.x.x_master_daisy_connector.csv @@ -1,11 +1,11 @@ Pin; Signal 1; |NC| -2; |OUT+| (Secondary |ltc6804-1|) -3; |OUT-| (Secondary |ltc6804-1|) +2; |OUT+| (Secondary |ltc-ltc6804-1|) +3; |OUT-| (Secondary |ltc-ltc6804-1|) 4; |NC| 5; |NC| -6; |OUT+| (Primary |ltc6804-1|) -7; |OUT-| (Primary |ltc6804-1|) +6; |OUT+| (Primary |ltc-ltc6804-1|) +7; |OUT-| (Primary |ltc-ltc6804-1|) 8; |NC| 9; |NC| 10; |NC| diff --git a/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x/12-ltc-ltc6804-1-v1.x.x_primary_daisy_connector.csv b/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x/12-ltc-ltc6804-1-v1.x.x_primary_daisy_connector.csv index 21d48432..b09b4aa2 100644 --- a/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x/12-ltc-ltc6804-1-v1.x.x_primary_daisy_connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6804-1-vx.x.x/12-ltc-ltc6804-1-v1.x.x/12-ltc-ltc6804-1-v1.x.x_primary_daisy_connector.csv @@ -1,5 +1,5 @@ Pin; Daisy Chain -1; |IN+| (Primary |ltc6804-1|) -2; |OUT-| (Primary |ltc6804-1|) -3; |IN-| (Primary |ltc6804-1|) -4; |OUT+| (Primary |ltc6804-1|) +1; |IN+| (Primary |ltc-ltc6804-1|) +2; |OUT-| (Primary |ltc-ltc6804-1|) +3; |IN-| (Primary |ltc-ltc6804-1|) +4; |OUT+| (Primary |ltc-ltc6804-1|) diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-changelog.rst b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-changelog.rst index e8a5a8ca..e4317ab1 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-changelog.rst +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-changelog.rst @@ -1,19 +1,19 @@ .. include:: ./../../../macros.txt .. include:: ./../../../units.txt -.. _CHANGELOG_FOR_SLAVE_LTC6811_1: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1: -Changelog for Slave LTC6811-1 -============================= +Changelog for Slave LTC LTC6811-1 +================================= -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_1_7: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_1_7: v2.1.7 ------ - modified component designators to be compatible with 18cell versions -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_1_6: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_1_6: v2.1.6 ------ @@ -22,7 +22,7 @@ v2.1.6 - added RC filters on NTC sensor inputs - added DC/DC converters for 5V LTC supplies -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_1_5: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_1_5: v2.1.5 ------ @@ -30,7 +30,7 @@ v2.1.5 - Replaced opamps, port expanders and optocouplers with AEC-Q100 compliant ones - Modified silkscreen texts -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_1_4: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_1_4: v2.1.4 ------ @@ -38,14 +38,14 @@ v2.1.4 - Primary software timer is now switched on by default - added layermarker on PCB -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_1_3: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_1_3: v2.1.3 ------ - replaced EOL port expander with PCF8574 -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_1_2: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_1_2: v2.1.2 ------ @@ -54,7 +54,7 @@ v2.1.2 - created hierarchical design - introduced minor improvements to design -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_1_1: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_1_1: v2.1.1 ------ @@ -62,7 +62,7 @@ v2.1.1 - improved isolation distances between external DC/DC converter supply and battery module signals -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_1_0: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_1_0: v2.1.0 ------ @@ -72,23 +72,23 @@ v2.1.0 - switched connection of balancing resistors from serial to parallel - replaced isoSPI transformers HX1188NL with HM2102NL -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_0_3: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_0_3: v2.0.3 ------ - fixed isoSPI transformer CMC issue -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_0_2: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_0_2: v2.0.2 ------ -- replaced LTC1380 MUXs with ADG728 (400 kHz I2C) +- replaced LTC1380 multiplexer with ADG728 (400 kHz I2C) - adjusted connection of 100 ohm resistors for V+/V_REG supply - reduced value of I2C pull-up resistors to 1k2 -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_0_1: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_0_1: v2.0.1 ------ @@ -98,7 +98,7 @@ v2.0.1 - enlarged T201/301 cooling area - Replaced PCF8574 with PCA8574 (400 kHz I2C) -.. _CHANGELOG_FOR_SLAVE_LTC6811_1_v2_0_0: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6811_1_v2_0_0: v2.0.0 ------ diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3.rst b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3.rst index ef3bab7a..27fe3c4f 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3.rst +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3.rst @@ -15,8 +15,8 @@ Overview .. important:: - The following description only applies for the |ltc6811-1|\ -based 12 cell - |BMS-Slave| hardware versions |local_slave_version_start| to + The following description only applies for the |ltc-ltc6811-1|\ -based 12 + cell |BMS-Slave| hardware versions |local_slave_version_start| to |local_slave_version|. .. hint:: @@ -134,8 +134,8 @@ The passive balancing circuit is realized by a parallel connection of two 68 |Ohm| discharge resistors that can be connected to each single cell in parallel. The MOSFET switches (T701 - T712) that control the connection to the cells -are controlled by the primary |ltc6811-1| monitoring IC. -The secondary |ltc6811-1| does not support balancing. +are controlled by the primary |ltc-ltc6811-1| monitoring IC. +The secondary |ltc-ltc6811-1| does not support balancing. The resistor value of 2x 68 |Ohm| results in a balancing current of about 100mA at a cell voltage of 3.6V. This current results in a power dissipation of about 0.36W per balancing @@ -147,10 +147,10 @@ Global Cell Balancing Feedback In order to check the proper function of the balancing process or to detect a malfunction in the balancing circuit, a global balancing feedback signal is -connected to the |ltc6811-1|. +connected to the |ltc-ltc6811-1|. This allows the |BMS-Master| to check whether any balancing action is currently taking place. -The feedback signal is connected to the GPIO3 of the |ltc6811-1|. +The feedback signal is connected to the GPIO3 of the |ltc-ltc6811-1|. The signal remains in a logic zero state until any balancing action on at least one cell in the module starts. @@ -181,12 +181,12 @@ Using 8x 10\ |kOhm| NTC resistors with the corresponding 10\ |kOhm| series resistors results in a current of 1.2mA (at 20°C) which is drawn from VREF2. Each of the 8 temperature sensors are connected to an analog multiplexer. -The analog multiplexer can be controlled via |I2C| by the |ltc6811-1| +The analog multiplexer can be controlled via |I2C| by the |ltc-ltc6811-1| (7-bit address: 0x4C). In order to ensure fast settling times after switching the multiplexer input, the output signal of the multiplexer is buffered by an operational amplifier. Finally the analog voltage of the selected sensor is measured on the GPIO1 pin -of the |ltc6811-1|. +of the |ltc-ltc6811-1|. ^^^^^^^^^^^^^^^ On-board EEPROM @@ -202,7 +202,7 @@ with an EEPROM (IC1301 / IC1401). The EEPROM for example can be used for storing data such as calibration values or minimum and maximum temperatures seen by the module during its lifetime. Similar to the analog multiplexers, the EEPROM device is connected to the -|I2C| bus of the |ltc6811-1| (7-bit address: 0x50). +|I2C| bus of the |ltc-ltc6811-1| (7-bit address: 0x50). ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ On-board Ambient Temperature Sensor @@ -210,7 +210,7 @@ On-board Ambient Temperature Sensor For an additional monitoring of the ambient temperature an on-board temperature sensor is used. -This temperature sensor can be read by the |ltc6811-1| via the |I2C| bus +This temperature sensor can be read by the |ltc-ltc6811-1| via the |I2C| bus (7-bit address: 0x48). It is possible to program an alert temperature level. Once the measured temperature reaches this alert temperature level, the alert @@ -237,12 +237,12 @@ and is described in :file: ./12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_analog-inputs-connector.csv Each 8 analog inputs are connected to an analog multiplexer. -The analog multiplexers can be controlled via |I2C| by the |ltc6811-1| +The analog multiplexers can be controlled via |I2C| by the |ltc-ltc6811-1| (7-bit addresses: 0x4D and 0x4E). In order to ensure fast settling times after switching the multiplexer input, the output signals of the multiplexers are buffered by operational amplifiers. Finally the analog voltage of the selected sensor can be measured on the GPIO2 -pin of the |ltc6811-1|. +pin of the |ltc-ltc6811-1|. Each 8 digital inputs/outputs are provided on the connectors X1504 (primary) and X1505 (secondary). @@ -276,7 +276,7 @@ The isoSPI signals for daisy-chaining are output on the connectors X1510 The isoSPI connections are isolated galvanically using pulse transformers (TR201 / TR301). The voltage amplitude of the differential signal can be adjusted by setting -resistors (see paragraph :ref:`hw_slave_daisy_current_12cell`). +resistors (see paragraph :ref:`hardware_slave_daisy_current_12cell_v2.0.3`). The pinout of the isoSPI connectors is described in :numref:`Table %s <6811-1_slave_12cell_v2.0.3_daisy_input_connectors>` and @@ -304,7 +304,7 @@ Hardware Settings / Options Software Timer """""""""""""" -The internal software timer of the |ltc6811-1| can be enabled/disabled by a +The internal software timer of the |ltc-ltc6811-1| can be enabled/disabled by a dedicated external pin (SWTEN, pin 36). In order to support all features, the |BMS-Slave| board offers a possibility to switch the software timer. @@ -313,7 +313,7 @@ The software timer is disabled in the standard configuration, which means pin The timer can be enabled by removing the resistor R219/R319 and placing a zero-ohm resistor to R220/R320. -.. _hw_slave_daisy_current_12: +.. _hardware_slave_daisy_current_12cell_v2.0.3: Daisy Chain Communication Current """"""""""""""""""""""""""""""""" @@ -325,13 +325,13 @@ This values result in a bias current of approximately 1mA and a differential signal amplitude of 1.18V. Theses values are suitable for high noise environments with cable lengths of over 50m. -More information can be found in the |ltc6811-1| data sheet. +More information can be found in the |ltc-ltc6811-1| data sheet. Status LED """""""""" The status LEDs LD201 and LD301 show the current mode of each, the primary and -secondary |ltc6811-1|. +secondary |ltc-ltc6811-1|. The LED is on in STANDBY, REFUP or MEASURE mode, whereas the LED is off in SLEEP mode. The LED can be disabled by removing the resistor R205 (primary) or R305 @@ -340,7 +340,7 @@ The LED can be disabled by removing the resistor R205 (primary) or R305 GPIO Extension Connector """""""""""""""""""""""" -The internal GPIO lines of the primary or secondary |ltc6811-1| can be +The internal GPIO lines of the primary or secondary |ltc-ltc6811-1| can be connected to the GPIO extension pin header X1508 via optional zero-ohm resistors. In the standard configuration these resistors are not placed. diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_analog-inputs-connector.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_analog-inputs-connector.csv index a431f2b2..626b1ae7 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_analog-inputs-connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_analog-inputs-connector.csv @@ -15,5 +15,5 @@ Pin; Signal; Direction; Description 14; ANALOG-IN_13; Input; Analog input 13 15; ANALOG-IN_14; Input; Analog input 14 16; ANALOG-IN_15; Input; Analog input 15 -17; +3.0V_VREF2; Output; |ltc6811-1| 3.0V voltage reference +17; +3.0V_VREF2; Output; |ltc-ltc6811-1| 3.0V voltage reference 18; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_daisy-input-connectors.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_daisy-input-connectors.csv index bc3ad88d..29ee1616 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_daisy-input-connectors.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_daisy-input-connectors.csv @@ -1,3 +1,3 @@ Pin; Daisy Chain -1; |IN+| (Primary/Secondary |ltc6811-1|) -2; |IN-| (Primary/Secondary |ltc6811-1|) +1; |IN+| (Primary/Secondary |ltc-ltc6811-1|) +2; |IN-| (Primary/Secondary |ltc-ltc6811-1|) diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_daisy-output-connectors.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_daisy-output-connectors.csv index 22aa775f..61b00c94 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_daisy-output-connectors.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_daisy-output-connectors.csv @@ -1,3 +1,3 @@ Pin; Daisy Chain -1; |OUT+| (Primary/Secondary |ltc6811-1|) -2; |OUT-| (Primary/Secondary |ltc6811-1|) +1; |OUT+| (Primary/Secondary |ltc-ltc6811-1|) +2; |OUT-| (Primary/Secondary |ltc-ltc6811-1|) diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_digital-io-connector.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_digital-io-connector.csv index f6028aa0..b86460a8 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_digital-io-connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_digital-io-connector.csv @@ -6,5 +6,5 @@ Pin; Signal; Direction; Description 5; DIGITAL-IO_4; Input/Output; Digital input/output 4 6; DIGITAL-IO_5; Input/Output; Digital input/output 5 7; DIGITAL-IO_6; Input/Output; Digital input/output 6 -8; +5.0V_VREG; Output; |ltc6811-1| 5.0V regulated voltage +8; +5.0V_VREG; Output; |ltc-ltc6811-1| 5.0V regulated voltage 9; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_extension-connector.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_extension-connector.csv index 3520ef5e..f8944db7 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_extension-connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.0.3/12-ltc-ltc6811-1-v2.0.3_extension-connector.csv @@ -1,20 +1,20 @@ Pin; Signal; Direction; Description -1; +3.0V_VREF2_0; Output; Primary |ltc6811-1| 3.0V reference voltage 2 -2; +3.0V_VREF2_1; Output; Secondary |ltc6811-1| 3.0V reference voltage 2 -3; +5.0V_VREG_0; Output; Primary |ltc6811-1| 5.0V regulated voltage -4; +5.0V_VREG_1; Output; Secondary |ltc6811-1| 5.0V regulated voltage -5; PRIMARY-GPIO1-OPT; Input/Output; Primary |ltc6811-1| GPIO1 -6; SECONDARY-GPIO1-OPT; Input/Output; Secondary |ltc6811-1| GPIO1 -7; PRIMARY-GPIO2-OPT; Input/Output; Primary |ltc6811-1| GPIO2 -8; SECONDARY-GPIO2-OPT; Input/Output; Secondary |ltc6811-1| GPIO2 -9; PRIMARY-GPIO3-OPT; Input/Output; Primary |ltc6811-1| GPIO3 -10; SECONDARY-GPIO3-OPT; Input/Output; Secondary |ltc6811-1| GPIO3 -11; PRIMARY-GPIO4-OPT; Input/Output; Primary |ltc6811-1| GPIO4 -12; SECONDARY-GPIO4-OPT; Input/Output; Secondary |ltc6811-1| GPIO4 -13; PRIMARY-GPIO5-OPT; Input/Output; Primary |ltc6811-1| GPIO5 -14; SECONDARY-GPIO5-OPT; Input/Output; Secondary |ltc6811-1| GPIO5 -15; PRIMARY-WDT; Output; Primary |ltc6811-1| watchdog output -16; SECONDARY-WDT; Output; Secondary |ltc6811-1| watchdog output +1; +3.0V_VREF2_0; Output; Primary |ltc-ltc6811-1| 3.0V reference voltage 2 +2; +3.0V_VREF2_1; Output; Secondary |ltc-ltc6811-1| 3.0V reference voltage 2 +3; +5.0V_VREG_0; Output; Primary |ltc-ltc6811-1| 5.0V regulated voltage +4; +5.0V_VREG_1; Output; Secondary |ltc-ltc6811-1| 5.0V regulated voltage +5; PRIMARY-GPIO1-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO1 +6; SECONDARY-GPIO1-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO1 +7; PRIMARY-GPIO2-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO2 +8; SECONDARY-GPIO2-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO2 +9; PRIMARY-GPIO3-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO3 +10; SECONDARY-GPIO3-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO3 +11; PRIMARY-GPIO4-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO4 +12; SECONDARY-GPIO4-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO4 +13; PRIMARY-GPIO5-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO5 +14; SECONDARY-GPIO5-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO5 +15; PRIMARY-WDT; Output; Primary |ltc-ltc6811-1| watchdog output +16; SECONDARY-WDT; Output; Secondary |ltc-ltc6811-1| watchdog output 17; PRIMARY-TEMP-ALERT; Output; Primary board T-sensor alarm output 18; SECONDARY-TEMP-ALERT; Output; Secondary board T-sensor alarm output 19; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2.rst b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2.rst index 69b24f47..ca78a59b 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2.rst +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2.rst @@ -15,8 +15,8 @@ Overview .. important:: - The following description only applies for the |ltc6811-1|\ -based 12 cell - |BMS-Slave| hardware versions |local_slave_version_start| to + The following description only applies for the |ltc-ltc6811-1|\ -based 12 + cell |BMS-Slave| hardware versions |local_slave_version_start| to |local_slave_version|. .. hint:: @@ -134,8 +134,8 @@ The passive balancing circuit is realized by a parallel connection of two 68 |Ohm| discharge resistors that can be connected to each single cell in parallel. The MOSFET switches (T701 - T712) that control the connection to the cells -are controlled by the primary |ltc6811-1| monitoring IC. -The secondary |ltc6811-1| does not support balancing. +are controlled by the primary |ltc-ltc6811-1| monitoring IC. +The secondary |ltc-ltc6811-1| does not support balancing. The resistor value of 2x 68 |Ohm| results in a balancing current of about 100mA at a cell voltage of 3.6V. This current results in a power dissipation of about 0.36W per balancing @@ -147,10 +147,10 @@ Global Cell Balancing Feedback In order to check the proper function of the balancing process or to detect a malfunction in the balancing circuit, a global balancing feedback signal is -connected to the |ltc6811-1|. +connected to the |ltc-ltc6811-1|. This allows the |BMS-Master| to check whether any balancing action is currently taking place. -The feedback signal is connected to the GPIO3 of the |ltc6811-1|. +The feedback signal is connected to the GPIO3 of the |ltc-ltc6811-1|. The signal remains in a logic zero state until any balancing action on at least one cell in the module starts. @@ -181,12 +181,12 @@ Using 8x 10\ |kOhm| NTC resistors with the corresponding 10\ |kOhm| series resistors results in a current of 1.2mA (at 20°C) which is drawn from VREF2. Each of the 8 temperature sensors are connected to an analog multiplexer. -The analog multiplexer can be controlled via |I2C| by the |ltc6811-1| +The analog multiplexer can be controlled via |I2C| by the |ltc-ltc6811-1| (7-bit address: 0x4C). In order to ensure fast settling times after switching the multiplexer input, the output signal of the multiplexer is buffered by an operational amplifier. Finally the analog voltage of the selected sensor is measured on the GPIO1 pin -of the |ltc6811-1|. +of the |ltc-ltc6811-1|. ^^^^^^^^^^^^^^^ On-board EEPROM @@ -202,7 +202,7 @@ with an EEPROM (IC1301 / IC1401). The EEPROM for example can be used for storing data such as calibration values or minimum and maximum temperatures seen by the module during its lifetime. Similar to the analog multiplexers, the EEPROM device is connected to the -|I2C| bus of the |ltc6811-1| (7-bit address: 0x50). +|I2C| bus of the |ltc-ltc6811-1| (7-bit address: 0x50). ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ On-board Ambient Temperature Sensor @@ -210,7 +210,7 @@ On-board Ambient Temperature Sensor For an additional monitoring of the ambient temperature an on-board temperature sensor is used. -This temperature sensor can be read by the |ltc6811-1| via the |I2C| bus +This temperature sensor can be read by the |ltc-ltc6811-1| via the |I2C| bus (7-bit address: 0x48). It is possible to program an alert temperature level. Once the measured temperature reaches this alert temperature level, the alert @@ -237,12 +237,12 @@ and is described in :file: ./12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_analog-inputs-connector.csv Each 8 analog inputs are connected to an analog multiplexer. -The analog multiplexers can be controlled via |I2C| by the |ltc6811-1| +The analog multiplexers can be controlled via |I2C| by the |ltc-ltc6811-1| (7-bit addresses: 0x4D and 0x4E). In order to ensure fast settling times after switching the multiplexer input, the output signals of the multiplexers are buffered by operational amplifiers. Finally the analog voltage of the selected sensor can be measured on the GPIO2 -pin of the |ltc6811-1|. +pin of the |ltc-ltc6811-1|. Each 8 digital inputs/outputs are provided on the connectors X1504 (primary) and X1505 (secondary). @@ -276,7 +276,7 @@ The isoSPI signals for daisy-chaining are output on the connectors X1510 The isoSPI connections are isolated galvanically using pulse transformers (TR201 / TR301). The voltage amplitude of the differential signal can be adjusted by setting -resistors (see paragraph :ref:`hw_slave_daisy_current_12cell`). +resistors (see paragraph :ref:`hardware_slave_daisy_current_12cell_v2.1.2`). The pinout of the isoSPI connectors is described in :numref:`Table %s <6811-1_slave_12cell_v2.1.2_daisy_input_connectors>` and @@ -304,8 +304,8 @@ Hardware Settings / Options Software Timer """""""""""""" -The internal software timer of the |ltc6811-1| can be enabled/disabled by a -dedicated external pin (SWTEN, pin 36 of the |ltc6811-1|). +The internal software timer of the |ltc-ltc6811-1| can be enabled/disabled by a +dedicated external pin (SWTEN, pin 36 of the |ltc-ltc6811-1|). In order to support all features, the |BMS-Slave| board offers a possibility to switch the software timer. The software timer is enabled in the standard configuration, which means pin 36 @@ -313,7 +313,7 @@ is pulled to VREG via a zero-ohm resistor (R221/R321). The timer can be disabled by removing the resistor R221/R321 and placing a zero-ohm resistor to R220/R320. -.. _hw_slave_daisy_current_12cell: +.. _hardware_slave_daisy_current_12cell_v2.1.2: Daisy Chain Communication Current """"""""""""""""""""""""""""""""" @@ -325,13 +325,13 @@ This values result in a bias current of approximately 1mA and a differential signal amplitude of 1.18V. Theses values are suitable for high noise environments with cable lengths of over 50m. -More information can be found in the |ltc6811-1| data sheet. +More information can be found in the |ltc-ltc6811-1| data sheet. Status LED """""""""" The status LEDs LD201 and LD301 show the current mode of each, the primary and -secondary |ltc6811-1|. +secondary |ltc-ltc6811-1|. The LED is on in STANDBY, REFUP or MEASURE mode, whereas the LED is off in SLEEP mode. The LED can be disabled by removing the resistor R205 (primary) or R305 @@ -340,7 +340,7 @@ The LED can be disabled by removing the resistor R205 (primary) or R305 GPIO Extension Connector """""""""""""""""""""""" -The internal GPIO lines of the primary or secondary |ltc6811-1| can be +The internal GPIO lines of the primary or secondary |ltc-ltc6811-1| can be connected to the GPIO extension pin header X1508 via optional zero-ohm resistors. In the standard configuration these resistors are not placed. diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_analog-inputs-connector.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_analog-inputs-connector.csv index 2bca35fc..6c138e9a 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_analog-inputs-connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_analog-inputs-connector.csv @@ -15,5 +15,5 @@ Pin; Signal; Direction; Description 14; ANALOG-IN_13; Input; Analog input 13 15; ANALOG-IN_14; Input; Analog input 14 16; ANALOG-IN_15; Input; Analog input 15 -17; +3.0V_VREF2; Output; |ltc6811-1| 3.0V voltage reference +17; +3.0V_VREF2; Output; |ltc-ltc6811-1| 3.0V voltage reference 18; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_daisy-input-connectors.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_daisy-input-connectors.csv index 07a316ff..09230d6e 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_daisy-input-connectors.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_daisy-input-connectors.csv @@ -1,3 +1,3 @@ Pin; Daisy Chain -1; |IN+| (Primary/Secondary |ltc6811-1|) -2; |IN-| (Primary/Secondary |ltc6811-1|) +1; |IN+| (Primary/Secondary |ltc-ltc6811-1|) +2; |IN-| (Primary/Secondary |ltc-ltc6811-1|) diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_daisy-output-connectors.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_daisy-output-connectors.csv index 43ffe9e0..6895bbbe 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_daisy-output-connectors.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_daisy-output-connectors.csv @@ -1,3 +1,3 @@ Pin; Daisy Chain -1; |OUT+| (Primary/Secondary |ltc6811-1|) -2; |OUT-| (Primary/Secondary |ltc6811-1|) +1; |OUT+| (Primary/Secondary |ltc-ltc6811-1|) +2; |OUT-| (Primary/Secondary |ltc-ltc6811-1|) diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_digital-io-connector.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_digital-io-connector.csv index a5d4c8f8..4c55cfb2 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_digital-io-connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_digital-io-connector.csv @@ -6,5 +6,5 @@ Pin; Signal; Direction; Description 5; DIGITAL-IO_4; Input/Output; Digital input/output 4 6; DIGITAL-IO_5; Input/Output; Digital input/output 5 7; DIGITAL-IO_6; Input/Output; Digital input/output 6 -8; 5.0V_VREG; Output; |ltc6811-1| 5.0V regulated voltage +8; 5.0V_VREG; Output; |ltc-ltc6811-1| 5.0V regulated voltage 9; FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_extension-connector.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_extension-connector.csv index 38bf2646..55fcf52f 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_extension-connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.2/12-ltc-ltc6811-1-v2.1.2_extension-connector.csv @@ -1,20 +1,20 @@ Pin; Signal Direction; Description -1; +3.0V_VREF2_0 Output; Primary |ltc6811-1| 3.0V reference voltage 2 -2; +3.0V_VREF2_1 Output; Secondary |ltc6811-1| 3.0V reference voltage 2 -3; +5.0V_VREG_0 Output; Primary |ltc6811-1| 5.0V regulated voltage -4; +5.0V_VREG_1 Output; Secondary |ltc6811-1| 5.0V regulated voltage -5; PRIMARY-GPIO1-OPT Input/Output; Primary |ltc6811-1| GPIO1 -6; SECONDARY-GPIO1-OPT Input/Output; Secondary |ltc6811-1| GPIO1 -7; PRIMARY-GPIO2-OPT Input/Output; Primary |ltc6811-1| GPIO2 -8; SECONDARY-GPIO2-OPT Input/Output; Secondary |ltc6811-1| GPIO2 -9; PRIMARY-GPIO3-OPT Input/Output; Primary |ltc6811-1| GPIO3 -10; SECONDARY-GPIO3-OPT Input/Output; Secondary |ltc6811-1| GPIO3 -11; PRIMARY-GPIO4-OPT Input/Output; Primary |ltc6811-1| GPIO4 -12; SECONDARY-GPIO4-OPT Input/Output; Secondary |ltc6811-1| GPIO4 -13; PRIMARY-GPIO5-OPT Input/Output; Primary |ltc6811-1| GPIO5 -14; SECONDARY-GPIO5-OPT Input/Output; Secondary |ltc6811-1| GPIO5 -15; PRIMARY-WDT Output; Primary |ltc6811-1| watchdog output -16; SECONDARY-WDT Output; Secondary |ltc6811-1| watchdog output +1; +3.0V_VREF2_0 Output; Primary |ltc-ltc6811-1| 3.0V reference voltage 2 +2; +3.0V_VREF2_1 Output; Secondary |ltc-ltc6811-1| 3.0V reference voltage 2 +3; +5.0V_VREG_0 Output; Primary |ltc-ltc6811-1| 5.0V regulated voltage +4; +5.0V_VREG_1 Output; Secondary |ltc-ltc6811-1| 5.0V regulated voltage +5; PRIMARY-GPIO1-OPT Input/Output; Primary |ltc-ltc6811-1| GPIO1 +6; SECONDARY-GPIO1-OPT Input/Output; Secondary |ltc-ltc6811-1| GPIO1 +7; PRIMARY-GPIO2-OPT Input/Output; Primary |ltc-ltc6811-1| GPIO2 +8; SECONDARY-GPIO2-OPT Input/Output; Secondary |ltc-ltc6811-1| GPIO2 +9; PRIMARY-GPIO3-OPT Input/Output; Primary |ltc-ltc6811-1| GPIO3 +10; SECONDARY-GPIO3-OPT Input/Output; Secondary |ltc-ltc6811-1| GPIO3 +11; PRIMARY-GPIO4-OPT Input/Output; Primary |ltc-ltc6811-1| GPIO4 +12; SECONDARY-GPIO4-OPT Input/Output; Secondary |ltc-ltc6811-1| GPIO4 +13; PRIMARY-GPIO5-OPT Input/Output; Primary |ltc-ltc6811-1| GPIO5 +14; SECONDARY-GPIO5-OPT Input/Output; Secondary |ltc-ltc6811-1| GPIO5 +15; PRIMARY-WDT Output; Primary |ltc-ltc6811-1| watchdog output +16; SECONDARY-WDT Output; Secondary |ltc-ltc6811-1| watchdog output 17; PRIMARY-TEMP-ALERT Output; Primary board T-sensor alarm output 18; SECONDARY-TEMP-ALERT Output; Secondary board T-sensor alarm output 19; |FUSED_VBAT-| Output; GND diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6.rst b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6.rst index 90ddcd3e..c15b226b 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6.rst +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6.rst @@ -15,8 +15,8 @@ Overview .. important:: - The following description only applies for the |ltc6811-1|\ -based 12 cell - |BMS-Slave| hardware versions |local_slave_version_start| to + The following description only applies for the |ltc-ltc6811-1|\ -based 12 + cell |BMS-Slave| hardware versions |local_slave_version_start| to |local_slave_version|. .. hint:: @@ -134,8 +134,8 @@ The passive balancing circuit is realized by a parallel connection of two 68 |Ohm| discharge resistors that can be connected to each single cell in parallel. The MOSFET switches (T1500 - T1511) that control the connection to the cells -are controlled by the primary |ltc6811-1| monitoring IC. -The secondary |ltc6811-1| does not support balancing. +are controlled by the primary |ltc-ltc6811-1| monitoring IC. +The secondary |ltc-ltc6811-1| does not support balancing. The resistor value of 2x 68 |Ohm| results in a balancing current of about 100mA at a cell voltage of 3.6V. This current results in a power dissipation of about 0.36W per balancing @@ -147,10 +147,10 @@ Global Cell Balancing Feedback In order to check the proper function of the balancing process or to detect a malfunction in the balancing circuit, a global balancing feedback signal is -connected to the |ltc6811-1|. +connected to the |ltc-ltc6811-1|. This allows the |BMS-Master| to check whether any balancing action is currently taking place. -The feedback signal is connected to the GPIO3 of the |ltc6811-1|. +The feedback signal is connected to the GPIO3 of the |ltc-ltc6811-1|. The signal remains in a logic zero state until any balancing action on at least one cell in the module starts. @@ -181,12 +181,12 @@ Using 8x 10\ |kOhm| NTC resistors with the corresponding 10\ |kOhm| series resistors results in a current of 1.2mA (at 20°C) which is drawn from VREF2. Each of the 8 temperature sensors are connected to an analog multiplexer. -The analog multiplexer can be controlled via |I2C| by the |ltc6811-1| +The analog multiplexer can be controlled via |I2C| by the |ltc-ltc6811-1| (7-bit address: 0x4C). In order to ensure fast settling times after switching the multiplexer input, the output signal of the multiplexer is buffered by an operational amplifier. Finally the analog voltage of the selected sensor is measured on the GPIO1 pin -of the |ltc6811-1|. +of the |ltc-ltc6811-1|. ^^^^^^^^^^^^^^^ On-board EEPROM @@ -202,7 +202,7 @@ with an EEPROM (IC800-1/2). The EEPROM for example can be used for storing data such as calibration values or minimum and maximum temperatures seen by the module during its lifetime. Similar to the analog multiplexers, the EEPROM device is connected to the -|I2C| bus of the |ltc6811-1| (7-bit address: 0x50). +|I2C| bus of the |ltc-ltc6811-1| (7-bit address: 0x50). ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ On-board Ambient Temperature Sensor @@ -210,7 +210,7 @@ On-board Ambient Temperature Sensor For an additional monitoring of the ambient temperature an on-board temperature sensor is used. -This temperature sensor can be read by the |ltc6811-1| via the |I2C| bus +This temperature sensor can be read by the |ltc-ltc6811-1| via the |I2C| bus (7-bit address: 0x48). It is possible to program an alert temperature level. Once the measured temperature reaches this alert temperature level, the alert @@ -237,12 +237,12 @@ and is described in :file: ./12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_analog-inputs-connector.csv Each 8 analog inputs are connected to an analog multiplexer. -The analog multiplexers can be controlled via |I2C| by the |ltc6811-1| +The analog multiplexers can be controlled via |I2C| by the |ltc-ltc6811-1| (7-bit addresses: 0x4D and 0x4E). In order to ensure fast settling times after switching the multiplexer input, the output signals of the multiplexers are buffered by operational amplifiers. Finally the analog voltage of the selected sensor can be measured on the GPIO2 -pin of the |ltc6811-1|. +pin of the |ltc-ltc6811-1|. Each 8 digital inputs/outputs are provided on the connectors X401 (primary) and X404 (secondary). @@ -276,7 +276,7 @@ The isoSPI signals for daisy-chaining are output on the connectors X501 The isoSPI connections are isolated galvanically using pulse transformers (TR1400-1/2). The voltage amplitude of the differential signal can be adjusted by setting -resistors (see paragraph :ref:`hw_slave_daisy_current_12cell_v2.1.6`). +resistors (see paragraph :ref:`hardware_slave_daisy_current_12cell_v2.1.6`). The pinout of the isoSPI connectors is described in :numref:`Table %s <6811-1_slave_12cell_v2.1.6_daisy_input_connectors>` and @@ -304,8 +304,8 @@ Hardware Settings / Options Software Timer """""""""""""" -The internal software timer of the |ltc6811-1| can be enabled/disabled by a -dedicated external pin (SWTEN, pin 36 of the |ltc6811-1|). +The internal software timer of the |ltc-ltc6811-1| can be enabled/disabled by a +dedicated external pin (SWTEN, pin 36 of the |ltc-ltc6811-1|). In order to support all features, the |BMS-Slave| board offers a possibility to switch the software timer. The software timer is enabled in the standard configuration, which means pin 36 @@ -313,7 +313,7 @@ is pulled to VREG via a zero-ohm resistor (R221/R321). The timer can be disabled by removing the resistor R1402-1/2 and placing a zero-ohm resistor to R1403-1/2. -.. _hw_slave_daisy_current_12cell_v2.1.6: +.. _hardware_slave_daisy_current_12cell_v2.1.6: Daisy Chain Communication Current """"""""""""""""""""""""""""""""" @@ -325,13 +325,13 @@ This values result in a bias current of approximately 1mA and a differential signal amplitude of 1.18V. Theses values are suitable for high noise environments with cable lengths of over 50m. -More information can be found in the |ltc6811-1| data sheet. +More information can be found in the |ltc-ltc6811-1| data sheet. Status LED """""""""" The status LEDs LD1400-1/2 show the current mode of each, the primary and -secondary |ltc6811-1|. +secondary |ltc-ltc6811-1|. The LED is on in STANDBY, REFUP or MEASURE mode, whereas the LED is off in SLEEP mode. The LED can be disabled by removing the resistor R1407-1/2. @@ -339,7 +339,7 @@ The LED can be disabled by removing the resistor R1407-1/2. GPIO Extension Connector """""""""""""""""""""""" -The internal GPIO lines of the primary or secondary |ltc6811-1| can be +The internal GPIO lines of the primary or secondary |ltc-ltc6811-1| can be connected to the GPIO extension pin header X402 via optional zero-ohm resistors. In the standard configuration these resistors are not placed. diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_analog-inputs-connector.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_analog-inputs-connector.csv index 2bca35fc..6c138e9a 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_analog-inputs-connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_analog-inputs-connector.csv @@ -15,5 +15,5 @@ Pin; Signal; Direction; Description 14; ANALOG-IN_13; Input; Analog input 13 15; ANALOG-IN_14; Input; Analog input 14 16; ANALOG-IN_15; Input; Analog input 15 -17; +3.0V_VREF2; Output; |ltc6811-1| 3.0V voltage reference +17; +3.0V_VREF2; Output; |ltc-ltc6811-1| 3.0V voltage reference 18; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_daisy-input-connectors.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_daisy-input-connectors.csv index bc3ad88d..29ee1616 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_daisy-input-connectors.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_daisy-input-connectors.csv @@ -1,3 +1,3 @@ Pin; Daisy Chain -1; |IN+| (Primary/Secondary |ltc6811-1|) -2; |IN-| (Primary/Secondary |ltc6811-1|) +1; |IN+| (Primary/Secondary |ltc-ltc6811-1|) +2; |IN-| (Primary/Secondary |ltc-ltc6811-1|) diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_daisy-output-connectors.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_daisy-output-connectors.csv index 22aa775f..61b00c94 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_daisy-output-connectors.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_daisy-output-connectors.csv @@ -1,3 +1,3 @@ Pin; Daisy Chain -1; |OUT+| (Primary/Secondary |ltc6811-1|) -2; |OUT-| (Primary/Secondary |ltc6811-1|) +1; |OUT+| (Primary/Secondary |ltc-ltc6811-1|) +2; |OUT-| (Primary/Secondary |ltc-ltc6811-1|) diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_digital-io-connector.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_digital-io-connector.csv index f6028aa0..b86460a8 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_digital-io-connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_digital-io-connector.csv @@ -6,5 +6,5 @@ Pin; Signal; Direction; Description 5; DIGITAL-IO_4; Input/Output; Digital input/output 4 6; DIGITAL-IO_5; Input/Output; Digital input/output 5 7; DIGITAL-IO_6; Input/Output; Digital input/output 6 -8; +5.0V_VREG; Output; |ltc6811-1| 5.0V regulated voltage +8; +5.0V_VREG; Output; |ltc-ltc6811-1| 5.0V regulated voltage 9; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_extension-connector.csv b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_extension-connector.csv index 3520ef5e..f8944db7 100644 --- a/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_extension-connector.csv +++ b/docs/hardware/slaves/12-ltc-ltc6811-1-vx.x.x/12-ltc-ltc6811-1-v2.1.6/12-ltc-ltc6811-1-v2.1.6_extension-connector.csv @@ -1,20 +1,20 @@ Pin; Signal; Direction; Description -1; +3.0V_VREF2_0; Output; Primary |ltc6811-1| 3.0V reference voltage 2 -2; +3.0V_VREF2_1; Output; Secondary |ltc6811-1| 3.0V reference voltage 2 -3; +5.0V_VREG_0; Output; Primary |ltc6811-1| 5.0V regulated voltage -4; +5.0V_VREG_1; Output; Secondary |ltc6811-1| 5.0V regulated voltage -5; PRIMARY-GPIO1-OPT; Input/Output; Primary |ltc6811-1| GPIO1 -6; SECONDARY-GPIO1-OPT; Input/Output; Secondary |ltc6811-1| GPIO1 -7; PRIMARY-GPIO2-OPT; Input/Output; Primary |ltc6811-1| GPIO2 -8; SECONDARY-GPIO2-OPT; Input/Output; Secondary |ltc6811-1| GPIO2 -9; PRIMARY-GPIO3-OPT; Input/Output; Primary |ltc6811-1| GPIO3 -10; SECONDARY-GPIO3-OPT; Input/Output; Secondary |ltc6811-1| GPIO3 -11; PRIMARY-GPIO4-OPT; Input/Output; Primary |ltc6811-1| GPIO4 -12; SECONDARY-GPIO4-OPT; Input/Output; Secondary |ltc6811-1| GPIO4 -13; PRIMARY-GPIO5-OPT; Input/Output; Primary |ltc6811-1| GPIO5 -14; SECONDARY-GPIO5-OPT; Input/Output; Secondary |ltc6811-1| GPIO5 -15; PRIMARY-WDT; Output; Primary |ltc6811-1| watchdog output -16; SECONDARY-WDT; Output; Secondary |ltc6811-1| watchdog output +1; +3.0V_VREF2_0; Output; Primary |ltc-ltc6811-1| 3.0V reference voltage 2 +2; +3.0V_VREF2_1; Output; Secondary |ltc-ltc6811-1| 3.0V reference voltage 2 +3; +5.0V_VREG_0; Output; Primary |ltc-ltc6811-1| 5.0V regulated voltage +4; +5.0V_VREG_1; Output; Secondary |ltc-ltc6811-1| 5.0V regulated voltage +5; PRIMARY-GPIO1-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO1 +6; SECONDARY-GPIO1-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO1 +7; PRIMARY-GPIO2-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO2 +8; SECONDARY-GPIO2-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO2 +9; PRIMARY-GPIO3-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO3 +10; SECONDARY-GPIO3-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO3 +11; PRIMARY-GPIO4-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO4 +12; SECONDARY-GPIO4-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO4 +13; PRIMARY-GPIO5-OPT; Input/Output; Primary |ltc-ltc6811-1| GPIO5 +14; SECONDARY-GPIO5-OPT; Input/Output; Secondary |ltc-ltc6811-1| GPIO5 +15; PRIMARY-WDT; Output; Primary |ltc-ltc6811-1| watchdog output +16; SECONDARY-WDT; Output; Secondary |ltc-ltc6811-1| watchdog output 17; PRIMARY-TEMP-ALERT; Output; Primary board T-sensor alarm output 18; SECONDARY-TEMP-ALERT; Output; Secondary board T-sensor alarm output 19; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-changelog.rst b/docs/hardware/slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-changelog.rst index 94b8c770..3fad77f5 100644 --- a/docs/hardware/slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-changelog.rst +++ b/docs/hardware/slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-changelog.rst @@ -1,12 +1,12 @@ .. include:: ./../../../macros.txt .. include:: ./../../../units.txt -.. _CHANGELOG_FOR_SLAVE_MC33775: +.. _CHANGELOG_FOR_SLAVE_NXP_MC33775A: -Changelog for Slave MC33775 -=========================== +Changelog for Slave NXP MC33775A +================================ -.. _CHANGELOG_FOR_SLAVE_MC33775_V1_0_0: +.. _CHANGELOG_FOR_SLAVE_NXP_MC33775A_V1_0_0: v1.0.0 ------ diff --git a/docs/hardware/slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-v1.0.0.rst b/docs/hardware/slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-v1.0.0.rst index 8e3216e7..6e074309 100644 --- a/docs/hardware/slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-v1.0.0.rst +++ b/docs/hardware/slaves/14-nxp-mc33775a-vx.x.x/14-nxp-mc33775a-v1.0.0.rst @@ -1,15 +1,15 @@ .. include:: ./../../../macros.txt .. include:: ./../../../units.txt -.. _MC33775A_BASED_14_CELL_SLAVE___V1_0_0__: +.. _NXP_MC33775A_BASED_14_CELL_SLAVE___V1_0_0__: -MC33775A-based 14-Cell Slave ``v1.0.0`` -======================================= +NXP MC33775A-based 14-Cell Slave ``v1.0.0`` +=========================================== .. note:: The changelog for this release is found at - :ref:`CHANGELOG_FOR_SLAVE_MC33775_V1_0_0`. + :ref:`CHANGELOG_FOR_SLAVE_NXP_MC33775A_V1_0_0`. .. |local_slave_version| replace:: ``1.0.0`` @@ -19,8 +19,8 @@ Overview .. important:: - The following description only applies for the |mc33775a|\ -based 14 cell - |BMS-Slave| hardware version |local_slave_version|. + The following description only applies for the |nxp-mc33775a|\ -based 14 + cell |BMS-Slave| hardware version |local_slave_version|. .. hint:: diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-changelog.rst b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-changelog.rst new file mode 100644 index 00000000..ce0f1e42 --- /dev/null +++ b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-changelog.rst @@ -0,0 +1,14 @@ +.. include:: ./../../../macros.txt +.. include:: ./../../../units.txt + +.. _CHANGELOG_FOR_SLAVE_ADI_ADES1830: + +Changelog for Slave ADI ADES1830 +================================ + +.. _CHANGELOG_FOR_SLAVE_ADI_ADES1830_V0_9_0: + +v0.9.0 +------ + +- initial release diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0.rst b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0.rst new file mode 100644 index 00000000..3bba4b00 --- /dev/null +++ b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0.rst @@ -0,0 +1,192 @@ +.. include:: ./../../../macros.txt +.. include:: ./../../../units.txt + +.. _ADI_ADES1830_BASED_16_CELL_SLAVE___V0_9_0__: + +ADI ADES1830-based 16-Cell Slave ``v0.9.0`` +=========================================== + +.. note:: + + The changelog for this release is found at + :ref:`CHANGELOG_FOR_SLAVE_ADI_ADES1830_V0_9_0`. + +.. |local_slave_version| replace:: ``0.9.0`` + +-------- +Overview +-------- + +.. important:: + + The following description only applies for the |adi-ades1830|\ -based 16 + cell |BMS-Slave| hardware version |local_slave_version|. + +.. hint:: + + All connector pinouts described below follow the + :ref:`CONVENTION_FOR_MOLEX_3_0_CONNECTOR_PIN_NUMBERING`. + +-------------- +Specifications +-------------- + +^^^^^^^^^^^^^^^^^^ +Electrical Ratings +^^^^^^^^^^^^^^^^^^ + +The current consumption from the module has been measured at 57.6 |_| V module +voltage, which is equivalent to a cell voltage of 3.6 |_| V per cell. +No sense lines have been connected for this measurement (as the impact of cell +voltage sensing is negligible on the current consumption). + + +.. csv-table:: Electrical Ratings + :name: adi_ades1830_slave_18cell_v0.9.0_electrical_ratings + :header-rows: 1 + :delim: ; + :file: ./16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_electrical-ratings.csv + +^^^^^^^^^^^^^^^^^^^^^ +Mechanical Dimensions +^^^^^^^^^^^^^^^^^^^^^ + +.. csv-table:: Mechanical Dimensions + :name: adi_ades1830_slave_18cell_v0.9.0_mechanical_dimensions + :header-rows: 1 + :delim: ; + :file: ./16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_mechanical-dimensions.csv + +^^^^^^^^^^^^^ +Block Diagram +^^^^^^^^^^^^^ + +The block diagram of the |BMS-Slave| is shown in +:numref:`Fig. %s `. + +.. _block_diagram_adi_ades1830_slave_18cell_v0.9.0: +.. figure:: ./16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0.png + :width: 100 % + + |BMS-Slave| 16-Cell Block Diagram + +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Schematic and Board Layout +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +More information about the board schematic and layout files can be found in +section :ref:`DESIGN_RESOURCES`. + +--------- +Functions +--------- + +^^^^^^^^^^^^^^^^^^^^^^^^ +Cell Voltage Measurement +^^^^^^^^^^^^^^^^^^^^^^^^ + +The cell voltage sense lines are input on the connector J400. +The pinout is described in +:numref:`Table %s `. + +.. figure:: ./../../img/molex_connector-24pin.png + :width: 50 % + +.. csv-table:: Cell voltage sense connector + :name: adi_ades1830_slave_16cell_v0.9.0_cell_sense_connector + :header-rows: 1 + :delim: ; + :file: ./16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_cell_voltage-sense-connector.csv + + +The |VBAT+| and |VBAT-| connection is used for the internal power supply of the +slave board. + +The cell input lines are filtered by differential capacitor +filter: +both possibilities are provided on the PCB of the |BMS-Slave|. +More information on the corner frequency of this filtering can be found in the +schematic. +The differential capacitor filter can be used when noise is less frequent or +the design is subjected to cost optimization. + +^^^^^^^^^^^^^^^^^^^^^^ +Passive Cell Balancing +^^^^^^^^^^^^^^^^^^^^^^ + +The passive balancing circuit is realized by a series connection of two +30 |Ohm| discharge-resistors that can be connected to each single cell in +parallel. +The balancing process is controlled by the |adi-ades1830| monitoring IC. +The resistor value of 2x 30 |_| |Ohm| results in a balancing current of about +60 |_| mA at a cell voltage of 3.6 |_| V. +This current results in a power dissipation of about 0.2W per balancing +channel (at 3.6 |_| V). + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Temperature Sensor Measurement +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The cell temperature sensors are connected to the connectors J403. + +The pinout is described in +:numref:`Table %s `. + +.. figure:: ./../../img/molex_connector-20pin.png + :width: 30 % + +.. csv-table:: Temperature sensor connector + :name: adi_ades1830_slave_16cell_v0.9.0_temp_sense_connector + :header-rows: 1 + :delim: ; + :file: ./16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_temperature-sensor-connector.csv + +Standard 10 |_| |kOhm| NTC resistors are recommended for use. +When using other values than these, the series resistors +(R517-R526) on the board may have to be adjusted. +Please note that the accuracy of the internal voltage reference VREF2 decreases +heavily with a load of over 3 |_| mA. +Using 10x 10 |_| |kOhm| NTC resistors with the corresponding 10 |_| |kOhm| +series resistors results in a current of 1.5mA (at 20 |_| °C) which is drawn +from VREF2. + +Each 10 temperature sensors are connected to an GPIO pin of the |adi-ades1830|. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +isoSPI Daisy Chain Connection +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The data transmission between the slaves and between the slaves and BMS master +uses the isoSPI interface. +The isoSPI signals are input/output on the connectors J501/J402. +The isoSPI ports are bidirectional, that means they can be used in forward and +reverse direction. +The isoSPI connections are isolated galvanically using pulse transformers +(T500/T501). + + +The pinout of the isoSPI connectors is described in +:numref:`Table %s ` +and +:numref:`Table %s `. + +.. figure:: ./../../img/molex_connector-2pin.png + :width: 5 % + +.. csv-table:: isoSPI Daisy Chain Input Connectors + :name: adi_ades1830_slave_16cell_v0.9.0_daisy_input_connectors + :header-rows: 1 + :delim: ; + :file: ./16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_daisy-input-connectors.csv + +.. csv-table:: isoSPI Daisy Chain Output Connectors + :name: adi_ades1830_slave_16cell_v0.9.0_daisy_output_connectors + :header-rows: 1 + :delim: ; + :file: ./16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_daisy-output-connectors.csv + +------------------------------ +Software Driver Implementation +------------------------------ + +The driver implementation for this AFE is documented at :ref:`ADI_ADES1830`. diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0.png b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0.png new file mode 100644 index 00000000..28ab0e9e Binary files /dev/null and b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0.png differ diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0.vsdx b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0.vsdx new file mode 100644 index 00000000..f96def82 Binary files /dev/null and b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0.vsdx differ diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_cell_voltage-sense-connector.csv b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_cell_voltage-sense-connector.csv new file mode 100644 index 00000000..17024d33 --- /dev/null +++ b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_cell_voltage-sense-connector.csv @@ -0,0 +1,25 @@ +Pin; Signal; Direction; Description +1; |VBAT-|; Input; Battery module negative terminal +2; |CELL_0+|; Input; Cell 0 positive terminal +3; |CELL_2+|; Input; Cell 2 positive terminal +4; |CELL_4+|; Input; Cell 4 positive terminal +5; |CELL_6+|; Input; Cell 6 positive terminal +6; |CELL_8+|; Input; Cell 8 positive terminal +7; |CELL_10+|; Input; Cell 10 positive terminal +8; |CELL_12+|; Input; Cell 12 positive terminal +9; |CELL_14+|; Input; Cell 14 positive terminal +10; |VBAT+|; Input; Battery module positive terminal +11; |NC|; \-; \- +12; |NC|; \-; \- +13; |CELL_0-|; Input; Cell 0 negative terminal +14; |CELL_1+|; Input; Cell 1 positive terminal +15; |CELL_3+|; Input; Cell 3 positive terminal +16; |CELL_5+|; Input; Cell 5 positive terminal +17; |CELL_7+|; Input; Cell 7 positive terminal +18; |CELL_9+|; Input; Cell 9 positive terminal +19; |CELL_11+|; Input; Cell 11 positive terminal +20; |CELL_13+|; Input; Cell 13 positive terminal +21; |CELL_15+|; Input; Cell 15 positive terminal +22; |NC|; \-; \- +23; |NC|; \-; \- +24; |NC|; \-; \- diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_daisy-input-connectors.csv b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_daisy-input-connectors.csv new file mode 100644 index 00000000..df9921ba --- /dev/null +++ b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_daisy-input-connectors.csv @@ -0,0 +1,3 @@ +Pin; Daisy Chain +1; |IN+| |adi-ades1830| +2; |IN-| |adi-ades1830| diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_daisy-output-connectors.csv b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_daisy-output-connectors.csv new file mode 100644 index 00000000..ad344680 --- /dev/null +++ b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_daisy-output-connectors.csv @@ -0,0 +1,3 @@ +Pin; Daisy Chain +1; |OUT+| |adi-ades1830| +2; |OUT-| |adi-ades1830| diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_electrical-ratings.csv b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_electrical-ratings.csv new file mode 100644 index 00000000..43ae738c --- /dev/null +++ b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_electrical-ratings.csv @@ -0,0 +1,5 @@ +Description; Minimum; Typical; Maximum; Unit +Battery Module Voltage;11; --;80; |V| +Single Battery Cell Voltage;0; --;5; |V| +Temperature Sensor Inputs; --; 10k; --; |Ohm| +Current consumption: AFE active; --; TBD; --; |mA| diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_mechanical-dimensions.csv b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_mechanical-dimensions.csv new file mode 100644 index 00000000..c8d0b6aa --- /dev/null +++ b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_mechanical-dimensions.csv @@ -0,0 +1,5 @@ +Description; Value; Unit +Width;100; |mm| +Length;160; |mm| +Height;15; |mm| +Weight;(TBC) 88; |g| diff --git a/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_temperature-sensor-connector.csv b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_temperature-sensor-connector.csv new file mode 100644 index 00000000..4edd64a7 --- /dev/null +++ b/docs/hardware/slaves/16-adi-ades1830-vx.x.x/16-adi-ades1830-v0.9.0/16-adi-ades1830-v0.9.0_temperature-sensor-connector.csv @@ -0,0 +1,21 @@ +Pin; Signal; Direction; Description +1; T-SENSOR_0; Input; NTC Sensor 0 terminal 1 +2; T-SENSOR_1; Input; NTC Sensor 1 terminal 1 +3; T-SENSOR_2; Input; NTC Sensor 2 terminal 1 +4; T-SENSOR_3; Input; NTC Sensor 3 terminal 1 +5; T-SENSOR_4; Input; NTC Sensor 4 terminal 1 +6; T-SENSOR_5; Input; NTC Sensor 5 terminal 1 +7; T-SENSOR_6; Input; NTC Sensor 6 terminal 1 +8; T-SENSOR_7; Input; NTC Sensor 7 terminal 1 +9; T-SENSOR_8; Input; NTC Sensor 8 terminal 1 +10; T-SENSOR_9; Input; NTC Sensor 9 terminal 1 +11; |VBAT-|; Input; NTC Sensor 0 terminal 2 +12; |VBAT-|; Input; NTC Sensor 1 terminal 2 +13; |VBAT-|; Input; NTC Sensor 2 terminal 2 +14; |VBAT-|; Input; NTC Sensor 3 terminal 2 +15; |VBAT-|; Input; NTC Sensor 4 terminal 2 +16; |VBAT-|; Input; NTC Sensor 5 terminal 2 +17; |VBAT-|; Input; NTC Sensor 6 terminal 2 +18; |VBAT-|; Input; NTC Sensor 7 terminal 2 +19; |VBAT-|; Input; NTC Sensor 8 terminal 2 +20; |VBAT-|; Input; NTC Sensor 9 terminal 2 diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-changelog.rst b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-changelog.rst index 1b16fe87..bdb09ab3 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-changelog.rst +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-changelog.rst @@ -1,12 +1,12 @@ .. include:: ./../../../macros.txt .. include:: ./../../../units.txt -.. _CHANGELOG_FOR_SLAVE_LTC6813_1: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6813_1: -Changelog for Slave LTC6813-1 -============================= +Changelog for Slave LTC LTC6813-1 +================================= -.. _CHANGELOG_FOR_SLAVE_LTC6813_1_V1_1_5: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_1_5: v1.1.5 ------ @@ -14,7 +14,7 @@ v1.1.5 - EMI layout improvements - adapted component variants to other changes -.. _CHANGELOG_FOR_SLAVE_LTC6813_1_V1_1_4: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_1_4: v1.1.4 ------ @@ -23,14 +23,14 @@ v1.1.4 - added circuit for switching off DC/DC converters in LTC sleep mode - added pull-ups on all GPIOs of the LTCs -.. _CHANGELOG_FOR_SLAVE_LTC6813_1_V1_1_3: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_1_3: v1.1.3 ------ - schematic cleanup, improved fonts and sizes on PCB -.. _CHANGELOG_FOR_SLAVE_LTC6813_1_V1_1_2: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_1_2: v1.1.2 ------ @@ -38,7 +38,7 @@ v1.1.2 - replaced ACPL-247 with ACPL-217 optocoupler in order to be able to use automotive components -.. _CHANGELOG_FOR_SLAVE_LTC6813_1_V1_1_1: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_1_1: v1.1.1 ------ @@ -47,7 +47,7 @@ v1.1.1 - replaced analog buffer opamp with AD8628ARTZ-R2 (automotive) - replaced DC/DC buck controller with LM5161QPWPRQ1 (automotive) -.. _CHANGELOG_FOR_SLAVE_LTC6813_1_V1_1_0: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_1_0: v1.1.0 ------ @@ -67,14 +67,14 @@ v1.1.0 - added layermarker on PCB - Primary discharge timer is now switched on by default -.. _CHANGELOG_FOR_SLAVE_LTC6813_1_V1_0_1: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_0_1: v1.0.1 ------ -- replaced all LTC1380 MUXs with ADG728 MUXs +- replaced all LTC1380 multiplexer with ADG728 multiplexer -.. _CHANGELOG_FOR_SLAVE_LTC6813_1_V1_0_0: +.. _CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_0_0: v1.0.0 ------ diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3.rst b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3.rst index 97459fdd..fc6340e2 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3.rst +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3.rst @@ -1,15 +1,15 @@ .. include:: ./../../../macros.txt .. include:: ./../../../units.txt -.. _LTC6813_1_BASED_18_CELL_SLAVE___V1_1_3__: +.. _LTC_LTC6813_1_BASED_18_CELL_SLAVE___V1_1_3__: -LTC6813-1-based 18-Cell Slave ``v1.1.3`` -======================================== +LTC LTC6813-1-based 18-Cell Slave ``v1.1.3`` +============================================ .. note:: The changelog for this release is found at - :ref:`CHANGELOG_FOR_SLAVE_LTC6813_1_V1_1_3`. + :ref:`CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_1_3`. .. |local_slave_version| replace:: ``1.1.3`` @@ -19,8 +19,8 @@ Overview .. important:: - The following description only applies for the |ltc6813-1|\ -based 18 cell - |BMS-Slave| hardware version |local_slave_version|. + The following description only applies for the |ltc-ltc6813-1|\ -based 18 + cell |BMS-Slave| hardware version |local_slave_version|. .. hint:: @@ -79,8 +79,6 @@ Schematic and Board Layout More information about the board schematic and layout files can be found in section :ref:`DESIGN_RESOURCES`. - - --------- Functions --------- @@ -139,8 +137,8 @@ The passive balancing circuit is realized by a parallel connection of two 130 |Ohm| discharge-resistors that can be connected to each single cell in parallel. The MOSFET switches (T1500 - T1517) that control the connection to the cells -are controlled by the primary |ltc6813-1| monitoring IC. -The |ltc6813-1| on the secondary unit does not support balancing. +are controlled by the primary |ltc-ltc6813-1| monitoring IC. +The |ltc-ltc6813-1| on the secondary unit does not support balancing. The resistor value of 2x 130 |_| |Ohm| results in a balancing current of about 55 |_| mA at a cell voltage of 3.6 |_| V. This current results in a power dissipation of about 0.2W per balancing @@ -152,10 +150,10 @@ Global Cell Balancing Feedback In order to check the proper function of the balancing process or to detect a malfunction in the balancing control circuit, a global balancing feedback -signal is connected to the |ltc6813-1|. +signal is connected to the |ltc-ltc6813-1|. This allows the system to check whether any balancing action is currently taking place at any time. -The feedback signal is connected to the GPIO3 of the |ltc6813-1|. +The feedback signal is connected to the GPIO3 of the |ltc-ltc6813-1|. The signal remains in a logic zero state until any balancing action on any cell starts. @@ -187,12 +185,12 @@ series resistors results in a current of 1.2mA (at 20 |_| °C) which is drawn from VREF2. Each 8 temperature sensors are connected to an analog multiplexer. -The analog multiplexer can be controlled via |I2C| by the |ltc6813-1| +The analog multiplexer can be controlled via |I2C| by the |ltc-ltc6813-1| (7-bit address: 0x4C). In order to ensure fast settling times after switching the multiplexer input, the output signal of the multiplexer is buffered by an operational amplifier. Finally the analog voltage of the selected sensor is measured on the GPIO1 pin -of the |ltc6813-1|. +of the |ltc-ltc6813-1|. ^^^^^^^^^^^^^^^ On-board EEPROM @@ -202,7 +200,7 @@ The primary unit as well as the secondary unit of the foxBMS BMS-Slave board is equipped with an EEPROM IC (IC801). The EEPROM for example can be used for storing data such as calibration values. Similar to the analog multiplexers, the EEPROM device is connected to the -|I2C| bus of the |ltc6813-1| (7-bit address: 0x50). +|I2C| bus of the |ltc-ltc6813-1| (7-bit address: 0x50). ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ On-board Ambient Temperature Sensor @@ -210,7 +208,7 @@ On-board Ambient Temperature Sensor For an additional monitoring of the ambient temperature an on-board temperature sensor is used. -This temperature sensor can be read by the |ltc6813-1| via the |I2C| bus +This temperature sensor can be read by the |ltc-ltc6813-1| via the |I2C| bus (7-bit address: 0x48). It is possible to program an alert temperature. Once the measured temperature reaches this alert temperature the alert pin of @@ -237,12 +235,12 @@ and is described in :file: ./18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_analog-inputs-connector.csv Each 8 analog inputs are connected to an analog multiplexer. -The analog multiplexers can be controlled via |I2C| by the |ltc6813-1| +The analog multiplexers can be controlled via |I2C| by the |ltc-ltc6813-1| (7-bit addresses: 0x4D and 0x4E). In order to ensure fast settling times after switching the multiplexer input, the output signals of the multiplexers are buffered by operational amplifiers. Finally the analog voltage of the selected sensor can be measured on the GPIO2 -pin of the |ltc6813-1|. +pin of the |ltc-ltc6813-1|. Each 8 digital inputs/outputs are provided on the connectors X402 (primary) and X403 (secondary). @@ -276,7 +274,7 @@ reverse direction. The isoSPI connections are isolated galvanically using pulse transformers (TR1400). The voltage amplitude of the differential signal can be adjusted by setting -resistors (see paragraph :ref:`hw_slave_daisy_current_18cell`). +resistors (see paragraph :ref:`hardware_slave_daisy_current_18cell`). The pinout of the isoSPI connectors is described in :numref:`Table %s <6813-1_slave_18cell_v1.1.3_daisy_input_connectors>` and @@ -304,8 +302,8 @@ Hardware Settings / Options Software Timer """""""""""""" -The internal software timer of the |ltc6813-1| can be enabled/disabled by a -dedicated external pin (SWTEN, pin 36 of the |ltc6813-1|). +The internal software timer of the |ltc-ltc6813-1| can be enabled/disabled by a +dedicated external pin (SWTEN, pin 36 of the |ltc-ltc6813-1|). In order to support all features, the foxBMS BMS-Slave board offers a possibility to switch the software timer. The software timer is enabled in the standard configuration, which means pin @@ -313,7 +311,7 @@ The software timer is enabled in the standard configuration, which means pin The timer can be disabled by removing the resistor R1407 and placing a zero-ohm resistor to R1406. -.. _hw_slave_daisy_current_18cell: +.. _hardware_slave_daisy_current_18cell: Daisy Chain Communication Current """"""""""""""""""""""""""""""""" @@ -325,13 +323,13 @@ This values result in a bias current of approximately 1mA and a differential signal amplitude of 1.18 |_| V. Theses values are suitable for high noise environments with cable lengths of over 50m. -More information can be found in the |ltc6813-1| data sheet. +More information can be found in the |ltc-ltc6813-1| data sheet. Status LED """""""""" The status LEDs LD1400 show the current mode of each, the primary and -secondary |ltc6813-1|. +secondary |ltc-ltc6813-1|. The LED is on in STANDBY, REFUP or MEASURE mode, whereas the LED is off in SLEEP mode. The LED can be disabled by removing the resistor R1403 next to the LED. @@ -339,7 +337,7 @@ The LED can be disabled by removing the resistor R1403 next to the LED. GPIO Extension Connector """""""""""""""""""""""" -The internal GPIO lines 1 to 5 of the primary or secondary |ltc6813-1| can be +The internal GPIO lines 1 to 5 of the primary or secondary |ltc-ltc6813-1| can be connected to the GPIO extension pin header X404 via optional zero-ohm resistors. In the standard configuration these resistors are not placed. diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_analog-inputs-connector.csv b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_analog-inputs-connector.csv index d50ec98a..ab2e6b3b 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_analog-inputs-connector.csv +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_analog-inputs-connector.csv @@ -15,5 +15,5 @@ Pin; Signal; Direction; Description 14; ANALOG-IN_13; Input; Analog input 13 15; ANALOG-IN_14; Input; Analog input 14 16; ANALOG-IN_15; Input; Analog input 15 -17; +3.0V_VREF2; Output; |ltc6813-1| 3.0V voltage reference +17; +3.0V_VREF2; Output; |ltc-ltc6813-1| 3.0V voltage reference 18; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_daisy-input-connectors.csv b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_daisy-input-connectors.csv index 04b147a0..e2ec6e88 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_daisy-input-connectors.csv +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_daisy-input-connectors.csv @@ -1,3 +1,3 @@ Pin; Daisy Chain -1; |IN+| (Primary/Secondary |ltc6813-1|) -2; |IN-| (Primary/Secondary |ltc6813-1|) +1; |IN+| (Primary/Secondary |ltc-ltc6813-1|) +2; |IN-| (Primary/Secondary |ltc-ltc6813-1|) diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_daisy-output-connectors.csv b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_daisy-output-connectors.csv index 11abfeea..de3af195 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_daisy-output-connectors.csv +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_daisy-output-connectors.csv @@ -1,3 +1,3 @@ Pin; Daisy Chain -1; |OUT+| (Primary/Secondary |ltc6813-1|) -2; |OUT-| (Primary/Secondary |ltc6813-1|) +1; |OUT+| (Primary/Secondary |ltc-ltc6813-1|) +2; |OUT-| (Primary/Secondary |ltc-ltc6813-1|) diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_digital-io-connector.csv b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_digital-io-connector.csv index c4371858..3b871a0d 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_digital-io-connector.csv +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_digital-io-connector.csv @@ -6,5 +6,5 @@ Pin; Signal; Direction; Description 5; DIGITAL-IO_4; Input/Output; Digital input/output 4 6; DIGITAL-IO_5; Input/Output; Digital input/output 5 7; DIGITAL-IO_6; Input/Output; Digital input/output 6 -8; +5.0V_VREG; Output; |ltc6813-1| 5.0V regulated voltage +8; +5.0V_VREG; Output; |ltc-ltc6813-1| 5.0V regulated voltage 9; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_extension-connector.csv b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_extension-connector.csv index f69357b3..86231390 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_extension-connector.csv +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_extension-connector.csv @@ -1,20 +1,20 @@ Pin; Signal; Direction; Description -1; +3.0V_VREF2_0; Output; Primary |ltc6813-1| 3.0V reference voltage 2 -2; +3.0V_VREF2_1; Output; Secondary |ltc6813-1| 3.0V reference voltage 2 -3; +5.0V_VREG_0; Output; Primary |ltc6813-1| 5.0V regulated voltage -4; +5.0V_VREG_1; Output; Secondary |ltc6813-1| 5.0V regulated voltage -5; PRIMARY-GPIO1-OPT; Input/Output; Primary |ltc6813-1| GPIO1 -6; SECONDARY-GPIO1-OPT; Input/Output; Secondary |ltc6813-1| GPIO1 -7; PRIMARY-GPIO2-OPT; Input/Output; Primary |ltc6813-1| GPIO2 -8; SECONDARY-GPIO2-OPT; Input/Output; Secondary |ltc6813-1| GPIO2 -9; PRIMARY-GPIO3-OPT; Input/Output; Primary |ltc6813-1| GPIO3 -10; SECONDARY-GPIO3-OPT; Input/Output; Secondary |ltc6813-1| GPIO3 -11; PRIMARY-GPIO4-OPT; Input/Output; Primary |ltc6813-1| GPIO4 -12; SECONDARY-GPIO4-OPT; Input/Output; Secondary |ltc6813-1| GPIO4 -13; PRIMARY-GPIO5-OPT; Input/Output; Primary |ltc6813-1| GPIO5 -14; SECONDARY-GPIO5-OPT; Input/Output; Secondary |ltc6813-1| GPIO5 -15; PRIMARY-WDT; Output; Primary |ltc6813-1| watchdog output -16; SECONDARY-WDT; Output; Secondary |ltc6813-1| watchdog output +1; +3.0V_VREF2_0; Output; Primary |ltc-ltc6813-1| 3.0V reference voltage 2 +2; +3.0V_VREF2_1; Output; Secondary |ltc-ltc6813-1| 3.0V reference voltage 2 +3; +5.0V_VREG_0; Output; Primary |ltc-ltc6813-1| 5.0V regulated voltage +4; +5.0V_VREG_1; Output; Secondary |ltc-ltc6813-1| 5.0V regulated voltage +5; PRIMARY-GPIO1-OPT; Input/Output; Primary |ltc-ltc6813-1| GPIO1 +6; SECONDARY-GPIO1-OPT; Input/Output; Secondary |ltc-ltc6813-1| GPIO1 +7; PRIMARY-GPIO2-OPT; Input/Output; Primary |ltc-ltc6813-1| GPIO2 +8; SECONDARY-GPIO2-OPT; Input/Output; Secondary |ltc-ltc6813-1| GPIO2 +9; PRIMARY-GPIO3-OPT; Input/Output; Primary |ltc-ltc6813-1| GPIO3 +10; SECONDARY-GPIO3-OPT; Input/Output; Secondary |ltc-ltc6813-1| GPIO3 +11; PRIMARY-GPIO4-OPT; Input/Output; Primary |ltc-ltc6813-1| GPIO4 +12; SECONDARY-GPIO4-OPT; Input/Output; Secondary |ltc-ltc6813-1| GPIO4 +13; PRIMARY-GPIO5-OPT; Input/Output; Primary |ltc-ltc6813-1| GPIO5 +14; SECONDARY-GPIO5-OPT; Input/Output; Secondary |ltc-ltc6813-1| GPIO5 +15; PRIMARY-WDT; Output; Primary |ltc-ltc6813-1| watchdog output +16; SECONDARY-WDT; Output; Secondary |ltc-ltc6813-1| watchdog output 17; PRIMARY-TEMP-ALERT; Output; Primary board temp. sensor alarm output 18; SECONDARY-TEMP-ALERT; Output; Secondary board temp. sensor alarm output 19; |FUSED_VBAT-|; Output; GND diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_extension-connector_2.csv b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_extension-connector_2.csv index 74d1a827..30a9b1f4 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_extension-connector_2.csv +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.3/18-ltc-ltc6813-1-v1.1.3_extension-connector_2.csv @@ -1,9 +1,9 @@ Pin; Signal; Direction; Description -1; PRIMARY-GPIO6; Input/Output; Primary |ltc6813-1| GPIO6 -2; SECONDARY-GPIO6; Input/Output; Secondary |ltc6813-1| GPIO6 -3; PRIMARY-GPIO7; Input/Output; Primary |ltc6813-1| GPIO7 -4; SECONDARY-GPIO7; Input/Output; Secondary |ltc6813-1| GPIO7 -5; PRIMARY-GPIO8; Input/Output; Primary |ltc6813-1| GPIO8 -6; SECONDARY-GPIO8; Input/Output; Secondary |ltc6813-1| GPIO8 -7; PRIMARY-GPIO9; Input/Output; Primary |ltc6813-1| GPIO9 -8; SECONDARY-GPIO9; Input/Output; Secondary |ltc6813-1| GPIO9 +1; PRIMARY-GPIO6; Input/Output; Primary |ltc-ltc6813-1| GPIO6 +2; SECONDARY-GPIO6; Input/Output; Secondary |ltc-ltc6813-1| GPIO6 +3; PRIMARY-GPIO7; Input/Output; Primary |ltc-ltc6813-1| GPIO7 +4; SECONDARY-GPIO7; Input/Output; Secondary |ltc-ltc6813-1| GPIO7 +5; PRIMARY-GPIO8; Input/Output; Primary |ltc-ltc6813-1| GPIO8 +6; SECONDARY-GPIO8; Input/Output; Secondary |ltc-ltc6813-1| GPIO8 +7; PRIMARY-GPIO9; Input/Output; Primary |ltc-ltc6813-1| GPIO9 +8; SECONDARY-GPIO9; Input/Output; Secondary |ltc-ltc6813-1| GPIO9 diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.4.rst b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.4.rst index 303a7edd..1ff4a5b0 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.4.rst +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.4.rst @@ -1,17 +1,17 @@ .. include:: ./../../../macros.txt .. include:: ./../../../units.txt -.. _LTC6813_1_BASED_18_CELL_SLAVE___V1_1_4__: +.. _LTC_LTC6813_1_BASED_18_CELL_SLAVE___V1_1_4__: -LTC6813-1-based 18-Cell Slave ``v1.1.4`` -======================================== +LTC_LTC6813-1-based 18-Cell Slave ``v1.1.4`` +============================================ .. note:: The changelog for this release is found at - :ref:`CHANGELOG_FOR_SLAVE_LTC6813_1_V1_1_4`. + :ref:`CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_1_4`. .. |local_slave_version| replace:: ``1.1.4`` There are no changes that need a new documentation compared to v1.1.3, -therefore see :ref:`LTC6813_1_BASED_18_CELL_SLAVE___V1_1_3__`. +therefore see :ref:`LTC_LTC6813_1_BASED_18_CELL_SLAVE___V1_1_3__`. diff --git a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.5.rst b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.5.rst index 50b49336..61be4789 100644 --- a/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.5.rst +++ b/docs/hardware/slaves/18-ltc-ltc6813-1-vx.x.x/18-ltc-ltc6813-1-v1.1.5.rst @@ -1,17 +1,17 @@ .. include:: ./../../../macros.txt .. include:: ./../../../units.txt -.. _LTC6813_1_BASED_18_CELL_SLAVE___V1_1_5__: +.. _LTC_LTC6813_1_BASED_18_CELL_SLAVE___V1_1_5__: -LTC6813-1-based 18-Cell Slave ``v1.1.5`` -======================================== +LTC LTC6813-1-based 18-Cell Slave ``v1.1.5`` +============================================ .. note:: The changelog for this release is found at - :ref:`CHANGELOG_FOR_SLAVE_LTC6813_1_V1_1_5`. + :ref:`CHANGELOG_FOR_SLAVE_LTC_LTC6813_1_V1_1_5`. .. |local_slave_version| replace:: ``1.1.5`` There are no changes that need a new documentation compared to v1.1.3, -therefore see :ref:`LTC6813_1_BASED_18_CELL_SLAVE___V1_1_3__`. +therefore see :ref:`LTC_LTC6813_1_BASED_18_CELL_SLAVE___V1_1_3__`. diff --git a/docs/index.rst b/docs/index.rst index f0b06680..f1a67847 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -170,6 +170,7 @@ All sections are listed here: ./system/system-introduction.rst ./system/system-voltage-and-current-monitoring.rst + ./system/precharging.rst .. _TOOLS_DOCUMENTATION_OVERVIEW: diff --git a/docs/introduction/use-case.rst b/docs/introduction/use-case.rst index e0897a8b..8c1095aa 100644 --- a/docs/introduction/use-case.rst +++ b/docs/introduction/use-case.rst @@ -32,9 +32,9 @@ will open and disconnect the battery. Three power contactors are used to connect and disconnect the battery modules from the load: - - Main Contactor Plus - - Main Contactor Minus - - Pre-charge contactor +- Main Contactor Plus +- Main Contactor Minus +- Pre-charge contactor There is no separate charge path, discharging and charging are made through the main contactors. diff --git a/docs/macros.txt b/docs/macros.txt index cc9536da..29b7120e 100644 --- a/docs/macros.txt +++ b/docs/macros.txt @@ -3,7 +3,7 @@ .. |timestamp| date:: %Y-%m-%d %H:%M:%S .. |foxbms| replace:: foxBMS 2 -.. |version_foxbms| replace:: ``1.5.1`` +.. |version_foxbms| replace:: ``1.6.0`` .. |foxbms.org| replace:: https://foxbms.org .. |docs.foxbms.org| replace:: https://docs.foxbms.org .. |github_foxbms| replace:: https://github.com/foxBMS/ @@ -44,7 +44,7 @@ .. |version_llvm| replace:: ``13.0.0`` .. |path_llvm| replace:: ``C:\Program Files\LLVM\13.0.0`` -.. |version_pcan_se| replace:: ``Version 6.5.2`` +.. |version_pcan_symbol_editor| replace:: ``Version 6.5.2`` .. |version_sym_file| replace:: ``Version 6.0`` .. _Ruby: https://www.ruby-lang.org/ @@ -96,10 +96,6 @@ .. _MISRA C: https://www.misra.org.uk/ -.. |nxp775| replace:: MC33775A - -.. |nxp664| replace:: MC33664 - .. |soa| replace:: *SOA* .. |soc| replace:: *SOC* .. |soe| replace:: *SOE* @@ -113,17 +109,19 @@ .. |adi| replace:: Analog Devices .. |mxm| replace:: Maxim Integrated -.. |tms570lc4357| replace:: TMS570LC4357 +.. |ti-tms570| replace:: TI TMS570 +.. |ti-tms570lc4357| replace:: TI TMS570LC4357 -.. |ltc6820| replace:: LTC6820 -.. |max17852| replace:: MAX17852 -.. |mc33664| replace:: MC33664 +.. |ltc-ltc6820| replace:: LTC LTC6820 +.. |max-max17852| replace:: Maxim MAX17852 +.. |nxp-mc33664| replace:: NXP MC33664 -.. |ltc6804-1| replace:: LTC6804-1 -.. |ltc6811-1| replace:: LTC6811-1 -.. |ltc6813-1| replace:: LTC6813-1 -.. |max17841b| replace:: MAX17841B -.. |mc33775a| replace:: MC33775A +.. |ltc-ltc6804-1| replace:: LTC LTC6804-1 +.. |ltc-ltc6811-1| replace:: LTC LTC6811-1 +.. |ltc-ltc6813-1| replace:: LTC LTC6813-1 +.. |max-max17841b| replace:: Maxim MAX17841B +.. |nxp-mc33775a| replace:: NXP MC33775A +.. |adi-ades1830| replace:: ADI ADES1830 .. |master| replace:: foxBMS Master Unit .. |masters| replace:: foxBMS Master Units diff --git a/docs/references.bib b/docs/references.bib index f6107675..e7042f7b 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -59,4 +59,13 @@ @book{MISRA-C:2012 isbn = {9781906400118} } +@book{Andrea2014, + title = "Battery management systems for large lithium-ion battery packs", + author = "Andrea, Davide", + publisher = "Artech House", + month = may, + year = 2014, + address = "Norwood, MA" +} + @Comment{jabref-meta: databaseType:bibtex;} diff --git a/docs/software/architecture/architecture.rst b/docs/software/architecture/architecture.rst index d2f86621..83221631 100644 --- a/docs/software/architecture/architecture.rst +++ b/docs/software/architecture/architecture.rst @@ -27,7 +27,6 @@ access the hardware and its peripherals. This enables encapsulation of the actual BMS software implementation from the hardware and eases porting the |foxbms| software to different microcontrollers. - The open-source real-time operating system |freertos| is the centerpiece of the software architecture. Its reliable kernel is ideally suited to ensure the compliance of all soft and @@ -65,7 +64,6 @@ The foxBMS software itself is grouped into three different layers: health, state-of-energy) and the vehicle specific BMS application is done within the **application layer**. - .. figure:: img/axivion_architecture.svg :alt: Detailed software architecture :name: axivion_architecture diff --git a/docs/software/build-environment/build-environment_how-to.rst b/docs/software/build-environment/build-environment_how-to.rst index 14f0f00e..64088e1a 100644 --- a/docs/software/build-environment/build-environment_how-to.rst +++ b/docs/software/build-environment/build-environment_how-to.rst @@ -66,7 +66,7 @@ Existing Environments +---------------------+-------+-------+ Further Reading -=============== +--------------- An explanation why build environments are used is found in :ref:`BUILD_ENVIRONMENT`. diff --git a/docs/software/build-process/build-process.rst b/docs/software/build-process/build-process.rst index 4c7e446f..4d514ad0 100644 --- a/docs/software/build-process/build-process.rst +++ b/docs/software/build-process/build-process.rst @@ -56,7 +56,6 @@ This failure is reported by the build system. did not match on static DATA_BLOCK_CELL_VOLTAGE_s mrc_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; - .. _afe_library_build: Building the Analog Front-End Library diff --git a/docs/software/build-process/misc/libproject-example.c b/docs/software/build-process/misc/libproject-example.c index 1b222c77..744ece08 100644 --- a/docs/software/build-process/misc/libproject-example.c +++ b/docs/software/build-process/misc/libproject-example.c @@ -43,8 +43,8 @@ * @file libproject-example.c * @author foxBMS Team * @date 2020-10-06 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup USER_LIB * @prefix SUPER * diff --git a/docs/software/build-process/misc/libproject-example.h b/docs/software/build-process/misc/libproject-example.h index ed525803..8054b544 100644 --- a/docs/software/build-process/misc/libproject-example.h +++ b/docs/software/build-process/misc/libproject-example.h @@ -43,8 +43,8 @@ * @file libproject-example.h * @author foxBMS Team * @date 2020-10-06 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup USER_LIB * @prefix SUPER * diff --git a/docs/software/configuration/battery-system-configuration.csv b/docs/software/configuration/battery-system-configuration.csv index 752481b0..d33cbbb9 100644 --- a/docs/software/configuration/battery-system-configuration.csv +++ b/docs/software/configuration/battery-system-configuration.csv @@ -3,7 +3,7 @@ Defines whether discharge current is seen as positive or negative; ``BS Number of parallel strings in the battery pack; ``BS_NR_OF_STRINGS`` Number of modules in a string; ``BS_NR_OF_MODULES_PER_STRING`` Number of cells per module; ``BS_NR_OF_CELL_BLOCKS_PER_MODULE`` -Number of battery cells in a parallel cell connection per battery module; ``BS_NR_OF_PARALLEL_CELLS_PER_MODULE`` +Number of battery cells in a parallel cell connection per battery module; ``BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK`` Value of the balancing resistors on the slave-board; ``BS_BALANCING_RESISTANCE_ohm`` Number of used GPIOs on the slave-board; ``BS_NR_OF_GPIOS_PER_MODULE`` Number of temperature sensors per battery module; ``BS_NR_OF_TEMP_SENSORS_PER_MODULE`` diff --git a/docs/software/configuration/compiler/compiler-configuration.rst b/docs/software/configuration/compiler/compiler-configuration.rst index 3a2896b0..0ffc5096 100644 --- a/docs/software/configuration/compiler/compiler-configuration.rst +++ b/docs/software/configuration/compiler/compiler-configuration.rst @@ -51,7 +51,6 @@ System and the Hardware Abstraction Layer. - ``operating_system``: ``CFLAGS`` that should only be applied to the operating system sources (``src/os/*``). - ``LINKFLAGS`` """"""""""""" @@ -114,7 +113,6 @@ Remarks can be added to a single build step as shown in The default remark settings are relatively strict to avoid common mistakes. **Changing them is generally not recommended**. - .. note:: It is possible to add all kinds of compiler flags in command files, this is @@ -154,14 +152,12 @@ symbol should be pulled from where needs to be defined (see In this file use Unix-separator and specify the linked source as seen from the build directory. - .. literalinclude:: linker_pulls/example_linker_pulls.json :language: json :caption: Linker pulls file ``linker_pulls.json`` :name: pulls-config-file :linenos: - This file needs to be specified when a program is built (see :ref:`linker-pulls-build-example`). If the symbol ``_c_int00`` would not be pulled from diff --git a/docs/software/configuration/configuration.rst b/docs/software/configuration/configuration.rst index d0196da3..fb37b56b 100644 --- a/docs/software/configuration/configuration.rst +++ b/docs/software/configuration/configuration.rst @@ -31,7 +31,7 @@ This is explained in :ref:`BMS_APPLICATION`. It generates sources in form of ``.h`` and ``.c`` and ``.asm`` files. These HAL sources are generated based on the |halcogen| configuration files (``*.hcg`` and ``*.dil``). -|foxbms| uses the waf tool :ref:`WAF_TOOL_HALCOGEN` to automatically run +|foxbms| uses the Waf tool :ref:`WAF_TOOL_HALCOGEN` to automatically run |halcogen| and create the required sources. Additional information on the tool can be found in :ref:`HALCOGEN_TOOL_DOCUMENTATION`. @@ -95,11 +95,10 @@ The process is illustrated in :numref:`halcogen-configuration`. HALCoGen configuration change detection process - Enabling Cache ^^^^^^^^^^^^^^ -The |tms570lc4357| can use cache to improve performance. +The |ti-tms570lc4357| can use cache to improve performance. - Since |foxbms| v1.3.0, cache is enabled by setting the define ``OS_ENABLE_CACHE`` in ``src/app/task/os/os.h`` to ``true``. @@ -261,7 +260,6 @@ The basic, top level view on the battery system configuration is defined at: :delim: ; :file: ./battery-system-configuration.csv - The symbolic names of the individual strings needs to be adapted in ``BS_STRING_ID_e`` to the actual number of strings in the battery system. diff --git a/docs/software/configuration/without-halcogen/without-halcogen_diff-includes.diff b/docs/software/configuration/without-halcogen/without-halcogen_diff-includes.diff index 57a25f57..5f57a060 100644 --- a/docs/software/configuration/without-halcogen/without-halcogen_diff-includes.diff +++ b/docs/software/configuration/without-halcogen/without-halcogen_diff-includes.diff @@ -63,7 +63,7 @@ index 1945b079..a47c3e20 100644 --- a/src/app/main/wscript +++ b/src/app/main/wscript @@ -69,6 +69,7 @@ def build(bld): - os.path.join("..", "engine", "hwinfo"), + os.path.join("..", "engine", "hw_info"), os.path.join("..", "task", "os"), os.path.join("..", "task", "config"), + os.path.join("..", "..", "hal", "include"), diff --git a/docs/software/configuration/without-halcogen_how-to.rst b/docs/software/configuration/without-halcogen_how-to.rst index 831a9c05..8d82aca1 100644 --- a/docs/software/configuration/without-halcogen_how-to.rst +++ b/docs/software/configuration/without-halcogen_how-to.rst @@ -8,7 +8,7 @@ How to Use Generated Sources from HALCoGen .. note:: A documentation of the tool |halcogen| can be found in - :ref:`HALCOGEN_TOOL_DOCUMENTATION`, the waf-tool wrapper for this project in + :ref:`HALCOGEN_TOOL_DOCUMENTATION`, the Waf tool wrapper for this project in :ref:`WAF_TOOL_HALCOGEN` and information on configuring |halcogen| in the context of the toolchain of this project in :ref:`HAL_CONFIGURATION`. diff --git a/docs/software/how-to/how-to.rst b/docs/software/how-to/how-to.rst index 3e0b4ed6..9f484111 100644 --- a/docs/software/how-to/how-to.rst +++ b/docs/software/how-to/how-to.rst @@ -19,6 +19,9 @@ BMS Software Modules ./../modules/engine/database/database_how-to.rst ./../modules/task/ftask/ftask_how-to.rst ./../modules/main/fassert_how-to.rst + ./../modules/driver/afe/adding-a-new-ic_how-to + ./../modules/driver/ts/adding-a-new-ts_how-to + ./../modules/application/bms/bms_how-to Other ----- @@ -26,8 +29,6 @@ Other .. toctree:: :maxdepth: 1 - ./../modules/driver/afe/adding-a-new-ic_how-to - ./../modules/driver/ts/adding-a-new-ts_how-to ./../../developer-manual/style-guide/state-machines_how-to ./../configuration/without-halcogen_how-to ./../unit-tests/unit-tests_how-to diff --git a/docs/software/modules/application/algorithm/state-estimation/soc/soc_counting.rst b/docs/software/modules/application/algorithm/state-estimation/soc/soc_counting.rst index fed7fc1f..b1b86727 100644 --- a/docs/software/modules/application/algorithm/state-estimation/soc/soc_counting.rst +++ b/docs/software/modules/application/algorithm/state-estimation/soc/soc_counting.rst @@ -13,19 +13,16 @@ Driver ^^^^^^ - ``src/app/application/algorithm/state_estimation/soc/counting/soc_counting.c`` (`API <./../../../../../../_static/doxygen/src/html/soc__counting_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__counting_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soc/counting/soc_counting.h`` (`API <./../../../../../../_static/doxygen/src/html/soc__counting_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__counting_8h_source.html>`__) Configuration ^^^^^^^^^^^^^ -- ``src/app/application/algorithm/state_estimation/soc/counting/soc_counting_cfg.c`` (`API <./../../../../../../_static/doxygen/src/html/soc__counting__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__counting__cfg_8c_source.html>`__) - ``src/app/application/algorithm/state_estimation/soc/counting/soc_counting_cfg.h`` (`API <./../../../../../../_static/doxygen/src/html/soc__counting__cfg_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__counting__cfg_8h_source.html>`__) Unit Test ^^^^^^^^^ - ``tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soc__counting_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soc__counting_8c_source.html>`__) -- ``tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting_cfg.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soc__counting__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soc__counting__cfg_8c_source.html>`__) Detailed Description -------------------- @@ -37,7 +34,6 @@ directly in the |foxbms| software. The check of the presence of the integrator and the software integration are made in the :ref:`cc-function-name`. - .. literalinclude:: ./../../../../../../../src/app/application/algorithm/state_estimation/soc/counting/soc_counting.c :language: C :linenos: diff --git a/docs/software/modules/application/algorithm/state-estimation/soc/soc_debug.rst b/docs/software/modules/application/algorithm/state-estimation/soc/soc_debug.rst index 76bbaf9d..afbda8d4 100644 --- a/docs/software/modules/application/algorithm/state-estimation/soc/soc_debug.rst +++ b/docs/software/modules/application/algorithm/state-estimation/soc/soc_debug.rst @@ -13,19 +13,14 @@ Driver ^^^^^^ - ``src/app/application/algorithm/state_estimation/soc/debug/soc_debug.c`` (`API <./../../../../../../_static/doxygen/src/html/soc__debug_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__debug_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soc/debug/soc_debug.h`` (`API <./../../../../../../_static/doxygen/src/html/soc__debug_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__debug_8h_source.html>`__) Configuration ^^^^^^^^^^^^^ -- ``src/app/application/algorithm/state_estimation/soc/debug/soc_debug_cfg.c`` (`API <./../../../../../../_static/doxygen/src/html/soc__debug__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__debug__cfg_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soc/debug/soc_debug_cfg.h`` (`API <./../../../../../../_static/doxygen/src/html/soc__debug__cfg_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__debug__cfg_8h_source.html>`__) - Unit Test ^^^^^^^^^ - ``tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soc__debug_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soc__debug_8c_source.html>`__) -- ``tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug_cfg.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soc__debug__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soc__debug__cfg_8c_source.html>`__) Detailed Description -------------------- diff --git a/docs/software/modules/application/algorithm/state-estimation/soc/soc_none.rst b/docs/software/modules/application/algorithm/state-estimation/soc/soc_none.rst index 6a7f3954..218ed341 100644 --- a/docs/software/modules/application/algorithm/state-estimation/soc/soc_none.rst +++ b/docs/software/modules/application/algorithm/state-estimation/soc/soc_none.rst @@ -13,19 +13,14 @@ Driver ^^^^^^ - ``src/app/application/algorithm/state_estimation/soc/none/soc_none.c`` (`API <./../../../../../../_static/doxygen/src/html/soc__none_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__none_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soc/none/soc_none.h`` (`API <./../../../../../../_static/doxygen/src/html/soc__none_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__none_8h_source.html>`__) Configuration ^^^^^^^^^^^^^ -- ``src/app/application/algorithm/state_estimation/soc/none/soc_none_cfg.c`` (`API <./../../../../../../_static/doxygen/src/html/soc__none__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__none__cfg_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soc/none/soc_none_cfg.h`` (`API <./../../../../../../_static/doxygen/src/html/soc__none__cfg_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soc__none__cfg_8h_source.html>`__) - Unit Test ^^^^^^^^^ - ``tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soc__none_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soc__none_8c_source.html>`__) -- ``tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none_cfg.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soc__none__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soc__none__cfg_8c_source.html>`__) Detailed Description -------------------- diff --git a/docs/software/modules/application/algorithm/state-estimation/soe/soe_counting.rst b/docs/software/modules/application/algorithm/state-estimation/soe/soe_counting.rst index 3577589d..95bb90c5 100644 --- a/docs/software/modules/application/algorithm/state-estimation/soe/soe_counting.rst +++ b/docs/software/modules/application/algorithm/state-estimation/soe/soe_counting.rst @@ -13,19 +13,16 @@ Driver ^^^^^^ - ``src/app/application/algorithm/state_estimation/soe/counting/soe_counting.c`` (`API <./../../../../../../_static/doxygen/src/html/soe__counting_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__counting_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soe/counting/soe_counting.h`` (`API <./../../../../../../_static/doxygen/src/html/soe__counting_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__counting_8h_source.html>`__) Configuration ^^^^^^^^^^^^^ -- ``src/app/application/algorithm/state_estimation/soe/counting/soe_counting_cfg.c`` (`API <./../../../../../../_static/doxygen/src/html/soe__counting__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__counting__cfg_8c_source.html>`__) - ``src/app/application/algorithm/state_estimation/soe/counting/soe_counting_cfg.h`` (`API <./../../../../../../_static/doxygen/src/html/soe__counting__cfg_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__counting__cfg_8h_source.html>`__) Unit Test ^^^^^^^^^ - ``tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soe__counting_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soe__counting_8c_source.html>`__) -- ``tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting_cfg.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soe__counting__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soe__counting__cfg_8c_source.html>`__) Detailed Description -------------------- diff --git a/docs/software/modules/application/algorithm/state-estimation/soe/soe_debug.rst b/docs/software/modules/application/algorithm/state-estimation/soe/soe_debug.rst index 67a52e26..898e1b1b 100644 --- a/docs/software/modules/application/algorithm/state-estimation/soe/soe_debug.rst +++ b/docs/software/modules/application/algorithm/state-estimation/soe/soe_debug.rst @@ -13,19 +13,16 @@ Driver ^^^^^^ - ``src/app/application/algorithm/state_estimation/soe/debug/soe_debug.c`` (`API <./../../../../../../_static/doxygen/src/html/soe__debug_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__debug_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soe/debug/soe_debug.h`` (`API <./../../../../../../_static/doxygen/src/html/soe__debug_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__debug_8h_source.html>`__) Configuration ^^^^^^^^^^^^^ -- ``src/app/application/algorithm/state_estimation/soe/debug/soe_debug_cfg.c`` (`API <./../../../../../../_static/doxygen/src/html/soe__debug__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__debug__cfg_8c_source.html>`__) - ``src/app/application/algorithm/state_estimation/soe/debug/soe_debug_cfg.h`` (`API <./../../../../../../_static/doxygen/src/html/soe__debug__cfg_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__debug__cfg_8h_source.html>`__) Unit Test ^^^^^^^^^ - ``tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soe__debug_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soe__debug_8c_source.html>`__) -- ``tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug_cfg.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soe__debug__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soe__debug__cfg_8c_source.html>`__) Detailed Description -------------------- diff --git a/docs/software/modules/application/algorithm/state-estimation/soe/soe_none.rst b/docs/software/modules/application/algorithm/state-estimation/soe/soe_none.rst index 4337eada..11757889 100644 --- a/docs/software/modules/application/algorithm/state-estimation/soe/soe_none.rst +++ b/docs/software/modules/application/algorithm/state-estimation/soe/soe_none.rst @@ -13,19 +13,16 @@ Driver ^^^^^^ - ``src/app/application/algorithm/state_estimation/soe/none/soe_none.c`` (`API <./../../../../../../_static/doxygen/src/html/soe__none_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__none_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soe/none/soe_none.h`` (`API <./../../../../../../_static/doxygen/src/html/soe__none_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__none_8h_source.html>`__) Configuration ^^^^^^^^^^^^^ -- ``src/app/application/algorithm/state_estimation/soe/none/soe_none_cfg.c`` (`API <./../../../../../../_static/doxygen/src/html/soe__none__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__none__cfg_8c_source.html>`__) - ``src/app/application/algorithm/state_estimation/soe/none/soe_none_cfg.h`` (`API <./../../../../../../_static/doxygen/src/html/soe__none__cfg_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soe__none__cfg_8h_source.html>`__) Unit Test ^^^^^^^^^ - ``tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soe__none_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soe__none_8c_source.html>`__) -- ``tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none_cfg.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soe__none__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soe__none__cfg_8c_source.html>`__) Detailed Description -------------------- diff --git a/docs/software/modules/application/algorithm/state-estimation/sof/trapezoid.rst b/docs/software/modules/application/algorithm/state-estimation/sof/sof_trapezoid.rst similarity index 65% rename from docs/software/modules/application/algorithm/state-estimation/sof/trapezoid.rst rename to docs/software/modules/application/algorithm/state-estimation/sof/sof_trapezoid.rst index e377851e..2070cbc3 100644 --- a/docs/software/modules/application/algorithm/state-estimation/sof/trapezoid.rst +++ b/docs/software/modules/application/algorithm/state-estimation/sof/sof_trapezoid.rst @@ -30,4 +30,19 @@ Unit Test Detailed Description -------------------- -|tbc| +The state of function estimation (SOF) calculates current derating values to +operate the battery system within the safe operating area. These charge and +discharge derating values are calculated according to battery cell specific +and battery system related constraints. + +For this, the operating limits for the cell voltage and cell temperature are +taken into account. Two derating points are defined for each of these limits. +A **cut-off** value where the derating begins and the allowed current starts to +be decreased and a **limit** value where no current flow is allowed anymore. +The allowed current is linearly decreased between these two points. + +Additionally, the electrical string current capability are consider and the +allowed current is limited below this value. This value needs to be configured +according to the design of the battery system. Important factors for this are +for example the selected contactors and connectors or the busbar/wire cross +section. diff --git a/docs/software/modules/application/algorithm/state-estimation/soh/soh_debug.rst b/docs/software/modules/application/algorithm/state-estimation/soh/soh_debug.rst index 48728fa4..b7b39bfc 100644 --- a/docs/software/modules/application/algorithm/state-estimation/soh/soh_debug.rst +++ b/docs/software/modules/application/algorithm/state-estimation/soh/soh_debug.rst @@ -13,19 +13,14 @@ Driver ^^^^^^ - ``src/app/application/algorithm/state_estimation/soh/debug/soh_debug.c`` (`API <./../../../../../../_static/doxygen/src/html/soh__debug_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soh__debug_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soh/debug/soh_debug.h`` (`API <./../../../../../../_static/doxygen/src/html/soh__debug_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soh__debug_8h_source.html>`__) Configuration ^^^^^^^^^^^^^ -- ``src/app/application/algorithm/state_estimation/soh/debug/soh_debug_cfg.c`` (`API <./../../../../../../_static/doxygen/src/html/soh__debug__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soh__debug__cfg_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soh/debug/soh_debug_cfg.h`` (`API <./../../../../../../_static/doxygen/src/html/soh__debug__cfg_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soh__debug__cfg_8h_source.html>`__) - Unit Test ^^^^^^^^^ - ``tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soh__debug_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soh__debug_8c_source.html>`__) -- ``tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug_cfg.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soh__debug__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soh__debug__cfg_8c_source.html>`__) Detailed Description -------------------- diff --git a/docs/software/modules/application/algorithm/state-estimation/soh/soh_none.rst b/docs/software/modules/application/algorithm/state-estimation/soh/soh_none.rst index 964142e4..476b67a3 100644 --- a/docs/software/modules/application/algorithm/state-estimation/soh/soh_none.rst +++ b/docs/software/modules/application/algorithm/state-estimation/soh/soh_none.rst @@ -13,19 +13,14 @@ Driver ^^^^^^ - ``src/app/application/algorithm/state_estimation/soh/none/soh_none.c`` (`API <./../../../../../../_static/doxygen/src/html/soh__none_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soh__none_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soh/none/soh_none.h`` (`API <./../../../../../../_static/doxygen/src/html/soh__none_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soh__none_8h_source.html>`__) Configuration ^^^^^^^^^^^^^ -- ``src/app/application/algorithm/state_estimation/soh/none/soh_none_cfg.c`` (`API <./../../../../../../_static/doxygen/src/html/soh__none__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/src/html/soh__none__cfg_8c_source.html>`__) -- ``src/app/application/algorithm/state_estimation/soh/none/soh_none_cfg.h`` (`API <./../../../../../../_static/doxygen/src/html/soh__none__cfg_8h.html>`__, `source <./../../../../../../_static/doxygen/src/html/soh__none__cfg_8h_source.html>`__) - Unit Test ^^^^^^^^^ - ``tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soh__none_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soh__none_8c_source.html>`__) -- ``tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none_cfg.c`` (`API <./../../../../../../_static/doxygen/tests/html/test__soh__none__cfg_8c.html>`__, `source <./../../../../../../_static/doxygen/tests/html/test__soh__none__cfg_8c_source.html>`__) Detailed Description -------------------- diff --git a/docs/software/modules/application/algorithm/state-estimation/state-estimation.rst b/docs/software/modules/application/algorithm/state-estimation/state-estimation.rst index 2f87c814..09b9e0a5 100644 --- a/docs/software/modules/application/algorithm/state-estimation/state-estimation.rst +++ b/docs/software/modules/application/algorithm/state-estimation/state-estimation.rst @@ -8,10 +8,10 @@ State estimation |foxbms| performs various state estimations for the battery system: - - state-of-charge (|soc|) - - state-of-energy (|soe|) - - state-of-health (|soh|) - - state-of-function (|sof|) +- state-of-charge (|soc|) +- state-of-energy (|soe|) +- state-of-health (|soh|) +- state-of-function (|sof|) The |soc| estimation is used to estimate the currently remaining charge (|Ah|) within the battery system whereas the |soe| estimation provides the remaining @@ -55,7 +55,7 @@ the battery system configuration file (`bms.json`). ./soe/soe_counting.rst ./soe/soe_debug.rst ./soe/soe_none.rst - ./sof/trapezoid.rst + ./sof/sof_trapezoid.rst ./soh/soh_debug.rst ./soh/soh_none.rst diff --git a/docs/software/modules/application/bal/bal.rst b/docs/software/modules/application/bal/bal.rst index d99de068..627e43fd 100644 --- a/docs/software/modules/application/bal/bal.rst +++ b/docs/software/modules/application/bal/bal.rst @@ -13,9 +13,7 @@ Driver ^^^^^^ - ``src/app/application/bms/history/bal_strategy_history.c`` (`API <../../../../_static/doxygen/src/html/bal__strategy__history_8c.html>`__, `source <../../../../_static/doxygen/src/html/bal__strategy__history_8c_source.html>`__) -- ``src/app/application/bms/history/bal_strategy_history.h`` (`API <../../../../_static/doxygen/src/html/bal__strategy__history_8h.html>`__, `source <../../../../_static/doxygen/src/html/bal__strategy__history_8h_source.html>`__) - ``src/app/application/bms/none/bal_strategy_none.c`` (`API <../../../../_static/doxygen/src/html/bal__strategy__none_8c.html>`__, `source <../../../../_static/doxygen/src/html/bal__strategy__none_8c_source.html>`__) -- ``src/app/application/bms/none/bal_strategy_none.h`` (`API <../../../../_static/doxygen/src/html/bal__strategy__none_8h.html>`__, `source <../../../../_static/doxygen/src/html/bal__strategy__none_8h_source.html>`__) - ``src/app/application/bms/voltage/bal_strategy_voltage.c`` (`API <../../../../_static/doxygen/src/html/bal__strategy__voltage_8c.html>`__, `source <../../../../_static/doxygen/src/html/bal__strategy__voltage_8c_source.html>`__) - ``src/app/application/bms/voltage/bal_strategy_voltage.h`` (`API <../../../../_static/doxygen/src/html/bal__strategy__voltage_8h.html>`__, `source <../../../../_static/doxygen/src/html/bal__strategy__voltage_8h_source.html>`__) - ``src/app/application/bms/bal.c`` (`API <../../../../_static/doxygen/src/html/bal_8c.html>`__, `source <../../../../_static/doxygen/src/html/bal_8c_source.html>`__) @@ -36,7 +34,6 @@ Unit Test Detailed Description -------------------- - .. _BALANCING_MODULE_VOLTAGE_BASED_BALANCING: Voltage-based Balancing @@ -88,8 +85,10 @@ each specific cell only if its cell voltage is above the minimum cell voltage of threshold is set in this case to ``BAL_GetBalancingThreshold_mV()`` + ``BAL_HYSTERESIS_mV``. The correspondence between cell voltage and SOC must be defined by the user depending on the specific battery cells -used. Currently, it is done in the function ``SE_GetStateOfChargeFromVoltage()`` in ``sox.c``. This function gets a voltage in V -and return an SOC between 0.0 and 1.0. +used. +Currently, it is done in the function ``SE_GetStateOfChargeFromVoltage()`` in +``soc_counting.c``, ``soc_debug.c``, ``soc_none.c``, or ``state_estimation.h``. +This function gets a voltage in V and return an SOC between 0.0 and 1.0. .. _BALANCING_MODULE_NO_BALANCING: diff --git a/docs/software/modules/application/bms/bms_how-to.rst b/docs/software/modules/application/bms/bms_how-to.rst new file mode 100644 index 00000000..510ac895 --- /dev/null +++ b/docs/software/modules/application/bms/bms_how-to.rst @@ -0,0 +1,37 @@ +.. include:: ../../../../macros.txt +.. include:: ../../../../units.txt + +.. _HOW_TO_REACH_STANDBY_STATE: + +How to reach STANDBY state +========================== + +In *STANDBY* state, the BMS is monitoring and controlling the balancing, +recalibrates the |soc| and is waiting for a state request to close the +contactors. + +Following conditions MUST be met, that the BMS switches into *STANDBY* state: + +#. No error from a diagnosis entry with a severity of ``DIAG_FATAL_ERROR`` + defined in ``src\app\engine\config\diag_cfg.c`` MUST be detected. +#. Depending on the configuration of *BS_CHECK_CAN_TIMING* in file + ``src\app\application\config\battery_system_cfg.c`` the state request + message **foxBMS_BmsStateRequest** MUST be received periodically via CAN. +#. **STANDBY** state MUST be requested via signal **foxBMS_modeRequest** in + message **foxBMS_BmsStateRequest**. + +How to recalibrate the SOC +========================== + +The |soc| is automatically recalibrated by the BMS in STANDBY state if the +battery system is in a rest phase (**BMS_AT_REST**). +This state is reached if for duration of **BS_RELAXATION_PERIOD_10ms**, the +current drawn from or supplied to the battery system is below +**BS_REST_CURRENT_mA**. +The default values for these defines are 200 |mA| and 600000 |ms|. +This means that with the default configuration, the battery system will enter +the rest phase if for 10 minutes no current above 200 |mA| is drawn from or +supplied to the battery system. +Both defines are configured in file +``src\app\application\config\battery_system_cfg.c`` the system will begin the +relaxation phase (**BMS_RELAXATION**). diff --git a/docs/software/modules/driver/afe/adi/adi_ades1830.rst b/docs/software/modules/driver/afe/adi/adi_ades1830.rst new file mode 100644 index 00000000..4ae14a35 --- /dev/null +++ b/docs/software/modules/driver/afe/adi/adi_ades1830.rst @@ -0,0 +1,1067 @@ +.. include:: ./../../../../../macros.txt +.. include:: ./../../../../../units.txt + +.. _ADI_ADES1830: + +ADI ADES1830 +============ + +The communication with the AFE is made via a daisy-chain, which means that all +the AFEs take part in every transmission. + +There are 3 types of communications: + +- Sending a command without data (e.g., start a measurement). +- Writing a register. +- Reading a register. + +Commands are sent to the whole daisy-chain, which means that for commands +the daisy-chain acts as a transmission line. + +When reading and writing, the daisy-chain acts as a shift register. +The registers read or written are 6 bytes wide. + +The data packets are made of bytes (8 bit words). +The driver was developed on a |ti-tms570|. +As the |ti-tms570| SPI can transmit up to 16 bit per word, all HAL SPI function +work with 16 bit words. +As a consequence, all AFE functions work with 16 bit words, but each +word must only contain one byte (i.e., the value must not be greater than +255). + +A common parameter to all AFE functions has the type ``ADI_STATE_s``. +This structure is used to control the flow of the AFE driver. +The structure holds the following information +(for implementation details see +`here <../../../../_static/doxygen/src/html/structADI__STATE__s.html>`__): + +- A boolean indicating if the driver has been initialized or not, i.e., whether + the first measurement has been started or not. +- A boolean set to ``true`` after the first measurement was made. +- The number of SPI interfaces to be used. + Usually it corresponds to the number of strings in the system. +- The number of the string currently addressed. +- A table used to store the redundant GPIO channel being used. + This is an internal variable for the driver and should not be modified. +- The serial IDs read from the AFEs in the daisy-chain. +- The revision read from the AFEs in the daisy-chain. +- A structure of the type ``ADI_DATA_s``. + It is used to store pointers to all relevant data (e.g., measured cell + voltages, measured temperatures). + It also stores the command counter for each string and an error table + with all error flags. + +The ``ADI_DATA_s`` structure contains the following data +(for implementation details see +`here <../../../../_static/doxygen/src/html/structADI__DATAPTR__s.html>`__): + +- A pointer to the SPI receive and the transmit buffer +- All measurements (e.g., cell voltages, cell temperatures, GPIO voltages) +- The command counter for each AFE +- The error table, a structure of the type ``ADI_ERROR_TABLE_s`` +- An internal variable of the driver used for redundant auxiliary voltage + check. + +The ``ADI_ERROR_TABLE_s`` structure contains the error status of the driver +(for implementation details see +`here <../../../../_static/doxygen/src/html/structADI__ERROR__TABLE__s.html>`__): + +- Flag indicating if PEC correct or not +- Flag indicating if the command counter of the driver matches the internal + command counter of the AFEs +- Flag indicating if the configuration read from the AFEs matches the written + configuration + +Functions to adapt to change environment +---------------------------------------- + +The AFE driver in its current form is designed to work within foxBMS 2, +using |freertos|. +In order to use it in another environment (e.g., bare metal), +it must be adapted in the following places. + +Definitions +^^^^^^^^^^^ + +The function used in the AFE driver make use of the following enum +as return value: + +.. code-block:: c + + /** enum for standard return type */ + typedef enum { + STD_OK, /**< ok */ + STD_NOT_OK, /**< not ok */ + } STD_RETURN_TYPE_e; + +It must be added if it is not defined. + +Dedicated structures are used to store the data retrieved by the driver. +If they are not defined, the following definitions must be added: + +.. code-block:: c + + /** data block struct of cell voltages */ + typedef struct { + int16_t cellVoltage_mV[ADI_NR_OF_STRINGS][ADI_NR_OF_CELL_BLOCKS_PER_STRING]; /*!< unit: mV */ + } DATA_BLOCK_CELL_VOLTAGE_s; + + /** data block struct of GPIO voltages */ + typedef struct { + int16_t gpioVoltages_mV[ADI_NR_OF_STRINGS] + [ADI_NR_OF_MODULES_PER_STRING * ADI_NR_OF_GPIOS_PER_MODULE]; /*!< unit: mV */ + int16_t gpaVoltages_mV[ADI_NR_OF_STRINGS] + [ADI_NR_OF_MODULES_PER_STRING * ADI_NR_OF_GPAS_PER_MODULE]; /*!< unit: mV */ + } DATA_BLOCK_ALL_GPIO_VOLTAGES_s; + + /** data block struct of cell temperatures */ + typedef struct { + int16_t cellTemperature_ddegC[ADI_NR_OF_STRINGS][ADI_NR_OF_TEMP_SENSORS_PER_STRING]; /*!< unit: deci °C */ + } DATA_BLOCK_CELL_TEMPERATURE_s; + + /** data block struct of balancing control */ + typedef struct { + uint8_t balancingState[ADI_NR_OF_STRINGS] + [ADI_NR_OF_CELL_BLOCKS_PER_STRING]; /*!< 0: no balancing, 1: balancing active */ + } DATA_BLOCK_BALANCING_CONTROL_s; + + /** data block struct of cell open wire */ + typedef struct { + uint8_t openWire[ADI_NR_OF_STRINGS] + [ADI_NR_OF_MODULES_PER_STRING * + (ADI_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)]; /*!< 1 -> open wire, 0 -> everything ok */ + } DATA_BLOCK_OPEN_WIRE_s; + +They must be added at the place in code marked with: + +.. code-block:: c + + /* If needed, add definition of database entries here */ + +in the file ``adi_ades183x_defs.h``. + +In the file ``adi_cfg.h``, the following defines must be adapted: + +.. code-block:: c + + #define ADI_NR_OF_STRINGS (BS_NR_OF_STRINGS) + #define ADI_NR_OF_MODULES_PER_STRING (BS_NR_OF_MODULES_PER_STRING) + #define ADI_NR_OF_CELL_BLOCKS_PER_MODULE (BS_NR_OF_CELL_BLOCKS_PER_MODULE) + #define ADI_NR_OF_GPIOS_PER_MODULE (BS_NR_OF_GPIOS_PER_MODULE) + #define ADI_NR_OF_TEMP_SENSORS_PER_MODULE (BS_NR_OF_TEMP_SENSORS_PER_MODULE) + #define ADI_MAX_SUPPORTED_CELLS (16u) + +``ADI_NR_OF_STRINGS`` must be set to ``1u`` if only one string is used. +If several strings are used, the SPI function must be adapted to take this +into account. + +``ADI_NR_OF_MODULES_PER_STRING`` is the number of modules in one daisy-chain +so corresponds to the number of AFEs in a daisy-chain. + +``ADI_NR_OF_CELL_BLOCKS_PER_MODULE`` is the number of cells connected to +an AFE. + +``ADI_NR_OF_GPIOS_PER_MODULE`` is the number of GPIOs available on an AFE. +It must be set to ``10u``. + +``ADI_NR_OF_TEMP_SENSORS_PER_MODULE`` is the number of temperature sensors +connected to the GPIOs. +It cannot be higher than ``ADI_NR_OF_GPIOS_PER_MODULE``. + +``ADI_MAX_SUPPORTED_CELLS`` is the maximum number of cell voltage inputs +present on the AFE. +For the ADES1830, it must be set to ``16``. + +Static functions +^^^^^^^^^^^^^^^^ + +``ADI_SpiTransmitReceiveData()`` is the function used to trigger +transmission over SPI. +It takes four parameters: + +- a struct of the type ``ADI_STATE_s``, which is used to determine which + string has to be addressed +- a pointer to the transmit buffer +- a pointer to the receive buffer +- the number of bytes to be transmitted + +Three cases must be considered, each contained in +the markers + +.. code-block:: c + + /* START SPI function to adapt for different environment */ + /* Code to be defined here to make SPI transmission */ + /* END SPI function to adapt for different environment */ + +in the code. +There are three cases to consider: + +- case 1: if a length of ``0`` is used, this means that the function must only send + a dummy byte. +- if a length greater than ``0`` is used: + + - case 2: if the pointer to the receive buffer has the value ``NULL_PTR``, this + means that the function has only data to transmit and that the data + received on the SPI interface is discarded. + - case 3: otherwise the function transmits and receives data. + +.. warning:: + + For the last two cases, before the data transmission and/or reception, + a dummy byte must be sent to wake up the AFE communication interface. + +The function ``ADI_AccessToDatabase()`` is used to store and retrieve the +data from the foxBMS 2 database. +If the database is not used, the function content can simply be removed. + +The function ``ADI_Wait()`` receives an integer parameter. +The function must wait for the number of milliseconds passed as parameter. +In foxBMS 2, it blocks the |freertos| task running the AFE driver. + +The AFE driver looks for requests to start or stop. +Requests are made made with the extern function ``ADI_MakeRequest()``. +The static function ``ADI_GetRequest()`` is used to retrieve the requests +made to the driver. +In foxBMS 2, a |freertos| queue is used. +If this environment is not used, the request mechanism must be adapted +accordingly and the reference to the queue must be removed if the queue is not +used. +If the request mechanism is not needed or for debugging purposes, the +function ``ADI_GetRequest()`` can simply be changed to always set the +request to ``ADI_START_REQUEST``. + +The functions ``OS_EnterTaskCritical()`` and ``OS_ExitTaskCritical()`` are +used to prevent interrupts during the setting of the flags to ensure the +validity of the flags. +They must be replaced by an appropriate protection mechanism if |freertos| +is not used. + +Extern functions +^^^^^^^^^^^^^^^^ + +In foxBMS 2, a |freertos| queue is used in the function ``ADI_MakeRequest()``. +If this environment is not used, the request mechanism must be adapted +accordingly and the reference to the queue must be removed if the queue is +not used. +As explained above, if requests are not needed or for debugging +purposes, if the function ``ADI_GetRequest()`` is changed to always set the +request to ``ADI_START_REQUEST``, the function ``ADI_MakeRequest()`` can +simply be changed to do nothing. + +The function ``ADI_ActivateInterfaceBoard()`` is used to drive an I2C port +expander, to toggle activation pins in order to activate the interface board +communicating with the slave. +It must be adapted to the hardware used. + +The function ``ADI_ConvertGpioVoltageToTemperature()`` converts a GPIO +voltage in mV to a temperature in deci Celsius. +It must be adapted to the hardware used. + +Primitives for communication +---------------------------- + +As stated before, the communication with the daisy-chain is made via three +basic operations. +They are detailed in this section. + +Each transaction with the daisy-chain starts with a command. +It is then followed by data when reading from or writing to the AFE, +or by nothing for command not involving data (e.g., when triggering +a measurement). + +Each command is accessible via a dedicated variable, like + +.. code-block:: c + + const uint16_t adi_cmdWrcfga[4u] = {ADI_WRCFGA_BYTE0, ADI_WRCFGA_BYTE1, ADI_WRCFGA_INC, ADI_WRCFGA_LEN}; + +to write configuration register A. +Each variable has four fields: + +- command byte 0 +- command byte 1 +- 1 if the command increments the command counter, 0 otherwise +- data length in bytes. + For writing and reading register, it is 6. + For commands not involving data, it can be set to 0. + +A list of defines was created for these fields for each command. +They are located in the file ``adi_ades183x_defs.h``. + +Sending commands without data +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The function ``ADI_TransmitCommand()`` is used for this purpose. +It has four parameters: + +- a ``uint16_t`` pointer. + As commands sent to the AFE are made out of 2 bytes, it must point to two + bytes, corresponding to the used command as defined in the data sheet. + One of the commands defined as explained above must be used. +- a pointer to the ``ADI_STATE_s`` structure. + +The functions to send commands are illustrated in +:numref:`send-command-ades1830`. + + .. figure:: img/ades1830/adi_ades1830_primitive_send_command.png + :alt: Functions used to send commands + :name: send-command-ades1830 + :align: center + :width: 35 % + + Functions used to send commands + +Some commands have configurable bits (e.g., measurement commands, in order +to change measurement parameters). +Base commands have been defined as constant variables and for concerned +commands, the configurable bits are set to 0. +The function ``ADI_TransmitCommand()`` takes the command +as a non-constant variable, so the following procedure must be used: + +- Use ``ADI_CopyCommandBits()`` to copy the constant command definition + to a non constant variable. + This variable must be an ``uint16_t`` table of length 4. +- If necessary, use ``ADI_WriteCommandConfigurationBits()`` to modify + the configurable bits as needed. +- Call ``ADI_TransmitCommand()`` with the non constant variable. + +The function realizes the following operations: + +- The function computes the PEC of the two command bytes and then + sends 4 bytes (2 bytes command followed by two bytes PEC). +- If the command sent increments the AFE command counter, the + command counter stored in the driver and accessed via the + ``ADI_DATA_s`` structure in the ``ADI_STATE_s`` structure is + increased. + The comparison between the AFE command counter and the + command counter stored by the driver is made in the function + ``ADI_ReadRegister()``, as the AFE transmits its command counter + in each answer frame. + +Reading a register +^^^^^^^^^^^^^^^^^^ + +The function ``ADI_ReadRegister()`` is used for this purpose. +It has three parameters: + +- An ``uint16_t`` pointer to the command corresponding to the register to read. + One of the commands defined as explained above must be used. +- A uint8_t pointer to the table where the read data is stored +- A pointer to the ``ADI_STATE_s`` structure + +The functions and variables to read registers are illustrated in +:numref:`read-register-ades1830`. + + .. figure:: img/ades1830/adi_ades1830_primitive_read_register.png + :alt: Functions and variables used to read registers + :name: read-register-ades1830 + :align: center + :width: 55 % + + Functions and variables used to read registers + +The function realizes the following operations: + +- The SPI transmit/receive function is used to transmit the command and + receive the data: + + - First the two bytes of the command must be transmitted, followed by the + two command PEC bytes. + The command PEC is computed with the PEC15 function. + - Then the AFE ICs in the daisy-chain transform into a shift-register + to transmit the data to be read while the MCU receives it. + This data consists of one frame for each AFE. + Each frame contains 4 or 6 bytes, depending on the register size, followed + by two bytes of data PEC. + Data PEC is computed with the PEC10 function. + +- The function computes the PEC of each data frame and compare it to the + PEC sent by each AFE. + If it does not match, the corresponding ``crcIsOk`` variable in the + ``ADI_ERROR_TABLE_s`` structure is set to ``false``. + It is set to ``true`` otherwise. +- The function extract the command counter sent by each AFE and + compares it with the value stored in the driver in the ``ADI_DATA_s`` + structure. + If it does not match, the corresponding ``commandCounterIsOk`` + variable in the ``ADI_ERROR_TABLE_s`` structure is set to ``false``. + It is set to ``true`` otherwise. + +The variable +``uint8_t adi_dataReceive[ADI_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]`` +is a general purpose variable used throughout the driver as a buffer when +using the read function. + +Writing a register +^^^^^^^^^^^^^^^^^^ + +The function ``ADI_WriteRegister()`` is used for this purpose. +It has three parameters: + +- A ``uint16_t`` pointer to the command corresponding to the register to write. + One of the commands defined as explained above must be used. +- A uint8_t pointer to the table where the data to be written is stored +- A variable of the type ``ADI_PEC_FAULT_INJECTION_e`` used for fault + injection. +- A pointer to the ``ADI_STATE_s`` structure + +The functions and variables to write registers are illustrated in +:numref:`write-register-ades1830`. + + .. figure:: img/ades1830/adi_ades1830_primitive_write_register.png + :alt: Functions and variables used to write registers + :name: write-register-ades1830 + :align: center + :width: 55 % + + Functions and variables used to write registers + +The function realizes the following operations: + +- The data to be sent for the transmission is prepared: + + - First the two bytes of the command must be transmitted, followed by the + two command PEC bytes. + Command PEC is computed with the PEC15 function. + - Then the PEC of the written data must be computed. + This data consists of one frame for each AFE. + Each frame contains 4 or 6 bytes, depending on the register size, followed + by two bytes of data PEC. + Data PEC is computed with the PEC10 function. + +- The SPI transmit/receive function is used to transmit the command and + followed by the data. + After the command was received, the AFEs in the daisy-chain transform into + a shift-register to receive the data to be written while the MCU + transmits it. + +The fault injection can be of 3 types: + +- ``ADI_PEC_NO_FAULT_INJECTION``, the write process is made without + fault injection +- ``ADI_COMMAND_PEC_FAULT_INJECTION``, the write process is made and + the command PEC is modified so that it does not correspond anymore to the + command sent for writing +- ``ADI_DATA_PEC_FAULT_INJECTION``, the write process is made and + the data is modified so that it does not correspond anymore to the data + PEC sent + +The variable +``uint8_t adi_dataTransmit[ADI_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]`` +is a general purpose variable used throughout the driver as a buffer when +using the write function. + +The function ``ADI_WriteRegisterGlobal()`` is equivalent to +``ADI_WriteRegister()``, writing the same 6 bytes of data to +all AFEs in the daisy-chain. +It is a practical way to write the same data to all AFEs. +The variable ``uint8_t adi_writeGlobal[ADI_MAX_REGISTER_SIZE_IN_BYTES]`` is a +buffer used to write the same 6 bytes (``ADI_MAX_REGISTER_SIZE_IN_BYTES`` +equals 6) of data to a register for all the AFE ICs in the daisy-chain. + +Important variables used by the driver +-------------------------------------- + +``uint16_t adi_bufferRxPec[ADI_N_BYTES_FOR_DATA_TRANSMISSION]`` and +``uint16_t adi_bufferTxPec[ADI_N_BYTES_FOR_DATA_TRANSMISSION]`` +are the SPI buffers used during all transmissions. +The number of bytes is +``(ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + ((ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES) * ADI_N_ADI))`` +or ``4+(6+2)*ADI_N_ADI``. +The transmission uses 2 bytes for the command, followed by 2 command PEC bytes, +followed by the data. +For each AFE in the daisy-chain, the transmission has maximum 6 bytes of data, +each followed by 2 data PEC bytes, hence the number of +data bytes being 6+2 time the number of AFEs in the daisy-chain. +In |foxbms|, as the AFE driver uses SPI with DMA, these two variables **MUST** +reside in a non cache-able area. +These two variables are internal to the working of the AFE driver and should +not be used for other purposes. + +Helper functions to access bit fields in registers +-------------------------------------------------- + +The function ``ADI_ReadDataBits()`` is used to extract a bit field from data +that has been read. +Its parameters are: + +- Read byte from daisy-chain, from which data field is to be extracted. +- Pointer to memory location (1 byte) where extracted data field will be + written. +- Position of bit field to extract. +- Mask of bit field to extract. + +The function ``ADI_WriteDataBits()`` is used to write a bit field in data +that has to be written. +Its parameters are: + +- Pointer to byte that will be written to daisy-chain, where data from bit + field will be written. +- Byte containing data to be written to bit field. +- Position of bit field to extract. +- Mask of bit field to extract. + +Bit field position and bit field masks are defined for all entries of all +configuration registers in ``adi_ades183x_defs.h``. + +When writing a bit field in a byte with ``ADI_WriteDataBits()``, the other +bit fields in the byte remain unchanged. + +Configuration of the AFE +------------------------ + +The driver should ensure that the configuration stored on the AFE ICs +in the daisy-chain corresponds to the configuration that was written. +As a consequence, the driver holds a copy of the configuration that is written +to the AFE ICs in the daisy-chain. +There are 2 tables, one for configuration register A and one for configuration +register B. +They are named ``adi_configurationRegisterAgroup[]`` and +``adi_configurationRegisterBgroup[]``. +Both tables have the size +``[ADI_NR_OF_STRINGS][ADI_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]`` +where ``ADI_MAX_REGISTER_SIZE_IN_BYTES`` which equals 6u is the +register size in bytes: the content of each configuration register +must be stored for each AFE in the daisy-chain. +In addition, this must be done for each string. + +In :numref:`configuration-tables-ades1830`, the tables are +represented to ease the comprehension. + + .. figure:: img/ades1830/adi_ades1830_configuration_tables.png + :alt: Tables holding configuration + :name: configuration-tables-ades1830 + :align: center + :width: 55 % + + Tables holding configuration + +When writing the configuration, the driver also reads it to check that it was +written correctly. +For this purpose, another set of tables exists, named +``adi_readConfigurationRegisterAgroup[]`` and +``adi_readConfigurationRegisterBgroup[]``. +They have the same size as the variables used to write the configuration. + +It must be noted that the figure only shows the tables for one string. +There is one configuration table set for each string. + +The procedure to set a specific configuration is made out of two steps: + +- Change the configuration in the configuration tables + ``adi_configurationRegisterAgroup[]`` and/or ``adi_configurationRegisterBgroup[]``. +- Write the configuration of the tables to the AFEs in the + daisy-chain. + +Changing configuration in tables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The functions to change configuration and their interaction with the +variables are illustrated in +:numref:`configuration-procedure-ades1830`. + + .. figure:: img/ades1830/adi_ades1830_configuration_procedure.png + :alt: Functions and variables used to write registers + :name: configuration-procedure-ades1830 + :align: center + :width: 100 % + + Functions and variables used to change configuration + +Two functions are available change the configuration in the configuration +tables: ``ADI_StoredConfigurationFillRegisterData()`` and +``ADI_StoredConfigurationFillRegisterDataGlobal()``. + +The function ``ADI_StoredConfigurationFillRegisterData()`` is used to +modify the values in a specific byte of a register, for one specific +IC in the daisy-chain. +Its parameters are: + +- Module number corresponding to the AFE whose configuration must be changed. +- ``ADI_CFG_REGISTER_SET_e`` parameter. + Used to specify which configuration + register must be written (i.e., used to chose between register A and B). +- Register offset: corresponds to the byte position in the register. + Defines are available in ``adi_ades183x_defs.h`` (``ADI_REGISTER_OFFSET0`` to + ``ADI_REGISTER_OFFSET0``). +- Data to be written to the bit field in the register. +- Bit field position. +- Bit field mask. +- ``ADI_STATE_s`` structure. + The string number is passed via this structure. + +``ADI_StoredConfigurationFillRegisterData()`` uses ``ADI_WriteDataBits()``, +so when writing a bit field in a byte, the other bit fields in the byte remain +unchanged. + +The function ``ADI_StoredConfigurationFillRegisterDataGlobal()`` simply +calls ``ADI_StoredConfigurationFillRegisterData()`` for all modules in a +daisy-chain. +It is a useful and simpler way to set the same configuration +for all AFEs in the daisy-chain. + +In :numref:`configuration-tables-ades1830-modification`, the use of the helper +functions to modify the configuration tables is represented to ease the +comprehension. + + .. figure:: img/ades1830/adi_ades1830_configuration_tables_modification.png + :alt: Modification of tables holding configuration + :name: configuration-tables-ades1830-modification + :align: center + :width: 55 % + + Modification of tables holding configuration + +Writing the changes to the daisy-chain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To write the changes to the daisy-chain, the function +``ADI_StoredConfigurationWriteToAfe()`` must be called. +The first parameter is an enum of the type ``ADI_CFG_REGISTER_SET_e``. +It serves to chose which register from the configuration tables to write and +can have values ranging, ``ADI_CFG_REGISTER_SET_A`` or +``ADI_CFG_REGISTER_SET_B``. +When called, the function ``ADI_StoredConfigurationWriteToAfe()`` writes +the data contained in the ``configurationRegisterX[]`` variable to the +daisy-chain. +For instance, if the function is called with ``ADI_CFG_REGISTER_SET_B`` as +first parameter, the content of ``adi_configurationRegisterBgroup[]`` will be +written to the daisy-chain. + +It must be noted that even if the tables have been changed, the change will +not be written to the daisy-chain until the function +``ADI_StoredConfigurationWriteToAfe()`` is called for the corresponding +register. + +After the write operation is complete, +``ADI_StoredConfigurationWriteToAfe()`` reads the register it has just +written to and stores the results in the table +``readConfigurationRegisterX[]``, where ``X`` again corresponds to the +configuration register being accessed. +``ADI_StoredConfigurationWriteToAfe()`` then calls +``ADI_CheckConfigurationRegister()``. +This function compares ``configurationRegisterX[]`` and +``readConfigurationRegisterX[]``. +If both table do not match, the corresponding (i.e., string and module number) +``configurationIsOk`` variable in the ``ADI_ERROR_TABLE_s`` structure is set +to ``false``. +It is set to ``true`` otherwise. + +The function ``ADI_StoredConfigurationWriteToAfeGlobal()`` is used to write +all configuration register at once. +It simply calls ``ADI_StoredConfigurationWriteToAfe()`` for all configuration +registers. + +``ADI_StoredConfigurationWriteToAfe()`` and +``ADI_StoredConfigurationWriteToAfeGlobal()`` use the primitives +``ADI_WriteRegister()`` and ``ADI_ReadRegister()`` to communicate with +the daisy-chain. + +Example of configuration write +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The procedure to change the IIR filter setting for cell voltage measurement +for all AFEs in the daisy-chain is as follows. +The corresponding bit field is located in configuration register A, byte +CFGAR5, bits [2:0]. + +First, set the configuration in ``adi_configurationRegisterAgroup[]`` with +``ADI_StoredConfigurationFillRegisterDataGlobal()``. + +.. code-block:: c + + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET0, + 0b001u, + ADI_CFGRA5_FC_0_2_POS, + ADI_CFGRA5_FC_0_2_MASK, + adi_state); + +Then call ``ADI_StoredConfigurationWriteToAfe()`` + +.. code-block:: c + + ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_A, adi_state); + +All bytes of the configuration register must be written during the transaction +but the function ``ADI_StoredConfigurationFillRegisterDataGlobal()`` only +changes the filter bit field in byte CFGAR5 of configuration register A, so +the other bit fields in this byte and the other bytes are written but with +their current value, which means they remain unchanged. + +Calling of the driver +--------------------- + +The principal function of the AFE driver is ``ADI_MeasurementCycle()``. +It must be called once (i.e., it must not be called periodically), because it +already implements the measurement loop. + +A structure of the type ``ADI_STATE_s`` must be defined and passed as +a pointer. +It controls the flow of the driver. +The driver loop is structured as follows: + +- The driver starts making no measurements and check for a start + request. + As long as no request was received, the driver does nothing + except checking for a request. +- When a start request is received, the driver calls the + initialization function ``ADI_InitializeMeasurement()``. +- Then the driver performs a measurement cycle: it loops through all the + strings and measures all relevant values and manages balancing. +- After the measurement cycle, the driver check if a stop request comes. + If yes, it goes back to the non-measuring state, waiting for a + start request. + If no, it performs another measurement cycle and the process goes on. + +The variable ``firstMeasurementMade`` of the ``ADI_STATE_s`` structure +must be initialized with ``false``. +Once one measurement cycle was made, it is set to ``true``. + +The variable ``measurementStarted`` of the ``ADI_STATE_s`` structure must be +initialized with ``false`` and is set to ``true`` of ``false`` depending on +the state of the driver. + +Initialization function +^^^^^^^^^^^^^^^^^^^^^^^ + +The function resets the error table with ``ADI_ResetErrorTable()``. + +Then for each string: + +- Send a dummy byte with ``ADI_WakeUp()`` to wake up the daisy-chain +- Clear the command counter with ``ADI_ClearCommandCounter()`` +- Set the default configuration of the AFE in two steps. + First, write the tables ``adi_configurationRegisterAgroup[]`` and + ``adi_configurationRegisterBgroup[]``, which is done in + ``ADI_InitializeConfiguration()``. + Then call ``ADI_StoredConfigurationWriteToAfeGlobal()`` to write the + tables to the daisy-chain. +- Check reset values of supply and reference measurements. +- Clear values with the ``CLRAUX`` command. +- Check cleared values of supply and reference measurements. +- Set all PWM balancing values to 0. +- Clear all flags in Status Register Group C with the ``CLRFLAG`` command. +- Issue an ``ADCV`` command to set continuous measurements of C-ADCs and + S-ADCS (S-ADCs are redundant measurements). +- Read revision of all AFEs in the daisy-chain. + +Measurement sequence +^^^^^^^^^^^^^^^^^^^^ + +The measurement sequence is as follows: + +- Issue an ``ADAX`` command to measure all GPIOs and all other voltages like + supply and references. +- Issue an ``ADAX2`` command to measure one GPIO redundantly. +- Wait 10 ms. +- Issue a ``SNAP`` command to freeze values in voltage registers . +- Get the cell voltages with ``ADI_GetVoltages()``. + This function reads the registers and stores the data in the + chosen structures pointed by the ``ADI_DATA_s`` structure. +- Wait 8 ms. + 18 ms is the time needed for the ``ADAX`` command to complete. +- Read the GPIO voltages with ``ADI_GetGpioVoltages()``. + This function reads the auxiliary registers and stores the data in the + chosen structures pointed by the ``ADI_DATA_s`` structure. +- Convert the GPIO voltages to temperatures with ``ADI_GetTemperatures()``. + This function stores the temperatures in the structure pointed by the + ``ADI_DATA_s`` structure. +- If the first measurement flag was not set, set it. +- Read the balancing orders and activate balancing accordingly with + ``ADI_BalanceControl()``. +- Realize diagnostic functions with ``ADI_Diagnostic()`` + (This is a dummy function). + +The functions that retrieve data from the daisy-chain call the function +``ADI_ReadRegister()``. +The balancing control is done by writing to the configuration registers. +The driver reads in the table ``adi_balancingControl`` which cells have to +be balanced. + +Reading measured cell voltages +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For cell voltages, the function ``ADI_GetVoltages()`` must be used. +Its first parameter is the ``ADI_DATA_s`` structure containing the state +of the driver. +Two parameters are also passed: + +- ``ADI_VOLTAGE_REGISTER_TYPE_e registerType``: it is used to determine + which register set must be read. + Possible values: + + - ``ADI_CELL_VOLTAGE_REGISTER`` to read cell voltage register (RDCVx) + - ``ADI_AVERAGE_CELL_VOLTAGE_REGISTER`` to read average cell voltage + registers (RDACx) + - ``ADI_FILTERED_CELL_VOLTAGE_REGISTER`` to read filtered cell voltage + registers (RDFCx) + - ``ADI_REDUNDANT_CELL_VOLTAGE_REGISTER`` to read S-voltage registers + (RDSVx) + +- ``ADI_VOLTAGE_STORE_LOCATION_e storeLocation``: it is used to determine + in which variable the read values will be stored. + Possible values: + + - ``ADI_CELL_VOLTAGE``: store in ``data.cellVoltage`` + - ``ADI_AVERAGE_CELL_VOLTAGE``: store in ``data.cellVoltageAverage`` + - ``ADI_FILTERED_CELL_VOLTAGE``: store in ``data.cellVoltageFiltered`` + - ``ADI_REDUNDANT_CELL_VOLTAGE``: store in ``data.cellVoltageRedundant`` + - ``ADI_CELL_VOLTAGE_OPEN_WIRE_EVEN``: store in ``data.cellVoltageOpenWireEven`` + - ``ADI_CELL_VOLTAGE_OPEN_WIRE_ODD``: store in ``data.cellVoltageOpenWireOdd`` + +Care must be taken when choosing the parameter values because ``registerType`` +and ``storeLocation`` are independent. +Calling for instance + +.. code-block:: c + + ADI_GetVoltages(adi_state, ADI_FILTERED_CELL_VOLTAGE_REGISTER, ADI_AVERAGE_CELL_VOLTAGE); + +will cause the filtered voltage measurements to be stored in +``data.cellVoltageAverage``, which is probably not what is intended. + +Reading measured GPIO voltages +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For GPIO voltages, the function ``ADI_GetGpioVoltages()`` must be used. +Its first parameter is the ``ADI_DATA_s`` structure containing the state +of the driver. +Two parameters are also passed: + +- ``ADI_AUXILIARY_REGISTER_TYPE_e registerType``: it is used to determine + which register set must be read. + Possible values: + + - ``ADI_AUXILIARY_REGISTER`` to read GPIO voltage register (RDAUXx) + - ``ADI_REDUNDANT_AUXILIARY_REGISTER`` to read average cell voltage + registers (RDRAXx) + +- ``ADI_AUXILIARY_STORE_LOCATION_e storeLocation``: it is used to determine + in which variable the read values will be stored. + Possible values: + + - ``ADI_AUXILIARY_VOLTAGE``: ``data.allGpioVoltages`` + - ``ADI_REDUNDANT_AUXILIARY_VOLTAGE``: ``data.allGpioVoltagesRedundant`` + - ``ADI_AUXILIARY_VOLTAGE_OPEN_WIRE``: ``data.allGpioVoltageOpenWire`` + +Care must be taken when choosing the parameter values because ``registerType`` +and ``storeLocation`` are independent. +Calling for instance + +.. code-block:: c + + adi_state, ADI_REDUNDANT_AUXILIARY_REGISTER, ADI_AUXILIARY_VOLTAGE); + +will cause the redundant voltage measurements to be stored in +``data.allGpioVoltages``, which is probably not what is intended. + +CRC computations +---------------- + +For commands, PEC15 is used. +It is a 15 bit CRC with polynomial ``0xC599`` and seed ``0x10``. + +For data, PEC10 is used. +It is a 10 bit CRC with polynomial ``0x48F`` and seed ``0x10``. +It is computed on the 6 bytes of data plus the 6 bits of the command counter. +For data to be written to the daisy-chain, the command counter bits are set to +0. + +The scripts and documentation for the precomputed CRC tables are found at +``tools/crc/crc-15_0xc599.md`` and ``tools/crc/crc-10_0x48f.md``. + +A C-implementation for the CRC pre-computation could look like this: + +.. literalinclude:: ./../../../../../../tools/crc/crc-15_0xc599.c + :language: c + :linenos: + :lines: 71-88 + :caption: CRC-15 Polynomial 0xC599 + +.. literalinclude:: ./../../../../../../tools/crc/crc-10_0x48f.c + :language: c + :linenos: + :lines: 71-88 + :caption: CRC-10 Polynomial 0x48F + +Parameters used to configure the driver +--------------------------------------- + +File ``adi_ades183x_cfg.h`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``ADI_DISCARD_PEC`` is used as a debugging option. +If set to ``true``, the PEC checks are ignored. +In normal usage it must be set to ``false``. + +File ``adi_ades1830_cfg.c`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``adi_voltageInputsUsed[]`` is used to skip cell voltages. +It contains 16 times the value ``1``. +All voltages are measured by the AFE but any value replaced by ``0`` will +result in the corresponding measured cell voltage input to be skipped when +storing the cell voltages. + +.. warning:: + + The number of ``1`` must correspond to + ``BS_NR_OF_CELL_BLOCKS_PER_MODULE``. + +``adi_temperatureInputsUsed[]`` is used to skip GPIO voltages. +It contains 10 times the value ``1``. +All GPIOs are measured by the AFE but any value replaced by ``0`` will result +in the corresponding GPIO voltage input to be skipped when storing the +temperatures. + +.. warning:: + + The number of ``1`` must correspond to + ``ADI_NR_OF_TEMP_SENSORS_PER_MODULE``. + +Examples for standard operations +-------------------------------- + +Reading a register +^^^^^^^^^^^^^^^^^^ + +Steps: + +- Define a variable to hold the command information. +- Copy the command information to it. +- Optionally, set the desired values for configuration bits in the + command. +- Call ``ADI_ReadRegister()``. +- The results are stored in the table passed as parameters. + The table ``adi_dataReceive[ADI_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]`` + can be used. +- Typically, loop through all modules to extract the needed bytes. +- ``ADI_ReadDataBits()`` can be used to extract a specific field. + Defines are available in the file ``adi_defs.h``. + +``ADI_MAX_REGISTER_SIZE_IN_BYTES`` has the value 6. + +Code example to read Status Register Group C: + +.. code-block:: c + + uint16_t adi_command[ADI_COMMAND_DEFINITION_LENGTH] = {0}; + + ADI_CopyCommandBits(adi_cmdRdstatc, adi_command); + ADI_ReadRegister(adi_command, adi_dataReceive, adi_state); + for (uint16_t m = 0u; m < ADI_N_ADI; m++) { + /* Get STR5 */ + uint8_t statusData = adi_dataReceive[(m * ADI_RDSTATC_LEN) + ADI_REGISTER_OFFSET5]; + /* Check COMP flag */ + uint8_t flagComp = 0u; + ADI_ReadDataBits(statusData, &flagComp, ADI_STCR5_COMP_POS, ADI_STCR5_COMP_MASK); + if (flagComp != 1u) { + adi_state->data.errorTable->compFlagIsCleared[adi_state->currentString][m] = false; + } + } + +Writing a register +^^^^^^^^^^^^^^^^^^ + +The function ``ADI_WriteRegister()`` is used to write a register. +The command information is passed directly to the function. +The table ``adi_dataTransmit[ADI_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]`` +can be used to store the data to write. +The parameter ``pecFaultInjection`` should always have the value +``ADI_PEC_NO_FAULT_INJECTION``, otherwise faults will be injected and +the write operation will not be valid. + +Code example to write PMW Register Group A: + +.. code-block:: c + + ADI_WriteRegister(adi_cmdWrpwma, adi_dataTransmit, ADI_PEC_NO_FAULT_INJECTION, adi_state); + +If the same data must be written to all AFEs in the daisy chain, the +function ``ADI_WriteRegisterGlobal()`` can be used. +The parameters are similar except for the data table: it is only 6 bytes wide. +The table +``adi_dataTransmit[ADI_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]`` +can be used to store the data to write. + +Code example to write PMW Register Group A, same 6 bytes for all AFEs in the +daisy-chain: + +.. code-block:: c + + ADI_WriteRegisterGlobal(adi_cmdWrpwma, adi_writeGlobal, ADI_PEC_NO_FAULT_INJECTION, adi_state); + +The variable ``adi_writeGlobal[ADI_MAX_REGISTER_SIZE_IN_BYTES]`` can be +used to hold the 6 bytes that must be written in the desired register for +AFEs in the daisy-chain. + +Sending a command +^^^^^^^^^^^^^^^^^ + +Steps: + +- Define a variable to hold the command information. +- Copy the command information to it. +- Optionally, set the desired values for configuration bits in the + command. + The function ``ADI_WriteCommandConfigurationBits()`` is + available for this purpose. + Defines are available in the files ``adi_ades183x_defs.h`` and + ``adi_ades1830_defs.h`` for the setup bits. + +The last parameter must be ``NULL_PTR`` when no data is sent with the +command. + +Code example to send a command without data: + +.. code-block:: c + + uint16_t adi_command[ADI_COMMAND_DEFINITION_LENGTH] = {0}; + + ADI_CopyCommandBits(adi_cmdAdcv, adi_command); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RD_POS, ADI_ADCV_RD_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_CONT_POS, ADI_ADCV_CONT_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_DCP_POS, ADI_ADCV_DCP_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RSTF_POS, ADI_ADCV_RSTF_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_OW01_POS, ADI_ADCV_OW01_LEN, 0u); + ADI_TransmitCommand(adi_command, adi_state, NULL_PTR); + +The CLRFLAG command must be sent with data to indicate which flags must be +cleared. +The variable ``adi_clearFlagData[ADI_CLRFLAG_DATA_LENGTH]`` can be +used for this purpose. +``ADI_CLRFLAG_DATA_LENGTH`` has the value 6. +``adi_clearFlagData[]`` must be set without the desired value and passed +instead of ``NULL_PTR``. + +Code example to send a command with data: + +.. code-block:: c + + ADI_CopyCommandBits(adi_cmdClrflag, adi_command); + adi_clearFlagData[ADI_REGISTER_OFFSET0] = 0u; + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS1FLT_POS, ADI_STCR0_CS1FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS2FLT_POS, ADI_STCR0_CS2FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS3FLT_POS, ADI_STCR0_CS3FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS4FLT_POS, ADI_STCR0_CS4FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS5FLT_POS, ADI_STCR0_CS5FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS6FLT_POS, ADI_STCR0_CS6FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS7FLT_POS, ADI_STCR0_CS7FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS8FLT_POS, ADI_STCR0_CS8FLT_MASK); + adi_clearFlagData[ADI_REGISTER_OFFSET1] = 0u; + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS9FLT_POS, ADI_STCR1_CS9FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS10FLT_POS, ADI_STCR1_CS10FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS11FLT_POS, ADI_STCR1_CS11FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS12FLT_POS, ADI_STCR1_CS12FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS13FLT_POS, ADI_STCR1_CS13FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS14FLT_POS, ADI_STCR1_CS14FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS15FLT_POS, ADI_STCR1_CS15FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS16FLT_POS, ADI_STCR1_CS16FLT_MASK); + adi_clearFlagData[ADI_REGISTER_OFFSET2] = 0u; + adi_clearFlagData[ADI_REGISTER_OFFSET3] = 0u; + adi_clearFlagData[ADI_REGISTER_OFFSET4] = 0u; + adi_clearFlagData[ADI_REGISTER_OFFSET5] = 0u; + ADI_TransmitCommand(adi_command, adi_state, adi_clearFlagData); diff --git a/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_configuration_procedure.png b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_configuration_procedure.png new file mode 100644 index 00000000..07564ac9 Binary files /dev/null and b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_configuration_procedure.png differ diff --git a/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_configuration_tables.png b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_configuration_tables.png new file mode 100644 index 00000000..f878d0ac Binary files /dev/null and b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_configuration_tables.png differ diff --git a/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_configuration_tables_modification.png b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_configuration_tables_modification.png new file mode 100644 index 00000000..6b88cb10 Binary files /dev/null and b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_configuration_tables_modification.png differ diff --git a/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_function_hierarchy.vsdx b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_function_hierarchy.vsdx new file mode 100644 index 00000000..3d13ecce Binary files /dev/null and b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_function_hierarchy.vsdx differ diff --git a/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_primitive_read_register.png b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_primitive_read_register.png new file mode 100644 index 00000000..00063a6c Binary files /dev/null and b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_primitive_read_register.png differ diff --git a/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_primitive_send_command.png b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_primitive_send_command.png new file mode 100644 index 00000000..394b2062 Binary files /dev/null and b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_primitive_send_command.png differ diff --git a/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_primitive_write_register.png b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_primitive_write_register.png new file mode 100644 index 00000000..4cd6a829 Binary files /dev/null and b/docs/software/modules/driver/afe/adi/img/ades1830/adi_ades1830_primitive_write_register.png differ diff --git a/docs/software/modules/driver/afe/maxim/max1785x.rst b/docs/software/modules/driver/afe/maxim/max1785x.rst index 3cd78cf0..70fd54cd 100644 --- a/docs/software/modules/driver/afe/maxim/max1785x.rst +++ b/docs/software/modules/driver/afe/maxim/max1785x.rst @@ -41,7 +41,6 @@ The three main modules are: * Implementation of the operation state machine in ``mxm_17852.c``. This implementation is selected by the driver variant in ``bms.json``. - Configuration ------------- @@ -54,7 +53,7 @@ In order to adapt the driver to new interface hardware, it is necessary to adapt the following: * Ensure that the functions that interact with the shutdown pin of - the |max17841b| bridge IC are correct. + the |max-max17841b| bridge IC are correct. They are implemented in ``mxm_cfg.c``. * Check the |spi| configuration of the system and that it aligns with the capabilities of the bridge IC. @@ -118,7 +117,7 @@ The following flow chart describes the main flow of this ``AFE`` driver. op_balancing --> op_mux_control } -* State `Unitialized`: This is the default state of the driver. +* State `Uninitialized`: This is the default state of the driver. The driver transitions with the next execution into the `Pre-Initialization Self Check` state. diff --git a/docs/software/modules/driver/afe/nxp/img/775a_balancing.png b/docs/software/modules/driver/afe/nxp/img/nxp-mc33775a_balancing.png similarity index 100% rename from docs/software/modules/driver/afe/nxp/img/775a_balancing.png rename to docs/software/modules/driver/afe/nxp/img/nxp-mc33775a_balancing.png diff --git a/docs/software/modules/driver/afe/nxp/img/775a_balancing.vsdx b/docs/software/modules/driver/afe/nxp/img/nxp-mc33775a_balancing.vsdx similarity index 100% rename from docs/software/modules/driver/afe/nxp/img/775a_balancing.vsdx rename to docs/software/modules/driver/afe/nxp/img/nxp-mc33775a_balancing.vsdx diff --git a/docs/software/modules/driver/afe/nxp/mc33775a.rst b/docs/software/modules/driver/afe/nxp/mc33775a.rst index c217a089..2522fb7f 100644 --- a/docs/software/modules/driver/afe/nxp/mc33775a.rst +++ b/docs/software/modules/driver/afe/nxp/mc33775a.rst @@ -22,15 +22,21 @@ NXP MC33775A Description ----------- -The |nxp775| monitoring IC can monitor 4 to 14 cells, with +/- 5V voltage. It has 8 GPIOs. -GPIO 4 and 5 can be used for I2C communication. GPIO 1 can be used as alarm line. - -The communication with the |nxp775| can be made directly via SPI or through a differential line. -This type of communication is called TPL. To translate SPI communication to TPL -communication, a bridge IC is used, called |nxp664|. - -In SPI mode, only 1 |nxp775| can communicate with the MCU. In TPL mode, the MCU can communicate with -up to 62 |nxp775| in daisy-chain. +The |nxp-mc33775a| monitoring IC can monitor 4 to 14 cells, with +/- 5V +voltage. +It has 8 GPIOs. +GPIO 4 and 5 can be used for I2C communication. GPIO 1 can be used as alarm +line. + +The communication with the |nxp-mc33775a| can be made directly via SPI or +through a differential line. +This type of communication is called TPL. +To translate SPI communication to TPL communication, a bridge IC is used, +called |nxp-mc33664|. + +In SPI mode, only 1 |nxp-mc33775a| can communicate with the MCU. +In TPL mode, the MCU can communicate with up to 62 |nxp-mc33775a| in +daisy-chain. Daisy-chain ----------- @@ -38,161 +44,195 @@ Daisy-chain Wake-up +++++++ -A device wakes up when there is any communication on the TPL bus. In addition, there is a WAKE-UP -command that can be sent. When an enumerated device receives a WAKE-UP command, it automatically -transmits an additional WAKE-UP message to the next device. When an unenumerated device receives -a WAKE-UP command, it automatically sends two additional WAKE-UP messages to the next devices. - -As a consequence, sending two WAKE-UP commands (separated by the wake-up delay) allows waking up -the entire daisy-chain. In the case of enumerated devices, it works as follows: - - - The MCU sends the first WAKE-UP command (WU0) - - IC0 is woken up by WU0 - - The MCU sends a second WAKE-UP command WU1 - - IC0 gets WU1 and forwards it to IC1, as IC0 is enumerated - - IC1 is woken up by WU1 - - IC0 automatically transmits a second WAKE-UP command (WU2) - - IC1 gets WU2 and forwards it to IC2, as IC1 is enumerated - - IC2 is woken up by WU2 - - IC2 automatically transmits a third WAKE-UP command (WU3) - - The process goes on until the whole daisy-chain is woken-up +A device wakes up when there is any communication on the TPL bus. +In addition, there is a WAKE-UP command that can be sent. +When an enumerated device receives a WAKE-UP command, it automatically +transmits an additional WAKE-UP message to the next device. +When an unenumerated device receives a WAKE-UP command, it automatically sends +two additional WAKE-UP messages to the next devices. + +As a consequence, sending two WAKE-UP commands (separated by the wake-up delay) +allows waking up the entire daisy-chain. In the case of enumerated devices, it +works as follows: + +- The MCU sends the first WAKE-UP command (WU0) +- IC0 is woken up by WU0 +- The MCU sends a second WAKE-UP command WU1 +- IC0 gets WU1 and forwards it to IC1, as IC0 is enumerated +- IC1 is woken up by WU1 +- IC0 automatically transmits a second WAKE-UP command (WU2) +- IC1 gets WU2 and forwards it to IC2, as IC1 is enumerated +- IC2 is woken up by WU2 +- IC2 automatically transmits a third WAKE-UP command (WU3) +- The process goes on until the whole daisy-chain is woken-up For an unenumerated daisy-chain, it works as follows: - - The MCU sends the first WAKE-UP command (WU0) - - IC0 is woken up by WU0 - - The MCU sends a second WAKE-UP command WU1 - - IC0 gets WU1 checks it - - IC0 sends WU1_1 to IC1 - - IC1 wakes up - - IC0 sends WU1_2 to IC1 - - IC1 checks WU1_2 - - IC1 sends WU2_1 to IC2 - - IC2 wakes up - - IC1 sends WU2_2 to IC2 - - IC2 checks WU2_2 - - IC2 sends WU3_1 to IC3 - - IC3 wakes up - - IC1 sends WU3_2 to IC3 - - IC3 checks WU3_2 - - The process goes on until the whole daisy-chain is woken-up +- The MCU sends the first WAKE-UP command (WU0) +- IC0 is woken up by WU0 +- The MCU sends a second WAKE-UP command WU1 +- IC0 gets WU1 checks it +- IC0 sends WU1_1 to IC1 +- IC1 wakes up +- IC0 sends WU1_2 to IC1 +- IC1 checks WU1_2 +- IC1 sends WU2_1 to IC2 +- IC2 wakes up +- IC1 sends WU2_2 to IC2 +- IC2 checks WU2_2 +- IC2 sends WU3_1 to IC3 +- IC3 wakes up +- IC1 sends WU3_2 to IC3 +- IC3 checks WU3_2 +- The process goes on until the whole daisy-chain is woken-up Addressing of slaves ++++++++++++++++++++ -In daisy-chain mode, every |nxp775| has its own address. The |nxp775| starts unenumerated, which -means its address is 0 and it does not forward messages. - -To enumerate an |nxp775|, a write command must be sent to the daisy-chain, to -write the address of the device in the ``SYS_COM_CFG`` register. For the first |nxp775|, -1 must be written in the address field: due to the use of 0 to -represent an unenumerated device, the addresses start at 1. The bus forwarding must be enabled, too, -by writing 1 to bit 9. After this procedure, the first |nxp775| is then enumerated. - -Once a |nxp775| is enumerated, it forwards all messages in both directions. For the second |nxp775|, -the configuration message with 2 in the address field must be sent to the daisy-chain. -As this address in the configuration message does not match the address of the first -|nxp775|, it is ignored and simply forwarded. The second |nxp775| then receives the configuration -message and becomes enumerated. -The MCU must then repeat the enumeration procedure for each unenumerated |nxp775| in the daisy-chain, -by sending the configuration message for address setup and forward enabling. - -When all the ICs in the daisy-chain are enumerated and forwarding is enabled, the communication between -the MCU and the daisy-chain works as follows: - - - when the MCU sends a message to the daisy-chain, it is received by IC(0). IC(0) forwards it to IC(1). - IC(1) forwards it to IC(2) and soon until the last IC in the daisy-chain receives the message. As each - message contains the address of the IC that is addressed by the MCU, this addressed IC knows it has - to interpret the message and not only forward it. - - When IC(n) sends a message to the MCU (e.g., response to a voltage measurement request), it sends it to - IC(n-1). IC(n-1) forwards it to IC(n-2) and so on until IC(0) forwards it to the MCU - -This means that when communicating with the daisy-chain, the MCU does not see a shift register. It sees -single devices to which it sends messages and which answer. +In daisy-chain mode, every |nxp-mc33775a| has its own address. +The |nxp-mc33775a| starts unenumerated, which means its address is 0 and it +does not forward messages. + +To enumerate an |nxp-mc33775a|, a write command must be sent to the +daisy-chain, to write the address of the device in the ``SYS_COM_CFG`` +register. +For the first |nxp-mc33775a|, 1 must be written in the address field: due to +the use of 0 to represent an unenumerated device, the addresses start at 1. +The bus forwarding must be enabled, too, by writing 1 to bit 9. +After this procedure, the first |nxp-mc33775a| is then enumerated. + +Once a |nxp-mc33775a| is enumerated, it forwards all messages in both +directions. +For the second |nxp-mc33775a|, the configuration message with 2 in the address +field must be sent to the daisy-chain. +As this address in the configuration message does not match the address of the +first |nxp-mc33775a|, it is ignored and simply forwarded. +The second |nxp-mc33775a| then receives the configuration message and becomes +enumerated. +The MCU must then repeat the enumeration procedure for each unenumerated +|nxp-mc33775a| in the daisy-chain, by sending the configuration message for +address setup and forward enabling. + +When all the ICs in the daisy-chain are enumerated and forwarding is enabled, +the communication between the MCU and the daisy-chain works as follows: + +- when the MCU sends a message to the daisy-chain, it is received by IC(0). + IC(0) forwards it to IC(1). + IC(1) forwards it to IC(2) and soon until the last IC in the daisy-chain + receives the message. + As each message contains the address of the IC that is addressed by the MCU, + this addressed IC knows it has to interpret the message and not only forward + it. +- When IC(n) sends a message to the MCU (e.g., response to a voltage + measurement request), it sends it to IC(n-1). IC(n-1) forwards it to IC(n-2) + and so on until IC(0) forwards it to the MCU + +This means that when communicating with the daisy-chain, the MCU does not see a +shift register. +It sees single devices to which it sends messages and which answer. TPL +++ -TPL is the name of the differential communication protocol used by the |nxp775| ICs to communicate in -daisy-chain. A bridge IC called |nxp664| is used to make the translation between SPI and TPL, so that the -MCU only sees SPI communications. The |nxp664| has one important specificity: it uses two SPI interfaces -to communicate with the MCU, one Tx SPI and one Rx SPI. The SPI interfaces are configured as follows: +TPL is the name of the differential communication protocol used by the +|nxp-mc33775a| ICs to communicate in daisy-chain. +A bridge IC called |nxp-mc33664| is used to make the translation between SPI +and TPL, so that the MCU only sees SPI communications. +The |nxp-mc33664| has one important specificity: it uses two SPI interfaces to +communicate with the MCU, one Tx SPI and one Rx SPI. +The SPI interfaces are configured as follows: - - The Tx SPI is used by the MCU as a master to send messages to the daisy-chain - - The Rx SPI is used by the MCU as a slave to receive answers from the daisy-chain +- The Tx SPI is used by the MCU as a master to send messages to the + daisy-chain +- The Rx SPI is used by the MCU as a slave to receive answers from the + daisy-chain Message format -------------- There are 4 types of message: - - WAKE-UP/NOP - - READ register from |nxp775| - - WRITE register to |nxp775| - - RESPONSE of |nxp775| to READ message +- WAKE-UP/NOP +- READ register from |nxp-mc33775a| +- WRITE register to |nxp-mc33775a| +- RESPONSE of |nxp-mc33775a| to READ message -A RESPONSE message is received after a READ command was issued. In TPL mode, there is no response to -WRITE message. +A RESPONSE message is received after a READ command was issued. +In TPL mode, there is no response to WRITE message. The following fields compose messages and are common to all types of messages: - - CMD: command type, chooses one of the four command types described above. - - MADD: indicates upstream of downstream direction of message. Must be set to 0 by the MCU when sending messages - to the daisy-chain. - - CADD: daisy-chain address. Cannot be 0. - - DEVADD: device address. 0 is for enumerated devices. For enumerated devices, the MCU sets this value to - the address of the device it wants to communicate with and in RESPONSE messages, contains the address of the - device that responded. - - MSGCNT: message counter, is incremented for each response message sent by a |nxp775| IC. Is ignored in other - messages. The counter is reset when the device goes to sleep. - - DATLEN: number of register addressed, can be 1 to 4. With one message, up to 4 consecutive register can be - read from or written to. If DATLEN is higher then the length of the provided data, the communication is - discarded. - - REGADD: address of the first addressed register. - -The next fields are related to data and depend on the type of messages. For WRITE and RESPONSE messages, DATA -contains the data to write for WRITE or the data sent by the device for RESPONSE. +- CMD: command type, chooses one of the four command types described above. +- MADD: indicates upstream of downstream direction of message. + Must be set to 0 by the MCU when sending messages to the daisy-chain. +- CADD: daisy-chain address. + Cannot be 0. +- DEVADD: device address. + 0 is for enumerated devices. + For enumerated devices, the MCU sets this value to the address of the device + it wants to communicate with and in RESPONSE messages, contains the address + of the device that responded. +- MSGCNT: message counter, is incremented for each response message sent by a + |nxp-mc33775a| IC. Is ignored in other messages. + The counter is reset when the device goes to sleep. +- DATLEN: number of register addressed, can be 1 to 4. + With one message, up to 4 consecutive register can be read from or written + to. + If DATLEN is higher then the length of the provided data, the communication + is discarded. +- REGADD: address of the first addressed register. + +The next fields are related to data and depend on the type of messages. +For WRITE and RESPONSE messages, DATA contains the data to write for WRITE or +the data sent by the device for RESPONSE. For READ messages: - - PAD: padding. If set to 1, the response message always correspond to a RESPLEN of 4. If RESPLEN < 4 was used, - the remaining values are padded with zeros. - - RESPLEN: number of messages to be transferred in one RESPONSE frame, can be 1 to 4. RESPLEN greater than - number of registers to transfer? - - NUMREG: total number of register requested. If NUMREG is not a multiple of RESPLEN, the device sends in the - last message only the remaining registers. If PAD is set to 0, the length of the last message is adapted. If - PAD is set to 1, the remaining values are padded with zeros. +- PAD: padding. If set to 1, the response message always correspond to a + RESPLEN of 4. If RESPLEN < 4 was used, the remaining values are padded with + zeros. +- RESPLEN: number of messages to be transferred in one RESPONSE frame, can be + 1 to 4. + RESPLEN greater than number of registers to transfer? +- NUMREG: total number of register requested. + If NUMREG is not a multiple of RESPLEN, the device sends in the last message + only the remaining registers. + If PAD is set to 0, the length of the last message is adapted. + If PAD is set to 1, the remaining values are padded with zeros. The last field is the CRC value. Writing values to registers --------------------------- -The WRITE message must be used. In the message, the address of the device, the address of the register and the data -to write must simply be supplied. +The WRITE message must be used. +In the message, the address of the device, the address of the register and the +data to write must simply be supplied. The following data must be written. First the message head: - - 0x10 in CMD - - 0 in MADD - - CADD value - - device address in DEVADD. Care must be taken, the first device in the daisy-chain has the address 1. - - As MSGCNT is not used, it can be set to 0. +- 0x10 in CMD +- 0 in MADD +- CADD value +- device address in DEVADD. + Care must be taken, the first device in the daisy-chain has the address 1. +- As MSGCNT is not used, it can be set to 0. Then the data segment starts, first with the data head: - - Message length in DATLEN. A length of 1 corresponds to 0 for DATLEN. - - Address of first consecutive register in REGADD. +- Message length in DATLEN. + A length of 1 corresponds to 0 for DATLEN. +- Address of first consecutive register in REGADD. Then the data of the data segment: - - Data to write. +- Data to write. Finally the CRC: - - CRC value computed over the whole message. +- CRC value computed over the whole message. In TPL mode, the daisy-chain does not respond to WRITE commands. @@ -202,130 +242,151 @@ Reading values from registers Issuing a read command ++++++++++++++++++++++ -First, a READ command must be used. In the message, the address of the device and the address of the first -consecutive register to read must e supplied. +First, a READ command must be used. In the message, the address of the device +and the address of the first consecutive register to read must e supplied. The following data must be written. First the message head: - - 0x01 in CMD - - 0 in MADD - - CADD value - - device address in DEVADD. Care must be taken, the first device in the daisy-chain has the address 1. - - As MSGCNT is not used, it can be set to 0. +- 0x01 in CMD +- 0 in MADD +- CADD value +- device address in DEVADD. Care must be taken, the first device in the + daisy-chain has the address 1. +- As MSGCNT is not used, it can be set to 0. Then the data segment starts, first with the data head: - - Message length in DATLEN. A length of 1 corresponds to 0 for DATLEN. - - Address of first consecutive register in REGADD. +- Message length in DATLEN. + A length of 1 corresponds to 0 for DATLEN. +- Address of first consecutive register in REGADD. Then the data read configuration part of the data segment: - - Five bits must be written with 0. - - PAD must be set to 0 or 1. - - Response length in RESPLEN. A length of 1 corresponds to 0 in RESPLEN. - - Number of registers to read in NUMREG. +- Five bits must be written with 0. +- PAD must be set to 0 or 1. +- Response length in RESPLEN. A length of 1 corresponds to 0 in RESPLEN. +- Number of registers to read in NUMREG. Finally the CRC: - - CRC value computed over the whole message. +- CRC value computed over the whole message. Response from the daisy-chain +++++++++++++++++++++++++++++ -After a READ message was sent to a device in the daisy-chain, via the Tx SPI, the device answers -via the Rx SPI. - -Different checks in a RESPONSE frame can be made to determine if the READ command was performed -successfully: - - - the length of the received message must be greater than zero. - - the device address in RESPONSE messages must match the device address used in the WRITE message. - - the register address in each received RESPONSE message must correspond to the register address - written in the WRITE command. Care must be taken that one WRITE message can lead to several - RESPONSE messages, so the value of the first register written in the WRITE COMMAND has to be - incremented for each RESPONSE message received. - - the message counter MSGCNT can be checked, it is incremented at each response message. - It is reset when the device goes to sleep. - - If the register address of a RESPONSE frame contains 0x3FFF, this means there was an access error. - - The CMD field in a respond message must be set to 0x11. - -In addition, the ``FEH_COM_FLT_STAT`` register (Communication fault status register, address 0x423) -can be read. It signals communication errors that happened and contains a communication error counter. +After a READ message was sent to a device in the daisy-chain, via the Tx SPI, +the device answers via the Rx SPI. + +Different checks in a RESPONSE frame can be made to determine if the READ +command was performed successfully: + +- the length of the received message must be greater than zero. +- the device address in RESPONSE messages must match the device address used in + the WRITE message. +- the register address in each received RESPONSE message must correspond to the + register address written in the WRITE command. + Care must be taken that one WRITE message can lead to several RESPONSE + messages, so the value of the first register written in the WRITE COMMAND has + to be incremented for each RESPONSE message received. +- the message counter MSGCNT can be checked, it is incremented at each response + message. + It is reset when the device goes to sleep. +- If the register address of a RESPONSE frame contains 0x3FFF, this means there + was an access error. +- The CMD field in a respond message must be set to 0x11. + +In addition, the ``FEH_COM_FLT_STAT`` register (Communication fault status +register, address 0x423) can be read. +It signals communication errors that happened and contains a communication +error counter. Voltage measurement ------------------- -The |nxp775| can measure the following values: +The |nxp-mc33775a| can measure the following values: - - 14 cell voltages - - 4 + 4 voltages on analog inputs that can also be used as GPIOs - - voltage of the battery module - - diagnostic measurements like voltage references and internal IC temperature +- 14 cell voltages +- 4 + 4 voltages on analog inputs that can also be used as GPIOs +- voltage of the battery module +- diagnostic measurements like voltage references and internal IC temperature -The analog inputs can be used to measure temperature by using NTCs in a voltage dividers, supplied -by the output VAUX. +The analog inputs can be used to measure temperature by using NTCs in a voltage +dividers, supplied by the output VAUX. -The |nxp775| has two independent measurements chains, primary and secondary. +The |nxp-mc33775a| has two independent measurements chains, primary and +secondary. Primary can measure: - - the 14 cell voltages - - the 4 first analog inputs (AIN0 to AIN3) - - internal primary IC temperature - - various voltage references, not the same as secondary +- the 14 cell voltages +- the 4 first analog inputs (AIN0 to AIN3) +- internal primary IC temperature +- various voltage references, not the same as secondary Secondary can measure: - - the 14 cell voltages - - the 4 last analog inputs (AIN4 to AIN7) - - internal secondary IC temperature - - various voltage references, not the same as primary +- the 14 cell voltages +- the 4 last analog inputs (AIN4 to AIN7) +- internal secondary IC temperature +- various voltage references, not the same as primary -The first step is to activate measurements. The IC then continuously measures. When one of the 4 modes -described above is started, the measurements are captured. At least 16 measurements are necessary -for the IC to give valid values. +The first step is to activate measurements. +The IC then continuously measures. +When one of the 4 modes described above is started, the measurements are +captured. +At least 16 measurements are necessary for the IC to give valid values. Measurement types +++++++++++++++++ 4 different types of measurement are available: - - synchronous - - application-driven - - periodic - - fast VB +- synchronous +- application-driven +- periodic +- fast VB Synchronous *********** -In this mode, the cell voltages are measured synchronously between primary and secondary. -Only the inputs common to primary and secondary (cell voltages) are taken into account, the other inputs -(analog inputs, module voltage, internal temperature, voltage references) not. +In this mode, the cell voltages are measured synchronously between primary and +secondary. +Only the inputs common to primary and secondary (cell voltages) are taken into +account, the other inputs (analog inputs, module voltage, internal temperature, +voltage references) not. Application-driven ****************** In this mode, the application decides when the capture starts. -The measurements are taken into account after the IC receives a capture command via setting bits in the -appropriate register. All sources can be measured. Results are available as soon as at least 16 measurements -have been taken into account. This is signaled by a bit in the appropriate register. - -A new capture can be initiated when at least 16 values have been taken into account. If more than 65535 -or less than 16 measurements have been captured, the results are set to invalid. +The measurements are taken into account after the IC receives a capture command +via setting bits in the appropriate register. +All sources can be measured. +Results are available as soon as at least 16 measurements have been taken into +account. +This is signaled by a bit in the appropriate register. + +A new capture can be initiated when at least 16 values have been taken into +account. +If more than 65535 or less than 16 measurements have been captured, the results +are set to invalid. Periodic ******** -The number of measurements to use is defined in the appropriate register. Once this mode is started, the results -are available every time the number of measurements captured corresponding to the configured period has been -made. The availability of the results of a period are signaled by a bit in the appropriate register. +The number of measurements to use is defined in the appropriate register. +Once this mode is started, the results are available every time the number of +measurements captured corresponding to the configured period has been made. +The availability of the results of a period are signaled by a bit in the +appropriate register. Fast VB ******* -Measurements are made on the secondary line. The results are available after 24 measurements have been captured. +Measurements are made on the secondary line. +The results are available after 24 measurements have been captured. Measurement possibilities for primary and secondary *************************************************** @@ -356,181 +417,221 @@ secondary and with which method. Procedure to perform voltage measurements ----------------------------------------- -Writing to the ``ALLM`` register is equivalent to writing simultaneously to the corresponding - ``PRMM`` (primary) and ``SECM`` (secondary register). +Writing to the ``ALLM`` register is equivalent to writing simultaneously to the +corresponding ``PRMM`` (primary) and ``SECM`` (secondary register). Measurement unit activation +++++++++++++++++++++++++++ First, the measurement units must be activated: - - Enable cell measurement channels by writing ones to the VCBCxEN fields in the ``ALLM_VCVB_CFG`` register - (address 0x1408). +- Enable cell measurement channels by writing ones to the VCBCxEN fields in + the ``ALLM_VCVB_CFG`` register (address 0x1408). - * ``ALLM_VCVB_CFG`` |larr| ``0x3FFF`` + * ``ALLM_VCVB_CFG`` |larr| ``0x3FFF`` - - Enable AIN0 to AIN 3 and module voltage channels by writing ones to the AINx fields in the ``PRMM_AIN_CFG`` - register (address 0x1809). +- Enable AIN0 to AIN 3 and module voltage channels by writing ones to the AINx + fields in the ``PRMM_AIN_CFG`` register (address 0x1809). - * ``PRMM_AIN_CFG`` |larr| ``0x1F`` + * ``PRMM_AIN_CFG`` |larr| ``0x1F`` - - Enable AIN4 to AIN 7 channels by writing ones to the AINx fields in the ``SECM_AIN_CFG`` register (address 0x1C09). +- Enable AIN4 to AIN 7 channels by writing ones to the AINx fields in the + ``SECM_AIN_CFG`` register (address 0x1C09). - * ``PRMM_AIN_CFG`` |larr| ``0x0F`` + * ``PRMM_AIN_CFG`` |larr| ``0x0F`` - - Enable the measurements units simultaneously by setting bit 0 to 1 in the ``ALLM_CFG`` register (address 0x1400). +- Enable the measurements units simultaneously by setting bit 0 to 1 in the + ``ALLM_CFG`` register (address 0x1400). - * ``ALLM_CFG`` register |larr| ``0x01`` + * ``ALLM_CFG`` register |larr| ``0x01`` -Once the measurement units have been activated, measurement captures can be started. +Once the measurement units have been activated, measurement captures can be +started. Application-driven measurements +++++++++++++++++++++++++++++++ - - Enable capture by setting the bits 0 to 9 corresponding the the different channels (cell inputs, analog inputs, - module voltage) to 1 (corresponding to a value of 0x1FF) in the ``ALLM_APP_CTRL`` register (address 0x1401). - Also write 0x1F to bits 14:10 to disable open load detection for secondary. Writing a number between 0 to 13 - would activate open load detection for the corresponding cell measurement input. +- Enable capture by setting the bits 0 to 9 corresponding the the different + channels (cell inputs, analog inputs, module voltage) to 1 (corresponding to + a value of 0x1FF) in the ``ALLM_APP_CTRL`` register (address 0x1401). + Also write 0x1F to bits 14:10 to disable open load detection for secondary. + Writing a number between 0 to 13 would activate open load detection for the + corresponding cell measurement input. - * ``ALLM_APP_CTRL`` |larr| (``0x1F`` << ``10``) | ``0x3FF`` + * ``ALLM_APP_CTRL`` |larr| (``0x1F`` << ``10``) | ``0x3FF`` - - In the ``PRMM_MEAS_STAT`` register (address 0x183E), the status of the primary measurements can be checked. - If at least 16 measurements have been captured, the corresponding bit for each of the 6 measurement possibilities - is set to 1: +- In the ``PRMM_MEAS_STAT`` register (address 0x183E), the status of the + primary measurements can be checked. + If at least 16 measurements have been captured, the corresponding bit for + each of the 6 measurement possibilities is set to 1: - * cell inputs VC0 to VC13 - bit 0 - * analog inputs AIN0 to AIN3 - bit 1 to bit 4 - * module voltage - bit 5 + * cell inputs VC0 to VC13 - bit 0 + * analog inputs AIN0 to AIN3 - bit 1 to bit 4 + * module voltage - bit 5 - - In the ``PRMM_APP_VC_CNT register`` (address 0x183F), the number of captured values for the cell input measurements - can be read. Starting from address 0x1840, the results of the measurements can be read, with one value per register, - in the following order: +- In the ``PRMM_APP_VC_CNT register`` (address 0x183F), the number of captured + values for the cell input measurements can be read. + Starting from address 0x1840, the results of the measurements can be read, + with one value per register, in the following order: - * cell inputs VC0 to VC13 - * module voltage. - * analog inputs AIN0 to AIN3 + * cell inputs VC0 to VC13 + * module voltage. + * analog inputs AIN0 to AIN3 - - Starting from address 0x1C4F, the results of the secondary measurements can be read, with one value per register, - in the order analog inputs AIN4 to AIN7. +- Starting from address 0x1C4F, the results of the secondary measurements can + be read, with one value per register, in the order analog inputs AIN4 to AIN7. Periodic measurements +++++++++++++++++++++ - - Set the number of measurements used for each period by writing the corresponding value to the ``ALLM_PER_CTRL`` - register (address 0x1402) at bits 0 to 8 (PERLEN). The number must lie between 16 and 511. +- Set the number of measurements used for each period by writing the + corresponding value to the ``ALLM_PER_CTRL`` register (address 0x1402) at + bits 0 to 8 (PERLEN). + The number must lie between 16 and 511. - * ``ALLM_PER_CTRL`` |larr| ``0x10`` for 16 measurements + * ``ALLM_PER_CTRL`` |larr| ``0x10`` for 16 measurements - - In the ``PRMM_MEAS_STAT`` register (address 0x183E), the status of the periodic measurements can be checked. - If new periodic data is ready for readout, bit 8 (PERRDY) is set to 1. +- In the ``PRMM_MEAS_STAT`` register (address 0x183E), the status of the + periodic measurements can be checked. + If new periodic data is ready for readout, bit 8 (PERRDY) is set to 1. - - The number of the cycle in which the results have been created can be read in the ``PRMM_PER_NUM`` register - (address 0x185F). Starting from address 0x1860, the results of the measurements can be read, with one value - per register, in the following order: +- The number of the cycle in which the results have been created can be read in + the ``PRMM_PER_NUM`` register (address 0x185F). + Starting from address 0x1860, the results of the measurements can be read, + with one value per register, in the following order: - * cell inputs VC0 to VC13 - * module voltage. - * analog inputs AIN0 to AIN3 + * cell inputs VC0 to VC13 + * module voltage. + * analog inputs AIN0 to AIN3 - - Starting from address 0x1C6E, the results of the secondary measurements can be read, with one value per register, - in the order analog inputs AIN4 to AIN7. +- Starting from address 0x1C6E, the results of the secondary measurements can + be read, with one value per register, in the order analog inputs AIN4 to AIN7. Synchronous measurements ++++++++++++++++++++++++ - - Enable capture by setting the bit 0 (SYNCCYC) to 1 in the ALLM_SYNC_CTRL register (address 0x1403). - Also write 0x1F to bits 14:10 to disable open load detection for secondary. Writing a number between 0 to 13 - would activate open load detection for the corresponding cell measurement input. +- Enable capture by setting the bit 0 (SYNCCYC) to 1 in the ALLM_SYNC_CTRL + register (address 0x1403). + Also write 0x1F to bits 14:10 to disable open load detection for secondary. + Writing a number between 0 to 13 would activate open load detection for the + corresponding cell measurement input. - * ``ALLM_SYNC_CTRL`` |larr| (``0x1F`` << ``10``) | ``0x01`` + * ``ALLM_SYNC_CTRL`` |larr| (``0x1F`` << ``10``) | ``0x01`` - - In the ``PRMM_MEAS_STAT`` register (address 0x183E), the status of the synchronous measurements can be checked. - If synchronous data is ready for readout, bit 9 (SYNCRDY) is set to 1. +- In the ``PRMM_MEAS_STAT`` register (address 0x183E), the status of the + synchronous measurements can be checked. + If synchronous data is ready for readout, bit 9 (SYNCRDY) is set to 1. - - The number of the cycle in which the results have been created can be read in the ``PRMM_SYNC_NUM`` register - (address 0x187F). Starting from address 0x1880, the results of the measurements can be read, with one value - per register, in the order cell inputs VC0 to VC13 +- The number of the cycle in which the results have been created can be read in + the ``PRMM_SYNC_NUM`` register (address 0x187F). + Starting from address 0x1880, the results of the measurements can be read, + with one value per register, in the order cell inputs VC0 to VC13 Balancing --------- The following figure sums up the different switches for balancing. - .. figure:: img/775a_balancing.png - :alt: Balancing switches - :align: center +.. figure:: img/nxp-mc33775a_balancing.png + :alt: Balancing switches + :align: center - Balancing switches + Balancing switches Balancing can be controlled by different means: - - Global timer: all balancing stops when it reaches 0 - - Channel timer: the corresponding channel stops balancing when the timer reaches 0 - - Global undervoltage: all balancing stops when one cell reaches this value - - Channel undervoltage: the corresponding channel stops balancing when its voltage reaches the limit - - Pre-balancing timer: if set to no zero, balancing only starts when it has reached zero - - PWM: modulates balancing for each channels - - Temperature-controlled balancing: two temperature limits are defined, measured with analog inputs. When the high - limit is reached, all balancing stops. It starts again when the low limit is reached. +- Global timer: all balancing stops when it reaches 0 +- Channel timer: the corresponding channel stops balancing when the timer + reaches 0 +- Global undervoltage: all balancing stops when one cell reaches this value +- Channel undervoltage: the corresponding channel stops balancing when its + voltage reaches the limit +- Pre-balancing timer: if set to no zero, balancing only starts when it has + reached zero +- PWM: modulates balancing for each channels +- Temperature-controlled balancing: two temperature limits are defined, + measured with analog inputs. + When the high limit is reached, all balancing stops. + It starts again when the low limit is reached. There are three prerequisites for balancing to start: - - In the BAL_GLOB_TO_TMR register (address 0x1001), the global timer TOTIME must be set to a non-zero value. - - In the BAL_PRE_TMR register (address 0x1003), the pre-balancing timer must be set to 0 to balance immediately - - In the BAL_GLOB_CFG register (address 0x1000), the global balancing enable flag BALEN must be set to 1. +- In the BAL_GLOB_TO_TMR register (address 0x1001), the global timer TOTIME + must be set to a non-zero value. +- In the BAL_PRE_TMR register (address 0x1003), the pre-balancing timer must be + set to 0 to balance immediately +- In the BAL_GLOB_CFG register (address 0x1000), the global balancing enable + flag BALEN must be set to 1. - * ``BAL_GLOB_TO_TMR`` |larr| ``0xYYYY`` with YYYY>0 and high enough - * Set all individual channels to values high enough - * ``BAL_PRE_TMR`` |larr| ``0x00`` - * ``BAL_GLOB`` |larr| ``0x01`` + * ``BAL_GLOB_TO_TMR`` |larr| ``0xYYYY`` with YYYY>0 and high enough + * Set all individual channels to values high enough + * ``BAL_PRE_TMR`` |larr| ``0x00`` + * ``BAL_GLOB`` |larr| ``0x01`` -Once this is done, setting bits CHEN0-CHEN13 to 1 in the BAL_CH_CFG register (address 0x1002) activates the corresponding -balancing channel. +Once this is done, setting bits CHEN0-CHEN13 to 1 in the BAL_CH_CFG register +(address 0x1002) activates the corresponding balancing channel. I2C --- -The |nxp775| can act as a I2C master, by using GPIO4 and GPIO5 as SCL and SDA. -The I2C configuration is made in the I2C_CFG register (address 0xC00). Bit 0 enables the I2C interface. +The |nxp-mc33775a| can act as a I2C master, by using GPIO4 and GPIO5 as SCL and +SDA. +The I2C configuration is made in the I2C_CFG register (address 0xC00). +Bit 0 enables the I2C interface. Bit 1 select the clock rate (100 or 400 kHz) -Register I2C_DATA0 (address 0xC04) to I2C_DATA6 (address 0xC0A) contains the data transmitted or received, depending -on the form of the transmission. +Register I2C_DATA0 (address 0xC04) to I2C_DATA6 (address 0xC0A) contains the +data transmitted or received, depending on the form of the transmission. -The transmission is started by writing to the I2C_CTRL register (address 0xC01): +The transmission is started by writing to the I2C_CTRL register (address +0xC01): - - bits 3:0 (START) control how many bytes are transmitted after the START condition, including device address - - bit 4 (STOP) determines if a stop condition is sent after the last transmitted bytes - - bits 11:8 (RDAFTER) determines after how many bytes the master switches to read +- bits 3:0 (START) control how many bytes are transmitted after the START + condition, including device address +- bit 4 (STOP) determines if a stop condition is sent after the last + transmitted bytes +- bits 11:8 (RDAFTER) determines after how many bytes the master switches to + read -Data to be sent must be written in the registers I2C_DATA0 to I2C_DATA6 before the transmission starts. -Data received must be read in the registers I2C_DATA0 to I2C_DATA6 after the transmission. +Data to be sent must be written in the registers I2C_DATA0 to I2C_DATA6 before +the transmission starts. +Data received must be read in the registers I2C_DATA0 to I2C_DATA6 after the +transmission. -In the I2C_STAT register (address 0xC02), the status of the transmission can be polled. -Bit 1 (ACTIVE) states that a transmission is ongoing. TO check is the ongoing transmission is finished, the register -must be polled until the value 0 is read for the ACTIVE bit. +In the I2C_STAT register (address 0xC02), the status of the transmission can be +polled. +Bit 1 (ACTIVE) states that a transmission is ongoing. +TO check is the ongoing transmission is finished, the register must be polled +until the value 0 is read for the ACTIVE bit. Three wrapper functions have been added: - - ``N775_I2cRead()`` - - ``N775_I2cWrite()`` - - ``N775_I2cWriteRead()`` - -They are similar to the functions used by the MCU, except that the communication takes place over -the |I2C| bus of the |nxp775|. They take care of writing to and reading from the registers -described above. - -When they are called, they write in the queue ``ftsk_afeToI2cQueue`` that an |I2C| transaction -must take place and the calling task is blocked. It waits for the queue ``ftsk_afeFromI2cQueue`` -to be filled with one element. -For a write operation, the data to write on the bus is written to the queue ``ftsk_afeToI2cQueue``, too. -Elements of the type ``AFE_I2C_QUEUE_s`` are used for the communication with the queue. - -In each measurement cycle of the |nxp775|, the function ``N775_TransmitI2c()`` is called once and reads -the queue ``ftsk_afeToI2cQueue``. If a transaction must take place, it is executed. -The outcome of the transaction (success or fail) is written to the queue ``ftsk_afeFromI2cQueue``. -If data was read, the read data is written to the queue ``ftsk_afeFromI2cQueue``, too. -The calling function is then unblocked. If it does not get feedback in the queue within +- ``N775_I2cRead()`` +- ``N775_I2cWrite()`` +- ``N775_I2cWriteRead()`` + +They are similar to the functions used by the MCU, except that the +communication takes place over the |I2C| bus of the |nxp-mc33775a|. +They take care of writing to and reading from the registers described above. + +When they are called, they write in the queue ``ftsk_afeToI2cQueue`` that an +|I2C| transaction must take place and the calling task is blocked. +It waits for the queue ``ftsk_afeFromI2cQueue`` to be filled with one element. +For a write operation, the data to write on the bus is written to the queue +``ftsk_afeToI2cQueue``, too. +Elements of the type ``AFE_I2C_QUEUE_s`` are used for the communication with +the queue. + +In each measurement cycle of the |nxp-mc33775a|, the function +``N775_TransmitI2c()`` is called once and reads the queue +``ftsk_afeToI2cQueue``. +If a transaction must take place, it is executed. +The outcome of the transaction (success or fail) is written to the queue +``ftsk_afeFromI2cQueue``. +If data was read, the read data is written to the queue +``ftsk_afeFromI2cQueue``, too. +The calling function is then unblocked. +If it does not get feedback in the queue within ``N775_I2C_FINISHED_TIMEOUT_ms``, the transaction is considered to have failed. GPIOs @@ -538,15 +639,17 @@ GPIOs The GPIOs are driven by two configuration registers and two control registers. -The GPIO_CFG0 register (address 0x800) is the first control register. Bits 7:0 (INPEN0 to INPEN7) enable the -inputs for the pins. Bits 15:8 (OUTEN0 to OUTEN7) enable the outputs for the pins. +The GPIO_CFG0 register (address 0x800) is the first control register. +Bits 7:0 (INPEN0 to INPEN7) enable the inputs for the pins. +Bits 15:8 (OUTEN0 to OUTEN7) enable the outputs for the pins. -The GPIO_CFG1 register (address 0x801) is the second control register. Bits 7:0 (ODEN0 to ODEN7) allows enabling the -open-drain for each pin. +The GPIO_CFG1 register (address 0x801) is the second control register. +Bits 7:0 (ODEN0 to ODEN7) allows enabling the open-drain for each pin. -The GPIO_OUT register (address 0x802) is the first control register. Bits 7:0 (OUT0 to OUT7) set the output levels of -the pins. +The GPIO_OUT register (address 0x802) is the first control register. +Bits 7:0 (OUT0 to OUT7) set the output levels of the pins. -The GPIO_IN register (address 0x803) is the second control register. Reading bits 7:0 (IN0 to IN7) gives the level -of the GPIO pins. Reading bits 15:8 (HIGHDET0 to HIGHDET7) indicate if a high level was present on the pin since the -last READ command. +The GPIO_IN register (address 0x803) is the second control register. +Reading bits 7:0 (IN0 to IN7) gives the level of the GPIO pins. +Reading bits 15:8 (HIGHDET0 to HIGHDET7) indicate if a high level was present +on the pin since the last READ command. diff --git a/docs/software/modules/driver/afe/supported-afes.rst b/docs/software/modules/driver/afe/supported-afes.rst index cbed154a..18985518 100644 --- a/docs/software/modules/driver/afe/supported-afes.rst +++ b/docs/software/modules/driver/afe/supported-afes.rst @@ -14,6 +14,7 @@ This is achieved by drivers that follow the :ref:`ANALOG_FRONT_END_API`. :maxdepth: 1 :caption: List of supported AFEs + ./adi/adi_ades1830.rst ./ltc/6804-1.rst ./ltc/6806.rst ./ltc/6811-1.rst diff --git a/docs/software/modules/driver/can/can.rst b/docs/software/modules/driver/can/can.rst index 84b23e4c..3f120fb0 100644 --- a/docs/software/modules/driver/can/can.rst +++ b/docs/software/modules/driver/can/can.rst @@ -12,23 +12,88 @@ Module Files Driver ^^^^^^ -- ``src/app/driver/can/can.c`` (`API <../../../../_static/doxygen/src/html/can_8c.html>`__, `source <../../../../_static/doxygen/src/html/can_8c_source.html>`__) -- ``src/app/driver/can/can.h`` (`API <../../../../_static/doxygen/src/html/can_8h.html>`__, `source <../../../../_static/doxygen/src/html/can_8h_source.html>`__) -- ``src/app/driver/can/cbs/can_helper.c`` (`API <../../../../_static/doxygen/src/html/can__helper_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__helper_8c_source.html>`__) -- ``src/app/driver/can/cbs/can_helper.h`` (`API <../../../../_static/doxygen/src/html/can__helper_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__helper_8h_source.html>`__) -- ``src/app/driver/can/cbs/can_cbs.h`` (`API <../../../../_static/doxygen/src/html/can__cbs_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs_8h_source.html>`__) +- ``src/app/driver/can/can.c`` (`API <../../../../_static/doxygen/src/html/can_8c.html>`__, `source <../../../../_static/doxygen/src/html/can_8c_source.html>`__) +- ``src/app/driver/can/can.h`` (`API <../../../../_static/doxygen/src/html/can_8h.html>`__, `source <../../../../_static/doxygen/src/html/can_8h_source.html>`__) +- ``src/app/driver/can/cbs/can_cbs.h`` (`API <../../../../_static/doxygen/src/html/can__cbs_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs_8h_source.html>`__) +- ``src/app/driver/can/cbs/can_helper.c`` (`API <../../../../_static/doxygen/src/html/can__helper_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__helper_8c_source.html>`__) +- ``src/app/driver/can/cbs/can_helper.h`` (`API <../../../../_static/doxygen/src/html/can__helper_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__helper_8h_source.html>`__) Configuration ^^^^^^^^^^^^^ -- ``src/app/driver/config/can_cfg.c`` (`API <../../../../_static/doxygen/src/html/can__cfg_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cfg_8c_source.html>`__) -- ``src/app/driver/config/can_cfg.h`` (`API <../../../../_static/doxygen/src/html/can__cfg_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cfg_8h_source.html>`__) +- ``src/app/driver/can/cbs/rx/can_cbs_rx.h`` (`API <../../../../_static/doxygen/src/html/can__cbs__rx_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__rx_8h_source.html>`__) +- ``src/app/driver/can/cbs/rx/can_cbs_rx_aerosol-sensor.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__rx__aerosol-sensor_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__rx__aerosol-sensor_8c_source.html>`__) +- ``src/app/driver/can/cbs/rx/can_cbs_rx_bms-state-request.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__rx__bms-state-request_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__rx__bms-state-request_8c_source.html>`__) +- ``src/app/driver/can/cbs/rx/can_cbs_rx_current-sensor.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__rx__current-sensor_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__rx__current-sensor_8c_source.html>`__) +- ``src/app/driver/can/cbs/rx/can_cbs_rx_debug.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__rx__debug_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__rx__debug_8c_source.html>`__) +- ``src/app/driver/can/cbs/rx/can_cbs_rx_imd-info.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__rx__imd-info_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__rx__imd-info_8c_source.html>`__) +- ``src/app/driver/can/cbs/rx/can_cbs_rx_imd-response.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__rx__imd-response_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__rx__imd-response_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx.h`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx_8h_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_bms-state-details.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__bms-state-details_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__bms-state-details_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_bms-state.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__bms-state_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__bms-state_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_cell-temperatures.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__cell-temperatures_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__cell-temperatures_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_cell-voltages.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__cell-voltages_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__cell-voltages_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__crash-dump_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__crash-dump_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.h`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__crash-dump_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__crash-dump_8h_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__debug-response_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__debug-response_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.h`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__debug-response_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__debug-response_8h_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__debug-unsupported-multiplexer-values_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__debug-unsupported-multiplexer-values_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.h`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__debug-unsupported-multiplexer-values_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__debug-unsupported-multiplexer-values_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_imd-request.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__imd-request_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__imd-request_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_pack-limits.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__pack-limits_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__pack-limits_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_pack-minimum-maximum-values.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__pack-minimum-maximum-values_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__pack-minimum-maximum-values_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_pack-state-estimation.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__pack-state-estimation_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__pack-state-estimation_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p0.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__pack-values-p0_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__pack-values-p0_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p1.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__pack-values-p1_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__pack-values-p1_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_string-minimum-maximum-values.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__string-minimum-maximum-values_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__string-minimum-maximum-values_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_string-state-estimation.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__string-state-estimation_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__string-state-estimation_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_string-state.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__string-state_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__string-state_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p0.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__string-values-p0_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__string-values-p0_8c_source.html>`__) +- ``src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p1.c`` (`API <../../../../_static/doxygen/src/html/can__cbs__tx__string-values-p1_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cbs__tx__string-values-p1_8c_source.html>`__) +- ``src/app/driver/config/can_cfg.c`` (`API <../../../../_static/doxygen/src/html/can__cfg_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cfg_8c_source.html>`__) +- ``src/app/driver/config/can_cfg.h`` (`API <../../../../_static/doxygen/src/html/can__cfg_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cfg_8h_source.html>`__) +- ``src/app/driver/config/can_cfg_rx-message-definitions.h`` (`API <../../../../_static/doxygen/src/html/can__cfg__rx-message-definitions_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cfg__rx-message-definitions_8h_source.html>`__) +- ``src/app/driver/config/can_cfg_rx.c`` (`API <../../../../_static/doxygen/src/html/can__cfg__rx_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cfg__rx_8c_source.html>`__) +- ``src/app/driver/config/can_cfg_tx-message-definitions.h`` (`API <../../../../_static/doxygen/src/html/can__cfg__tx-message-definitions_8h.html>`__, `source <../../../../_static/doxygen/src/html/can__cfg__tx-message-definitions_8h_source.html>`__) +- ``src/app/driver/config/can_cfg_tx.c`` (`API <../../../../_static/doxygen/src/html/can__cfg__tx_8c.html>`__, `source <../../../../_static/doxygen/src/html/can__cfg__tx_8c_source.html>`__) Unit Test ^^^^^^^^^ -- ``tests/unit/app/driver/can/test_can.c`` (`API <../../../../_static/doxygen/tests/html/test__can_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can_8c_source.html>`__) -- ``tests/unit/app/driver/config/test_can_cfg.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cfg_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cfg_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_aerosol-sensor.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__rx__aerosol-sensor_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__rx__aerosol-sensor_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_bms-state-request.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__rx__bms-state-request_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__rx__bms-state-request_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_current-sensor.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__rx__current-sensor_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__rx__current-sensor_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_debug.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__rx__debug_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__rx__debug_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-info.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__rx__imd-info_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__rx__imd-info_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-response.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__rx__imd-response_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__rx__imd-response_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/test_can_helper.c`` (`API <../../../../_static/doxygen/tests/html/test__can__helper_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__helper_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/test_can_helper.h`` (`API <../../../../_static/doxygen/tests/html/test__can__helper_8h.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__helper_8h_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state-details.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__bms-state-details_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__bms-state-details_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__bms-state_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__bms-state_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-temperatures.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__cell-temperatures_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__cell-temperatures_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-voltages.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__cell-voltages_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__cell-voltages_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_crash-dump.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__crash-dump_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__crash-dump_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-response.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__debug-response_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__debug-response_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-unsupported-multiplexer-values.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__debug-unsupported-multiplexer-values_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__debug-unsupported-multiplexer-values_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_imd-request.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__imd-request_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__imd-request_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-limits.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-limits_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-limits_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-minimum-maximum-values.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-minimum-maximum-values_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-minimum-maximum-values_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-state-estimation.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-state-estimation_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-state-estimation_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values-p0.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-values-p0_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-values-p0_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values-p1.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-values-p1_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__pack-values-p1_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-minimum-maximum-values.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-minimum-maximum-values_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-minimum-maximum-values_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state-estimation.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-state-estimation_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-state-estimation_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-state_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-state_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values-p0.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-values-p0_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-values-p0_8c_source.html>`__) +- ``tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values-p1.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-values-p1_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cbs__tx__string-values-p1_8c_source.html>`__) +- ``tests/unit/app/driver/can/test_can.c`` (`API <../../../../_static/doxygen/tests/html/test__can_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can_8c_source.html>`__) +- ``tests/unit/app/driver/can/test_can_1.c`` (`API <../../../../_static/doxygen/tests/html/test__can__1_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__1_8c_source.html>`__) +- ``tests/unit/app/driver/can/test_can_2.c`` (`API <../../../../_static/doxygen/tests/html/test__can__2_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__2_8c_source.html>`__) +- ``tests/unit/app/driver/config/test_can_cfg.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cfg_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cfg_8c_source.html>`__) +- ``tests/unit/app/driver/config/test_can_cfg_rx.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cfg__rx_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cfg__rx_8c_source.html>`__) +- ``tests/unit/app/driver/config/test_can_cfg_tx.c`` (`API <../../../../_static/doxygen/tests/html/test__can__cfg__tx_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__cfg__tx_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_can.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__can_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__can_8c_source.html>`__) +- ``tests/unit/support/test_can_mpu_prototype_queue_create_stub.h`` (`API <../../../../_static/doxygen/tests/html/test__can__mpu__prototype__queue__create__stub_8h.html>`__, `source <../../../../_static/doxygen/tests/html/test__can__mpu__prototype__queue__create__stub_8h_source.html>`__) Description ----------- @@ -89,6 +154,12 @@ The message is then sent with the function ``CAN_DataSend()``. The function ``CAN_DataSend()`` can also be used to send a CAN message directly anywhere else in the code. +If all mailboxes on the CAN are full when the message is sent, it cannot be +transmitted. In this case, it will be stored in the queue +``ftsk_canTxUnsentMessagesQueue``. With the next call of the function +``CAN_PeriodicTransmit()``, the unsent messages will be pulled from this queue +and resent with the function ``CAN_DataSend()``. + Messages to receive ^^^^^^^^^^^^^^^^^^^ @@ -101,7 +172,6 @@ The received message parameters are: is received. The data of the CAN message is available within this function. - A receive queue called ``ftsk_canRxQueue`` is used as shown in :ref:`queue-can-receive-code-queue` and :ref:`queue-can-receive-code-vars`. @@ -188,7 +258,6 @@ The missing configuration for this mailbox is also done in function Mailbox 42 is configured to receive all CAN messages with a standard 11-bit identifier. - Callback definition ^^^^^^^^^^^^^^^^^^^ diff --git a/docs/software/modules/driver/can/can_how-to.rst b/docs/software/modules/driver/can/can_how-to.rst index 571608b1..0675f596 100644 --- a/docs/software/modules/driver/can/can_how-to.rst +++ b/docs/software/modules/driver/can/can_how-to.rst @@ -80,7 +80,7 @@ In the symbol file the message is implemented as ``foxBMS_BmsState`` (prefix ``foxBMS`` followed by the message name) with the ID ``0x220``. As the message is transmitted from the point of view of the BMS, the comment in the symbol file must be -``Message containing the foxBMS system state (in:can_cbs_tx_state.c:CANTX_BmsState, fv:tx)``. +``Message containing the foxBMS system state (in:can_cbs_tx_bms-state.c:CANTX_BmsState, fv:tx)``. The new dbc file must be exported. Required Macros @@ -141,7 +141,7 @@ The callback declaration must be done in file The callback definition must be done in the appropriate implementation file, i.e., for the BMS state message in -``src\app\driver\can\cbs\tx\can_cbs_tx_state.c``. +``src\app\driver\can\cbs\tx\can_cbs_tx_bms-state.c``. .. literalinclude:: ./can_how-to_tx.c :language: C @@ -149,7 +149,7 @@ i.e., for the BMS state message in :start-after: example-can-tx-messages-callback-definition-start :end-before: example-can-tx-messages-callback-definition-end :caption: Definition of the callback function in - ``src\app\driver\can\cbs\tx\can_cbs_tx_state.c`` + ``src\app\driver\can\cbs\tx\can_cbs_tx_bms-state.c`` :name: callback-definition Required Variables Adaptations @@ -166,12 +166,11 @@ The message needs to be added the transmitted messages array as follows: ``src/app/driver/config/can_cfg_tx.c`` :name: adding-the-the-new-message-to-the-tx-registry - Verification """""""""""" Run the check scripts to verify that the messages are implemented as described -in this how-to's guidelines. +in this how-to. .. code-block:: console :caption: Verify CAN transmit message definition and callback implementation diff --git a/docs/software/modules/driver/can/can_how-to_tx.c b/docs/software/modules/driver/can/can_how-to_tx.c index a260cbd3..5a3259c0 100644 --- a/docs/software/modules/driver/can/can_how-to_tx.c +++ b/docs/software/modules/driver/can/can_how-to_tx.c @@ -43,8 +43,8 @@ * @file can_how-to_tx.c * @author foxBMS Team * @date 2022-09-12 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SOME_GROUP * @prefix CAN * diff --git a/docs/software/modules/driver/crc/crc.rst b/docs/software/modules/driver/crc/crc.rst index 08809d5b..417378f9 100644 --- a/docs/software/modules/driver/crc/crc.rst +++ b/docs/software/modules/driver/crc/crc.rst @@ -37,9 +37,9 @@ to the MSB. The function ``CRC_CalculateCrc()`` takes three arguments: - - a ``uint64_t *`` pointer where the calculated 64 bit CRC is written - - a ``uint8_t *`` pointer to the data - - the length in bytes of the data +- a ``uint64_t *`` pointer where the calculated 64 bit CRC is written +- a ``uint8_t *`` pointer to the data +- the length in bytes of the data .. warning:: This function is not re-entrant: as it uses hardware registers, it diff --git a/docs/software/modules/driver/fram/fram.rst b/docs/software/modules/driver/fram/fram.rst index d5e6013d..5d62f59a 100644 --- a/docs/software/modules/driver/fram/fram.rst +++ b/docs/software/modules/driver/fram/fram.rst @@ -30,7 +30,7 @@ Description ----------- The FRAM (ferroelectric random access memory) used is the model CY15B102QN. -It is a 2 Mbit logically organized as 256K × 8 bits. +It is a 2 Mbit logically organized as 256K x 8 bits. It is non-volatile, does not need to be supplied to retain its data and can be written a virtually unlimited number of times. The FRAM is driven by an SPI interface. @@ -89,11 +89,11 @@ layout. The read and write functions return one of the following four values: - - ``FRAM_ACCESS_OK``: the write or read access was successful and - the CRC read matches with the CRC calculated on the read data. - - ``FRAM_ACCESS_SPI_BUSY``: the SPI is busy, the transaction could not - take place. - - ``FRAM_ACCESS_CRC_BUSY``: the CRC hardware is busy, the transaction - could not take place. - - ``FRAM_ACCESS_CRC_ERROR``: the data was read from the FRAM but the read - CRC does not match with the CRC computed on the read data. +- ``FRAM_ACCESS_OK``: the write or read access was successful and + the CRC read matches with the CRC calculated on the read data. +- ``FRAM_ACCESS_SPI_BUSY``: the SPI is busy, the transaction could not + take place. +- ``FRAM_ACCESS_CRC_BUSY``: the CRC hardware is busy, the transaction + could not take place. +- ``FRAM_ACCESS_CRC_ERROR``: the data was read from the FRAM but the read + CRC does not match with the CRC computed on the read data. diff --git a/docs/software/modules/driver/imd/bender/bender_ir155.rst b/docs/software/modules/driver/imd/bender/bender_ir155.rst index 9917f8d1..86cb4dfd 100644 --- a/docs/software/modules/driver/imd/bender/bender_ir155.rst +++ b/docs/software/modules/driver/imd/bender/bender_ir155.rst @@ -28,7 +28,6 @@ Unit Test - ``tests/unit/app/driver/imd/bender/ir155/test_bender_ir155.c`` (`API <../../../../../_static/doxygen/tests/html/test__bender__ir155_8c.html>`__, `source <../../../../../_static/doxygen/tests/html/test__bender__ir155_8c_source.html>`__) - ``tests/unit/app/driver/imd/bender/ir155/test_bender_helper_ir155.c`` (`API <../../../../../_static/doxygen/tests/html/test__bender__ir155__helper_8c.html>`__, `source <../../../../../_static/doxygen/tests/html/test__bender__ir155__helper_8c_source.html>`__) - Description of the IMD state machine ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/software/modules/driver/imd/bender/bender_iso165c.rst b/docs/software/modules/driver/imd/bender/bender_iso165c.rst index 86734329..6319a51d 100644 --- a/docs/software/modules/driver/imd/bender/bender_iso165c.rst +++ b/docs/software/modules/driver/imd/bender/bender_iso165c.rst @@ -83,7 +83,6 @@ The disabling process is implemented in function `I165C_Disable`. Insulation measurement """""""""""""""""""""" - The state flow diagram of the periodic insulation measurement procedure of the Bender iso165C state machine is depicted below. diff --git a/docs/software/modules/driver/imd/imd.rst b/docs/software/modules/driver/imd/imd.rst index 172efb77..3734d698 100644 --- a/docs/software/modules/driver/imd/imd.rst +++ b/docs/software/modules/driver/imd/imd.rst @@ -16,7 +16,6 @@ Several different Insulation Measurement Devices (IMD) are supported. ./bender/bender_iso165c.rst ./none/no-imd.rst - A superimposed state machine is implemented that interacts with the actual IMD implementation. There a different reasons for the state machine to transition between the states. Generally three cases can happen: @@ -78,7 +77,6 @@ This can be necessary to prevent a mutual interference if multiple insulation monitoring devices would be monitoring the battery system, e.g., when a vehicle is connected to a charging station. - Description of the IMD state machine ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -156,7 +154,6 @@ Interfaces for IMD driver implementation The following functions are used to interface the actual IMD implementation: - .. literalinclude:: ./../../../../../src/app/driver/imd/imd.h :language: C :linenos: diff --git a/docs/software/modules/driver/interlock/interlock.rst b/docs/software/modules/driver/interlock/interlock.rst index 9f7d0d3c..a1dbb64b 100644 --- a/docs/software/modules/driver/interlock/interlock.rst +++ b/docs/software/modules/driver/interlock/interlock.rst @@ -18,7 +18,6 @@ Driver Configuration ^^^^^^^^^^^^^ -- ``src/app/driver/config/interlock_cfg.c`` (`API <../../../../_static/doxygen/src/html/interlock__cfg_8c.html>`__, `source <../../../../_static/doxygen/src/html/interlock__cfg_8c_source.html>`__) - ``src/app/driver/config/interlock_cfg.h`` (`API <../../../../_static/doxygen/src/html/interlock__cfg_8h.html>`__, `source <../../../../_static/doxygen/src/html/interlock__cfg_8h_source.html>`__) Unit Test diff --git a/docs/software/modules/driver/rtc/rtc.rst b/docs/software/modules/driver/rtc/rtc.rst index d5ff00e7..74e63c6c 100644 --- a/docs/software/modules/driver/rtc/rtc.rst +++ b/docs/software/modules/driver/rtc/rtc.rst @@ -37,8 +37,8 @@ To avoid reading the RTC IC frequently, an RTC system timer is defined in ``rtc.c`` with the name ``rtc_SystemTime``. It has the format ``RTC_SYSTEM_TIMER_EPOCH_s``. This struct has two elements: - - the time in Unix format, which means seconds since January 1st 1970 - - an additional field with milliseconds +- the time in Unix format, which means seconds since January 1st 1970 +- an additional field with milliseconds The function ``RTC_IncrementSystemTime()`` is used to increment the RTC system timer. diff --git a/docs/software/modules/driver/sbc/sbc.rst b/docs/software/modules/driver/sbc/sbc.rst index d5d35409..3376c91e 100644 --- a/docs/software/modules/driver/sbc/sbc.rst +++ b/docs/software/modules/driver/sbc/sbc.rst @@ -19,7 +19,6 @@ Vendor Driver parameter into the functions to enable the usage of multiple ICs in the system. - - ``src/app/driver/sbc/fs8x_driver/sbc_fs8x_assert.h`` (`API <../../../../_static/doxygen/src/html/sbc__fs8x__assert_8h.html>`__, `source <../../../../_static/doxygen/src/html/sbc__fs8x__assert_8h_source.html>`__) - ``src/app/driver/sbc/fs8x_driver/sbc_fs8x_common.h`` (`API <../../../../_static/doxygen/src/html/sbc__fs8x__common_8h.html>`__, `source <../../../../_static/doxygen/src/html/sbc__fs8x__common_8h_source.html>`__) - ``src/app/driver/sbc/fs8x_driver/sbc_fs8x_communication.c`` (`API <../../../../_static/doxygen/src/html/sbc__fs8x__communication_8c.html>`__, `source <../../../../_static/doxygen/src/html/sbc__fs8x__communication_8c_source.html>`__) @@ -39,17 +38,28 @@ Driver Configuration ^^^^^^^^^^^^^ -- ``src/app/driver/config/nxpfs85xx_cfg.c`` (`API <../../../../_static/doxygen/src/html/nxpfs85xx__cfg_8c.html>`__, `source <../../../../_static/doxygen/src/html/nxpfs85xx__cfg_8c_source.html>`__) - ``src/app/driver/config/nxpfs85xx_cfg.h`` (`API <../../../../_static/doxygen/src/html/nxpfs85xx__cfg_8h.html>`__, `source <../../../../_static/doxygen/src/html/nxpfs85xx__cfg_8h_source.html>`__) Unit Test ^^^^^^^^^ -- ``tests/unit/app/driver/config/test_nxpfs85xx_cfg.c`` (`API <../../../../_static/doxygen/tests/html/test__nxpfs85xx__cfg_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__nxpfs85xx__cfg_8c_source.html>`__) - ``tests/unit/app/driver/sbc/test_sbc.c`` (`API <../../../../_static/doxygen/tests/html/test__sbc_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__sbc_8c_source.html>`__) - ``tests/unit/app/driver/sbc/test_nxpfs85xx.c`` (`API <../../../../_static/doxygen/tests/html/test__nxpfs85xx_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__nxpfs85xx_8c_source.html>`__) Description ----------- -|tbc| +As long as the Ignition signal is present, the SBC is operating normally in +Running mode. +If the Ignition signal is removed, the MCU will request to send the SBC to +Standby mode. +If no Ignition signal is present in Standby mode, the SBC will power down and +also stop powering the MCU, which will then also shut down. +When the Ignition signal is detected again at the SBC, it will start up and +power the MCU. The MCU will then initialize the SBC, which will return to +normal operation in Running mode after the initialization is complete. +This sequence is shown in :numref:`sbc_state_machine_wakeup`. + +.. graphviz:: sbc_state_machine_wakeup.dot + :caption: SBC wakeup state chart + :name: sbc_state_machine_wakeup diff --git a/docs/software/modules/driver/sbc/sbc_state_machine_wakeup.dot b/docs/software/modules/driver/sbc/sbc_state_machine_wakeup.dot new file mode 100644 index 00000000..183be900 --- /dev/null +++ b/docs/software/modules/driver/sbc/sbc_state_machine_wakeup.dot @@ -0,0 +1,61 @@ +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +digraph sbc_wakeup_states { + rankdir=LR; + + node [shape = doublecircle] sbc_running + sbc_power_down; + + node [shape = circle] sbc_standby + sbc_initialize + ; + + sbc_running [label=<Running>]; + sbc_standby [label=<Standby>]; + sbc_power_down [label=<Power Down>]; + sbc_initialize [label=<Initialize>]; + + sbc_running -> sbc_running [label = "Ignition = 1"] + sbc_running -> sbc_standby [label = "Ignition = 0"] + sbc_standby -> sbc_running [label = "Ignition = 1"] + sbc_standby -> sbc_power_down [label = "Ignition = 0"] + sbc_power_down -> sbc_initialize [label = "Ignition = 1"] + sbc_power_down -> sbc_power_down [label = "Ignition = 0"] + sbc_initialize -> sbc_running + ; +} diff --git a/docs/software/modules/driver/ts/adding-a-new-ts_how-to.rst b/docs/software/modules/driver/ts/adding-a-new-ts_how-to.rst index 495146a8..c98c1a8a 100644 --- a/docs/software/modules/driver/ts/adding-a-new-ts_how-to.rst +++ b/docs/software/modules/driver/ts/adding-a-new-ts_how-to.rst @@ -120,8 +120,8 @@ the main build system, special care has to be taken that the correct source files are attracted. This mainly applies to the implementations of the lookup-table and polynomial function as they do not have a separate header file. -Use ``TEST_FILE("good-sensor_temp123_polynomial.c")`` in the test file in order -to hint the correct source file to the unit test build system. +Use ``TEST_SOURCE_FILE("good-sensor_temp123_polynomial.c")`` in the test file +in order to hint the correct source file to the unit test build system. Updating the IDE configuration ------------------------------ diff --git a/docs/software/modules/driver/ts/murata/ncu15xh103f6sxx.rst b/docs/software/modules/driver/ts/murata/ncxxxxh103.rst similarity index 71% rename from docs/software/modules/driver/ts/murata/ncu15xh103f6sxx.rst rename to docs/software/modules/driver/ts/murata/ncxxxxh103.rst index 418cd736..1a5a7d86 100644 --- a/docs/software/modules/driver/ts/murata/ncu15xh103f6sxx.rst +++ b/docs/software/modules/driver/ts/murata/ncxxxxh103.rst @@ -8,9 +8,9 @@ .. spelling:: Murata -.. _MURATA_NCU15XH103F6SXX: +.. _MURATA_NCXXXXH103: -MURATA NCU15XH103F6SXX -====================== +MURATA NCXXXXH103 +================= |tbc| diff --git a/docs/software/modules/driver/ts/ts-sensors.rst b/docs/software/modules/driver/ts/ts-sensors.rst index 36576c07..bf5e9ad2 100644 --- a/docs/software/modules/driver/ts/ts-sensors.rst +++ b/docs/software/modules/driver/ts/ts-sensors.rst @@ -32,9 +32,10 @@ implement the :ref:`temperature_sensor_api`. ./epcos/b57251v5103j060.rst ./epcos/b57861s0103f045.rst ./fake/none.rst - ./murata/ncu15xh103f6sxx.rst + ./murata/ncxxxxh103.rst ./vishay/ntcalug01a103g.rst ./vishay/ntcle317e4103sba.rst + ./vishay/ntcle413e2103f102l.rst These temperature sensors have *short name* in order to be able to write shorter function and variable names. The *short names* are list in diff --git a/docs/software/modules/driver/ts/ts-short-names.csv b/docs/software/modules/driver/ts/ts-short-names.csv index 90f74dec..b95178a7 100644 --- a/docs/software/modules/driver/ts/ts-short-names.csv +++ b/docs/software/modules/driver/ts/ts-short-names.csv @@ -2,6 +2,7 @@ Manufacturer;Model;*Short Name* Epcos;B57251V5103J060;Epc00 Epcos;B57861S0103F045;Epc01 Fake;none;Fak00 -Murata;NCU15XH103F6XXS;Mur00 +Murata;NCXXXXH103;Mur00 Vishay;NTCALUG01A103G;Vis00 Vishay;NTCLE317E4103SBA;Vis01 +Vishay;NTCLE413E2103F102L;Vis02 diff --git a/docs/software/modules/driver/ts/vishay/ntcle413e2103f102l.rst b/docs/software/modules/driver/ts/vishay/ntcle413e2103f102l.rst new file mode 100644 index 00000000..5480901c --- /dev/null +++ b/docs/software/modules/driver/ts/vishay/ntcle413e2103f102l.rst @@ -0,0 +1,20 @@ +.. include:: ./../../../../../macros.txt +.. include:: ./../../../../../units.txt + +.. + Comments: + Vishay is the name of the sensor manufacturer + +.. spelling:: + Vishay + +.. _VISHAY_NTCLE413E2103F102L: + +Vishay NTCLE413E2103F102L +========================= + +The Vishay NTCLE413E2103F102L is a NTC thermistor. +The sensor features long leads making it suitable for battery system +applications. +More details can be found in the data sheet: +`NTCLE413E2103F102L.pdf `_. diff --git a/docs/software/modules/engine/database/database.rst b/docs/software/modules/engine/database/database.rst index 20d7ddcb..bf206333 100644 --- a/docs/software/modules/engine/database/database.rst +++ b/docs/software/modules/engine/database/database.rst @@ -27,7 +27,6 @@ Unit Test - ``tests/unit/app/engine/config/test_database_cfg.c`` - ``tests/unit/app/engine/database/test_database.c`` - Detailed Description -------------------- diff --git a/docs/software/modules/engine/database/database_how-to.c b/docs/software/modules/engine/database/database_how-to.c index 7b359b7e..7a22a35f 100644 --- a/docs/software/modules/engine/database/database_how-to.c +++ b/docs/software/modules/engine/database/database_how-to.c @@ -43,8 +43,8 @@ * @file database_how-to.c * @author foxBMS Team * @date 2021-04-12 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SOME_GROUP * @prefix DATA * diff --git a/docs/software/modules/engine/database/database_how-to.rst b/docs/software/modules/engine/database/database_how-to.rst index 5aa6b612..59efb78e 100644 --- a/docs/software/modules/engine/database/database_how-to.rst +++ b/docs/software/modules/engine/database/database_how-to.rst @@ -8,7 +8,6 @@ How to Use the Database Module This How-to shows how to add new entries to the database, and how to read and write database entries. - How to Add a Database Entry? ---------------------------- @@ -39,7 +38,6 @@ gives ``DATA_BLOCK_ID_EXAMPLE``. :caption: Adding a new element **example** to the ``DATA_BLOCK_ID_e`` enum :name: adding-a-new-element-to-the-data-block-id-e-enum - Second, a struct definition of the database entry has to be added in file ``src/app/engine/config/database_cfg.h``. This structure needs to contain a variable ``header`` of type ``DATA_BLOCK_HEADER_s`` at the beginning of the struct. This @@ -67,7 +65,6 @@ the ``_s`` suffix as the typedef is a struct, which gives ``DATA_BLOCK_EXAMPLE_s :caption: Creating a new database struct :name: creating-a-new-database-struct - The database checker basically checks that if a database struct is found (something matching ``DATA_BLOCK_(A_Z_0-9)_s``) that it is initialized with a corresponding ID name. @@ -81,7 +78,6 @@ Examples: | DATA_BLOCK\_\ **CELL_VOLTAGE**\ \_s | DATA_BLOCK_ID\_\ **CELL_VOLTAGE** | +---------------------------------------+-----------------------------------+ - Third, in ``src/app/engine/config/database_cfg.c``, a static variable with the structure type must be declared. In this declaration the ``uniqueId`` of the database header must be initialized with the identification number added in the @@ -96,7 +92,6 @@ this database entry during once the BMS is running. :caption: Initialization of the static variable inside the database module :name: initialization-of-the-static-variable-inside-the-database-module - Last, this declared struct must be linked to the actual database implementation by adding an additional entry to the structure ``DATA_BASE_s data_database[]`` in file ``src/app/engine/config/database_cfg.c`` @@ -109,7 +104,6 @@ in file ``src/app/engine/config/database_cfg.c`` :caption: Adding the struct to the database :name: adding-the-struct-to-the-database - How to Read a Database Entry? ----------------------------- @@ -130,7 +124,6 @@ the local database entry structure. :name: reading-a-database-entry :emphasize-lines: 4 - Up to four database entries can be accessed on the same time with one call of ``DATA_READ_DATA()``. @@ -164,7 +157,6 @@ be written with one call of ``DATA_WRITE_DATA()``. :name: writing-a-database-entry :emphasize-lines: 6 - After a call of ``DATA_WRITE_DATA`` the timestamp variables in the database entry header are automatically updated database entry **AND** the local database entry structure. @@ -181,7 +173,6 @@ Up to four database entries can be written on the same time with one call of :name: writing-multiple-database-entries :emphasize-lines: 11, 12 - Further Reading --------------- diff --git a/docs/software/modules/engine/diag/diag.rst b/docs/software/modules/engine/diag/diag.rst index ef711714..66e83d16 100644 --- a/docs/software/modules/engine/diag/diag.rst +++ b/docs/software/modules/engine/diag/diag.rst @@ -18,42 +18,44 @@ Driver Configuration ^^^^^^^^^^^^^ -- ``src/app/engine/config/diag_cfg.c`` (`API <../../../../_static/doxygen/src/html/diag__cfg_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cfg_8c_source.html>`__) -- ``src/app/engine/config/diag_cfg.h`` (`API <../../../../_static/doxygen/src/html/diag__cfg_8h.html>`__, `source <../../../../_static/doxygen/src/html/diag__cfg_8h_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_can.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__can_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__can_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_contactor.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__contactor_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__contactor_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_current.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__current_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__current_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_current-sensor.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__current-sensor_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__current-sensor_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_deep-discharge.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__deep-discharge_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__deep-discharge_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_dummy.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__dummy_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__dummy_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_interlock.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__interlock_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__interlock_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_afe.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__afe_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__afe_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_plausibility.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__plausibility_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__plausibility_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_power-measurement.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__power-measurement_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__power-measurement_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_sbc.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__sbc_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__sbc_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_sys-mon.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__sys-mon_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__sys-mon_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_temperature.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__temperature_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__temperature_8c_source.html>`__) -- ``src/app/engine/diag/cbs/diag_cbs_voltage.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__voltage_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__voltage_8c_source.html>`__) +- ``src/app/engine/config/diag_cfg.c`` (`API <../../../../_static/doxygen/src/html/diag__cfg_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cfg_8c_source.html>`__) +- ``src/app/engine/config/diag_cfg.h`` (`API <../../../../_static/doxygen/src/html/diag__cfg_8h.html>`__, `source <../../../../_static/doxygen/src/html/diag__cfg_8h_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_can.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__can_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__can_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_contactor.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__contactor_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__contactor_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_current.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__current_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__current_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_current-sensor.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__current-sensor_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__current-sensor_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_deep-discharge.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__deep-discharge_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__deep-discharge_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_dummy.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__dummy_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__dummy_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_interlock.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__interlock_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__interlock_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_afe.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__afe_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__afe_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_plausibility.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__plausibility_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__plausibility_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_power-measurement.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__power-measurement_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__power-measurement_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_sbc.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__sbc_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__sbc_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_sys-mon.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__sys-mon_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__sys-mon_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_temperature.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__temperature_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__temperature_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_voltage.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__voltage_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__voltage_8c_source.html>`__) +- ``src/app/engine/diag/cbs/diag_cbs_aerosol-sensor.c`` (`API <../../../../_static/doxygen/src/html/diag__cbs__aerosol-sensor_8c.html>`__, `source <../../../../_static/doxygen/src/html/diag__cbs__aerosol-sensor_8c_source.html>`__) Unit Test ^^^^^^^^^ -- ``tests/unit/app/engine/config/test_diag_cfg.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cfg_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cfg_8c_source.html>`__) -- ``tests/unit/app/engine/diag/test_diag.c`` (`API <../../../../_static/doxygen/tests/html/test__diag_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_can.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__can_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__can_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_contactor.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__contactor_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__contactor_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_current.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__current_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__current_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_current-sensor.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__current-sensor_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__current-sensor_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_deep-discharge.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__deep-discharge_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__deep-discharge_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_dummy.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__dummy_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__dummy_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_interlock.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__interlock_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__interlock_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_afe.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__afe_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__afe_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_plausibility.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__plausibility_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__plausibility_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_power-measurement.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__power-measurement_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__power-measurement_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_sbc.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__sbc_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__sbc_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_sys-mon.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__sys-mon_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__sys-mon_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_temperature.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__temperature_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__temperature_8c_source.html>`__) -- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_voltage.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__voltage_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__voltage_8c_source.html>`__) +- ``tests/unit/app/engine/config/test_diag_cfg.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cfg_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cfg_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_aerosol-sensor.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__aerosol-sensor_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__aerosol-sensor_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_afe.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__afe_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__afe_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_can.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__can_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__can_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_contactor.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__contactor_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__contactor_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_current.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__current_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__current_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_current-sensor.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__current-sensor_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__current-sensor_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_deep-discharge.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__deep-discharge_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__deep-discharge_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_dummy.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__dummy_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__dummy_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_interlock.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__interlock_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__interlock_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_plausibility.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__plausibility_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__plausibility_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_power-measurement.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__power-measurement_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__power-measurement_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_sbc.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__sbc_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__sbc_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_sys-mon.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__sys-mon_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__sys-mon_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_temperature.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__temperature_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__temperature_8c_source.html>`__) +- ``tests/unit/app/engine/diag/cbs/test_diag_cbs_voltage.c`` (`API <../../../../_static/doxygen/tests/html/test__diag__cbs__voltage_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag__cbs__voltage_8c_source.html>`__) +- ``tests/unit/app/engine/diag/test_diag.c`` (`API <../../../../_static/doxygen/tests/html/test__diag_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__diag_8c_source.html>`__) Detailed Description -------------------- diff --git a/docs/software/modules/engine/hw_info/hw_info.rst b/docs/software/modules/engine/hw_info/hw_info.rst new file mode 100644 index 00000000..b3215c70 --- /dev/null +++ b/docs/software/modules/engine/hw_info/hw_info.rst @@ -0,0 +1,31 @@ +.. include:: ../../../../macros.txt +.. include:: ../../../../units.txt + +.. _HARDWARE_INFO_MODULE: + +Hardware Info Module +==================== + +Module Files +------------ + +Driver +^^^^^^ + +- ``src/app/engine/hw_info/master_info.c`` (`API <../../../../_static/doxygen/src/html/master__info_8c.html>`__, `source <../../../../_static/doxygen/src/html/master__info_8c_source.html>`__) +- ``src/app/engine/hw_info/master_info.h`` (`API <../../../../_static/doxygen/src/html/master__info_8h.html>`__, `source <../../../../_static/doxygen/src/html/master__info_8h_source.html>`__) + +Configuration +^^^^^^^^^^^^^ + +*none* + +Unit Test +^^^^^^^^^ + +- ``tests/unit/app/engine/hw_info/test_master_info.c`` (`API <../../../../_static/doxygen/tests/html/test__master_info_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__master__info_8c_source.html>`__) + +Detailed Description +-------------------- + +|tbc| diff --git a/docs/software/modules/engine/hwinfo/hwinfo.rst b/docs/software/modules/engine/hwinfo/hwinfo.rst deleted file mode 100644 index b25afae7..00000000 --- a/docs/software/modules/engine/hwinfo/hwinfo.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. include:: ../../../../macros.txt -.. include:: ../../../../units.txt - -.. _HARDWARE_INFO_MODULE: - -Hardware Info Module -==================== - -Module Files ------------- - -Driver -^^^^^^ - -- ``src/app/engine/hwinfo/masterinfo.c`` (`API <../../../../_static/doxygen/src/html/masterinfo_8c.html>`__, `source <../../../../_static/doxygen/src/html/masterinfo_8c_source.html>`__) -- ``src/app/engine/hwinfo/masterinfo.h`` (`API <../../../../_static/doxygen/src/html/masterinfo_8h.html>`__, `source <../../../../_static/doxygen/src/html/masterinfo_8h_source.html>`__) - -Configuration -^^^^^^^^^^^^^ - -*none* - -Unit Test -^^^^^^^^^ - -- ``tests/unit/app/engine/hwinfo/test_masterinfo.c`` (`API <../../../../_static/doxygen/tests/html/test__masterinfo_8c.html>`__, `source <../../../../_static/doxygen/tests/html/test__masterinfo_8c_source.html>`__) - -Detailed Description --------------------- - -|tbc| diff --git a/docs/software/modules/main/fassert_how-to.rst b/docs/software/modules/main/fassert_how-to.rst index 82f72580..87759bf5 100644 --- a/docs/software/modules/main/fassert_how-to.rst +++ b/docs/software/modules/main/fassert_how-to.rst @@ -24,12 +24,11 @@ Generally, defines should be used as less as possible. :caption: Using #error directives :name: error-directive - #define NUMBER_OF_XYZ 3 - #if (NUMBER_OF_XYZ > 2) + #define NUMBER_OF_ABC 3 + #if (NUMBER_OF_ABC > 2) #error "Configurations with more than 2 XYZ are not supported" #endif - The downside of using the error-directive is that the C-preprocessor runs before any compilation is done. Therefore it is impossible to e.g., check size requirements of variables. @@ -52,7 +51,6 @@ a variable is not zero. FAS_STATIC_ASSERT((db_variable != 0), "database may not be zero"); /* This assertion will not compile if db_variable has size zero. */ - assertions ---------- diff --git a/docs/software/modules/modules.rst b/docs/software/modules/modules.rst index 493730c8..c6b4b4b2 100644 --- a/docs/software/modules/modules.rst +++ b/docs/software/modules/modules.rst @@ -23,7 +23,7 @@ Software Modules ./engine/database/database.rst ./engine/diag/diag.rst - ./engine/hwinfo/hwinfo.rst + ./engine/hw_info/hw_info.rst ./engine/sys/sys.rst ./engine/sys_mon/sys_mon.rst diff --git a/docs/software/modules/task/ftask/ftask.rst b/docs/software/modules/task/ftask/ftask.rst index 7587f6c1..be70c9e4 100644 --- a/docs/software/modules/task/ftask/ftask.rst +++ b/docs/software/modules/task/ftask/ftask.rst @@ -64,7 +64,6 @@ modified (see :numref:`ftask_special_task_idle`). The following sections show how tasks are created, configured and how task behavior can be changed. Code sections that are not meant to be modified by user are indicated in the code, e.g., for the Engine task: - .. code-block:: c :linenos: :emphasize-lines: 2-3,6-7 @@ -106,7 +105,6 @@ Engine task: Before and after the the User Code Function is run, the :ref:`SYSTEM_MONITORING_MODULE` is notified that either the User Code Function will be run or has run. This enables to determine if a task returns within the expected time frame. - .. code-block:: c :linenos: :emphasize-lines: 3,6,7,11 @@ -153,7 +151,6 @@ user/application code (``FTSK_InitializeUserCodePreCyclicTasks``). All tasks share the suffix ``FTSK_RunUserCode`` for a consistent implementation of the Task Creator Functions and are not meant to be changed. - FTSK_InitializeUserCodeEngine """"""""""""""""""""""""""""" @@ -170,7 +167,6 @@ FTSK_RunUserCodeEngine This task triggers the database and the system monitoring modules. The database module copies all data from the queue into the database variables. The system monitoring checks that all tasks run within their specified time frames. - .. _ftask_special_task_idle: FTSK_RunUserCodeIdle diff --git a/docs/software/modules/task/ftask/ftask_how-to.c b/docs/software/modules/task/ftask/ftask_how-to.c index 1f5d83ec..04e47a3a 100644 --- a/docs/software/modules/task/ftask/ftask_how-to.c +++ b/docs/software/modules/task/ftask/ftask_how-to.c @@ -43,8 +43,8 @@ * @file ftask_how-to.c * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SOME_GROUP * @prefix FTSK * diff --git a/docs/software/overview/sw-overview.rst b/docs/software/overview/sw-overview.rst index 00a54980..be40bde8 100644 --- a/docs/software/overview/sw-overview.rst +++ b/docs/software/overview/sw-overview.rst @@ -96,8 +96,8 @@ database. The two key modules used are: - - ``SYS`` - - ``BMS`` +- ``SYS`` +- ``BMS`` ``SYS`` has a lower priority than the database and a higher priority than ``BMS``. Both modules are implemented as a state machine, with a trigger diff --git a/docs/software/unit-tests/abc.c b/docs/software/unit-tests/abc.c index ac5a3869..7e5ce901 100644 --- a/docs/software/unit-tests/abc.c +++ b/docs/software/unit-tests/abc.c @@ -43,8 +43,8 @@ * @file abc.c * @author foxBMS Team * @date 2022-12-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SOME_GROUP * @prefix ABC * diff --git a/docs/software/unit-tests/abc.h b/docs/software/unit-tests/abc.h index 05bf389e..c12ad679 100644 --- a/docs/software/unit-tests/abc.h +++ b/docs/software/unit-tests/abc.h @@ -43,8 +43,8 @@ * @file abc.h * @author foxBMS Team * @date 2022-12-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SOME_GROUP * @prefix ABC * diff --git a/docs/software/unit-tests/run_abc.c b/docs/software/unit-tests/run_abc.c index f63db2e4..571249da 100644 --- a/docs/software/unit-tests/run_abc.c +++ b/docs/software/unit-tests/run_abc.c @@ -43,8 +43,8 @@ * @file run_abc.c * @author foxBMS Team * @date 2022-12-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SOME_GROUP * @prefix ABC * diff --git a/docs/software/unit-tests/test_abc.c b/docs/software/unit-tests/test_abc.c index f2cd0baa..e1fe5e7b 100644 --- a/docs/software/unit-tests/test_abc.c +++ b/docs/software/unit-tests/test_abc.c @@ -43,8 +43,8 @@ * @file test_abc.c * @author foxBMS Team * @date 2022-12-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -55,6 +55,8 @@ /*========== Includes =======================================================*/ #include "abc.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/docs/software/unit-tests/unit-tests.rst b/docs/software/unit-tests/unit-tests.rst index 9a0bdcc5..03bb9e90 100644 --- a/docs/software/unit-tests/unit-tests.rst +++ b/docs/software/unit-tests/unit-tests.rst @@ -24,9 +24,9 @@ target. Usage ----- -The tool is encapsulated in our waf-script. +The tool is encapsulated in our Waf tool. Additionally it is automatically executed on our CI-jobs. -The usage as a waf-tool is explained in +The usage as a Waf tool is explained in :ref:`How to Use Unit tests `. This part also explains how to use the tool directly in a shell. The benefit is that the output in the shell is colored and single tests can be @@ -498,7 +498,6 @@ For both tests the mock is told what it will receive and what it should return. Variants of these mock-functions exist that allow to ignore calls to this function, or to add a callback for more complex return values. - Further reading --------------- diff --git a/docs/software/unit-tests/unit-tests_how-to.rst b/docs/software/unit-tests/unit-tests_how-to.rst index 40386fc3..ee3edbad 100644 --- a/docs/software/unit-tests/unit-tests_how-to.rst +++ b/docs/software/unit-tests/unit-tests_how-to.rst @@ -3,10 +3,17 @@ .. _HOW_TO_USE_UNIT_TESTS: -How to use unit tests +How to use Unit Tests ===================== -Verify that the unit testing framework is work is working as expected: +.. spelling:: + Ootpa + gcc + el + bb + linux + +Verify that the unit testing framework is working as expected: .. code-block:: console @@ -17,7 +24,7 @@ Typical usage and more information on the unit tests can be found in :ref:`Unit tests `. Guidelines for the Unit Test Skeleton -===================================== +------------------------------------- In this example a driver that resides in `src/app/driver/abc/abc.c` and `src/app/driver/abc/abc.h` is added and therefore the accompanying unit tests @@ -83,7 +90,7 @@ Static Function Tests wrapper even more clear. Result -====== +------ .. literalinclude:: ./abc.h :language: C @@ -132,7 +139,7 @@ Using ceedling directly .. warning:: Ceedling (the unit test runner that is used by this project) is wrapped by - the waf-toolchain. + the Waf toolchain. The toolchain makes sure that the path handed to ceedling contains the necessary applications and files, so without the wrapper extensive knowledge of the project structure is helpful. @@ -140,7 +147,7 @@ Using ceedling directly That being said, it is normally not necessary to directly execute ceedling as the wrapper handles this. -The waf-script of this project executes always the complete unit test-suite. +The wscript of this project executes always the complete unit test-suite. This can take some time. When developing or debugging a unit test, it might be beneficial to have finer control over which test is executed. @@ -155,7 +162,7 @@ This will not be covered in this manual. Once such a shell is available it also has to be made sure that all files that are generated or adapted on-the-fly are available in the ``build``-directory. -This can be ensured by executing the waf-task ``build_unit_test`` just until +This can be ensured by executing the Waf task ``build_unit_test`` just until ceedling is run by it. After this step (it does not matter whether the task completes or is imported after it has generated the dependencies) the following example can be executed. @@ -174,3 +181,29 @@ after it has generated the dependencies) the following example can be executed. # should the current shell not be able to directly follow the ceedling.cmd # file, it might be necessary to access the vendored ceedling directly: ruby ../../tools/vendor/ceedling/bin/ceedling gcov:test_plausibility.c + +.. _linux_specific_usage: + +Linux specific Usage +==================== + +The unit test suite is developed on Windows and there works out of the box on +all setup that install the dependencies as they are specified in +:ref:`SOFTWARE_INSTALLATION`. +However, it is still possible to get the unit test suite working on Linux. +Internally it is tested with the following setup: + +- ``cat /etc/redhat-release``: Red Hat Enterprise Linux release 8.8 (Ootpa) +- ``uname -mrs``: Linux 4.18.0-425.19.2.el8_7.x86_64 x86_64 +- ``gcc --version``: gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-18) +- ``ruby --version``: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) + [x86_64-linux] + +Running ``./waf.sh build_unit_test`` works the same as on Windows. +There is also a wrapper to use ceedling directly, that is generated at +``build/unit_test/ceedling.sh``. +It can be used from the root of the repository as follows: + +.. code-block:: console + + ./build/unit_test/ceedling.sh test:test_adc diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index bc3bef18..1a343b54 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -9,12 +9,14 @@ alphanumericals Altium armcl armnm +Artech asm axivion Axivion BMS boolean bugfix +busbar bz cafeCC ceedling @@ -27,19 +29,24 @@ codebase comparator conda config +const contactor contactors CRC creepage criticality dask +Davide dbc deci decodable +derating designators devel Devkit diffs +dimensioning +Dimensioning distcheck dlc Doxygen @@ -56,6 +63,7 @@ extern Farnell fennec ferroelectric +FFh fgui fiducial filename @@ -115,6 +123,7 @@ ltc LTS lvac mA +mAh Mbit MCU microcontroller @@ -153,9 +162,11 @@ posix postprocess postprocessed postprocessing +powerline powershell pre precharge +precharged precharging precomputed preinc @@ -168,7 +179,9 @@ pylint radix readme readmes +recalibrate recalibrated +recalibrates recalibrating receptable redox @@ -240,6 +253,7 @@ vendored versioned versioning viewable +Vishay VSUP waf Wh diff --git a/docs/system/bjb-measurements.csv b/docs/system/bjb-measurements.csv index 3c2655b4..594b6881 100644 --- a/docs/system/bjb-measurements.csv +++ b/docs/system/bjb-measurements.csv @@ -1,6 +1,6 @@ -Symbol ; Description -V\ :sub:`P` ; Pack voltage -V\ :sub:`FP` ; Pack voltage after main fuse -V\ :sub:`SV` ; System voltage -V\ :sub:`SV2` ; System voltage: second power path -I\ :sub:`P` ; Pack current +Symbol ; Reference Name ; Description +V\ :sub:`P` ; ``PackVoltage`` ; Pack voltage +V\ :sub:`FP` ; ``FusedPackVoltage`` ; voltage after main fuse +V\ :sub:`SV` ; ``SystemVoltage`` ; System voltage +V\ :sub:`SV2` ; ``SystemVoltage2`` ; System voltage: second power path +I\ :sub:`P` ; ``PackCurrent`` ; Pack current diff --git a/docs/system/img/battery-system-precharging.png b/docs/system/img/battery-system-precharging.png new file mode 100644 index 00000000..55e7e371 Binary files /dev/null and b/docs/system/img/battery-system-precharging.png differ diff --git a/docs/system/measured-voltages-and-current-in-the-pack.csv b/docs/system/measured-voltages-and-current-in-the-pack.csv new file mode 100644 index 00000000..8ddf9921 --- /dev/null +++ b/docs/system/measured-voltages-and-current-in-the-pack.csv @@ -0,0 +1,5 @@ +Symbol ; Reference Name ; Description +V\ :sub:`Sm` ; ``StringVoltageM`` ; Voltage of string m +V\ :sub:`FSm` ; ``FusedStringVoltageM`` ; Voltage after string fuse of string m +V\ :sub:`Pm` ; ``PackVoltageM`` ; Pack voltage +I\ :sub:`Sm` ; ``StringCurrentM`` ; Current in string m diff --git a/docs/system/pack-measurements-single-string-system.csv b/docs/system/pack-measurements-single-string-system.csv new file mode 100644 index 00000000..594b6881 --- /dev/null +++ b/docs/system/pack-measurements-single-string-system.csv @@ -0,0 +1,6 @@ +Symbol ; Reference Name ; Description +V\ :sub:`P` ; ``PackVoltage`` ; Pack voltage +V\ :sub:`FP` ; ``FusedPackVoltage`` ; voltage after main fuse +V\ :sub:`SV` ; ``SystemVoltage`` ; System voltage +V\ :sub:`SV2` ; ``SystemVoltage2`` ; System voltage: second power path +I\ :sub:`P` ; ``PackCurrent`` ; Pack current diff --git a/docs/system/precharging.rst b/docs/system/precharging.rst new file mode 100644 index 00000000..19d80cbc --- /dev/null +++ b/docs/system/precharging.rst @@ -0,0 +1,82 @@ +.. include:: ./../macros.txt +.. include:: ./../units.txt + +.. _PRECHARGING: + +########### +Precharging +########### + +Precharging of the powerline voltages is a requirement in high voltage DC +applications to limit the potentially high inrush current during the startup. + +Most applications like e.g., motor inverter systems have a rather high +capacitance. +By connecting the application with the battery system a large inrush current +would occur as the load capacitance is charged up to the pack voltage. +This current can easily peak at 1000 A. +Therefore a precharging circuit is needed when initially connecting +a battery system to an application to limit the inrush current to a sensible +value. +Precharging prevents e.g., fuse triggering, excess heating, damage of the +components or weld shutting of the main contactor by limiting the inrush current. + +As shown in :numref:`battery-system-precharging`, a precharge circuit consists +of: + +* a precharge resistor to limit the inrush current +* a switch or contactor in series to the precharge resistor to + activate/deactivate precharging + +.. figure:: img/battery-system-precharging.png + :alt: Precharging circuit in a battery system + :name: battery-system-precharging + :align: center + :target: ../_images/battery-system-precharging.png + + Precharging circuit in a battery system + +*************** +Operation modes +*************** + +Basically, a battery system has three operating modes. + +* *Off*: All contactors connecting the battery system with the application are + open. +* *On*: All contactors connecting the battery system with the application are + closed, i.e., power can be drawn from the system. +* *Precharge*: The application is electrically connected to the battery system. + The precharging contactor is closed to start the precharging process until + the inrush current meets a defined threshold in the maximum specified time. + If the application could be not precharged within the expected maximum time, + precharging is aborted and the BMS goes back into *off* mode. + The precharge resistor in combination with the application capacitance forms + the RC time constant :math:`\tau`. + +******************** +Combination with BMS +******************** + +Another functionality that can be derived by analyzing the precharging process +is to detect failures in the application. +In normal operation the inrush current decreases as the voltage difference +between the battery and the application gets smaller. +If there is a short in the application the current flow will stay close to the +inrush current. +By measuring the voltage and current the BMS can detect the problem if the +normal operation conditions are exceeded by a certain time and report a timeout +failure. + +********************** +Precharge Dimensioning +********************** + +The project contains a tool to help with the dimensioning of the precharging +resistor at ``tools/precharge/precharge_dimensioning.ipynb``. + +*************** +Further Reading +*************** + +For further information on precharging see e.g., :cite:`Andrea2014`. diff --git a/docs/system/system-voltage-and-current-monitoring.rst b/docs/system/system-voltage-and-current-monitoring.rst index 9b78c89c..9be5875e 100644 --- a/docs/system/system-voltage-and-current-monitoring.rst +++ b/docs/system/system-voltage-and-current-monitoring.rst @@ -95,19 +95,14 @@ Thus, the following voltages need to be measured in each string: The current sensor additional measures each string current. -Comprehension of measured voltages and current in the pack: - -+---------------+---------------------------------------+ -| Symbol | Description | -+===============+=======================================+ -| V\ :sub:`Sm` | Voltage of string m | -+---------------+---------------------------------------+ -| V\ :sub:`FSm` | Voltage after string fuse of string m | -+---------------+---------------------------------------+ -| V\ :sub:`Pm` | Pack voltage | -+---------------+---------------------------------------+ -| I\ :sub:`Sm` | Current in string m | -+---------------+---------------------------------------+ +Comprehension of measured voltages and current is found in +:numref:`measured-voltages-and-current-in-the-pack`. + +.. csv-table:: List of measured voltages and current in the pack + :name: measured-voltages-and-current-in-the-pack + :header-rows: 1 + :delim: ; + :file: ./measured-voltages-and-current-in-the-pack.csv ******************** Single-String System @@ -135,7 +130,7 @@ inside the string are required. :name: pack-measurements-single-string-system :header-rows: 1 :delim: ; - :file: ./bjb-measurements.csv + :file: ./pack-measurements-single-string-system.csv ******************************************** Measurements Inside the Battery Junction Box diff --git a/docs/tools/dbc.rst b/docs/tools/dbc.rst index ca6d94d3..7755ba7c 100644 --- a/docs/tools/dbc.rst +++ b/docs/tools/dbc.rst @@ -9,12 +9,11 @@ DBC File .. Comments: - .. spelling:: sym These files describe the CAN interface used by |foxbms|. The .dbc-file has been -created using PCAN Symbol Editor |version_pcan_se| from symbol file +created using PCAN Symbol Editor |version_pcan_symbol_editor| from symbol file |version_sym_file|. The .dbc-file and .sym-file are located in ``tools/dbc``. diff --git a/docs/tools/debugger/debugger-lauterbach.rst b/docs/tools/debugger/debugger-lauterbach.rst index 012ede95..c220be74 100644 --- a/docs/tools/debugger/debugger-lauterbach.rst +++ b/docs/tools/debugger/debugger-lauterbach.rst @@ -26,7 +26,7 @@ Debugger Software ^^^^^^^^^^^^^^^^^ The debugger software is available at -`https://www.lauterbach.com `_. +`https://www.lauterbach.com `_. Lauterbach Manual ^^^^^^^^^^^^^^^^^ @@ -70,7 +70,6 @@ Flash Manipulation #. Manipulate flash as needed #. Lock flash: ``FLASH.ReProgram OFF`` - Deleting Flash -------------- diff --git a/docs/tools/debugger/debugger-ozone.rst b/docs/tools/debugger/debugger-ozone.rst index 35224acf..b051d1e1 100644 --- a/docs/tools/debugger/debugger-ozone.rst +++ b/docs/tools/debugger/debugger-ozone.rst @@ -92,7 +92,7 @@ Tracing with Segger J-Trace PRO Cortex Apart from debug probes, Segger also supplies trace probes. With these devices it is possible to stream internal information from the MCU such as the program counter directly to the debugger. -For the |tms570lc4357| target it is necessary to use the Segger J-Trace PRO +For the |ti-tms570lc4357| target it is necessary to use the Segger J-Trace PRO Cortex model. According to its documentation it is able to trace with a data width of 4 bit. diff --git a/docs/tools/halcogen/halcogen.rst b/docs/tools/halcogen/halcogen.rst index d3836bd6..d7962464 100644 --- a/docs/tools/halcogen/halcogen.rst +++ b/docs/tools/halcogen/halcogen.rst @@ -9,7 +9,7 @@ HALCoGen tool documentation .. note:: A documentation of the tool |halcogen| can be found in this section, the - waf-tool wrapper for this project in :ref:`WAF_TOOL_HALCOGEN`, information + Waf tool wrapper for this project in :ref:`WAF_TOOL_HALCOGEN`, information on configuring |halcogen| in the context of the toolchain of this project in :ref:`HAL_CONFIGURATION` and an example on how to use a pre-generated HAL instead of generating it in the compilation step in @@ -45,7 +45,7 @@ Incompatibility of enum-definitions with newer compilers in strict ANSI mode The ARM CGT compilers since version ``20.2.2.LTS`` (shipped with CCS ``10.2.0.00009``) contain a bugfix for the underlying data type of enums -described in `EXT_EP-10334 `_. +described in `10334 `_. The code that is generated by |halcogen| heavily relies on this behavior when implementing enums. diff --git a/docs/tools/static-analysis/axivion.rst b/docs/tools/static-analysis/axivion.rst index ae62d777..5898f0ec 100644 --- a/docs/tools/static-analysis/axivion.rst +++ b/docs/tools/static-analysis/axivion.rst @@ -32,9 +32,9 @@ Setup ----- - Install OpenJDK and make it available in PATH. -- Install Python 3.8 from https://www.python.org/downloads/windows/. Use the - user installer and make sure to install the Python launcher. Leave all other - options as they are selected. +- Install Python 3.8 from https://www.python.org/downloads/windows/. + Use the user installer and make sure to install the Python launcher. + Leave all other options as they are selected. - Extract Axivion Bauhaus Suite from the zip-file and copy it in a versioned directory e.g., ``C:\Bauhaus\x.y.z`` and add ``C:\Bauhaus\x.y.z\bin`` to the user PATH environment variable. @@ -119,9 +119,11 @@ Advanced Usage Race Condition Analysis +++++++++++++++++++++++ -Go into the directory `racepdfs` and execute the wrapper batch file. This -should generate a directory with call graphs to variables that are accessed in -a potential unsafe manner. These can be used for closer investigation. +Go into the directory `racepdfs` and execute the wrapper batch file. +This should generate a directory with call graphs to variables that are +accessed in a potential unsafe manner. +These can be used for closer investigation. + Updating the architecture ------------------------- diff --git a/docs/tools/waf-tools/compiler-tool/f_ti_arm_cgt.rst b/docs/tools/waf-tools/compiler-tool/f_ti_arm_cgt.rst index 53ba0239..d9dde323 100644 --- a/docs/tools/waf-tools/compiler-tool/f_ti_arm_cgt.rst +++ b/docs/tools/waf-tools/compiler-tool/f_ti_arm_cgt.rst @@ -30,7 +30,6 @@ TI ARM CGT testbuild confcache - The tool is located in ``tools/waf-tools``. Tool Documentation diff --git a/docs/tools/waf-tools/f_bootstrap_library_project.rst b/docs/tools/waf-tools/f_bootstrap_library_project.rst index 143f1864..7984d3b9 100644 --- a/docs/tools/waf-tools/f_bootstrap_library_project.rst +++ b/docs/tools/waf-tools/f_bootstrap_library_project.rst @@ -9,10 +9,8 @@ Bootstrap Library Project .. Comments: - .. spelling:: - The tool is located in ``tools/waf-tools``. Tool Documentation diff --git a/docs/tools/waf-tools/f_hcg.rst b/docs/tools/waf-tools/f_hcg.rst index d8576d0d..6102da40 100644 --- a/docs/tools/waf-tools/f_hcg.rst +++ b/docs/tools/waf-tools/f_hcg.rst @@ -8,7 +8,7 @@ HALCoGen .. note:: A documentation of the tool |halcogen| can be found in - :ref:`HALCOGEN_TOOL_DOCUMENTATION`, the waf-tool wrapper for this project in + :ref:`HALCOGEN_TOOL_DOCUMENTATION`, the Waf tool wrapper for this project in this section, information on configuring |halcogen| in the context of the toolchain of this project in :ref:`HAL_CONFIGURATION` and an example on how to use a pre-generated HAL instead of generating it in the compilation step @@ -24,7 +24,6 @@ HALCoGen hcg dil - The tool is located in ``tools/waf-tools``. .. automodule:: f_hcg diff --git a/docs/tools/waf-tools/waf-tools.rst b/docs/tools/waf-tools/waf-tools.rst index 54c498a4..b047705b 100644 --- a/docs/tools/waf-tools/waf-tools.rst +++ b/docs/tools/waf-tools/waf-tools.rst @@ -6,7 +6,7 @@ Waf Tools ========= -There are |foxbms| specific tools that do not come with waf by default. +There are |foxbms| specific tools that do not come with Waf by default. These tools are included in ``tools/waf-tools`` and implemented as Python scripts. The terms `tool` and `script` are used as synonyms in the following. diff --git a/src/app/application/algorithm/algorithm.c b/src/app/application/algorithm/algorithm.c index 83f4e196..1145184e 100644 --- a/src/app/application/algorithm/algorithm.c +++ b/src/app/application/algorithm/algorithm.c @@ -43,8 +43,8 @@ * @file algorithm.c * @author foxBMS Team * @date 2017-12-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ALGORITHMS * @prefix ALGO * @@ -133,13 +133,13 @@ extern void ALGO_MainFunction(void) { if ((runAlgorithmAsap != false) || (runAlgorithmCycleElapsed != false)) { /* Cycle time elapsed -> call function */ if (algo_algorithms[i].state == ALGO_READY) { - /* Set state to running -> reset to READY before leaving algo function */ + /* Set state to running -> reset to READY before leaving algorithm function */ algo_algorithms[i].state = ALGO_RUNNING; algo_algorithms[i].startTime = OS_GetTickCount(); algo_algorithms[i].fpAlgorithm(); ALGO_MarkAsDone(i); } - /* check if we need to reinit */ + /* check if we need to reinitialize */ if (algo_algorithms[i].state == ALGO_REINIT_REQUESTED) { /* set to uninitialized so that the algorithm can be reinitialized */ algo_algorithms[i].state = ALGO_UNINITIALIZED; diff --git a/src/app/application/algorithm/algorithm.h b/src/app/application/algorithm/algorithm.h index df67f46e..deb59b06 100644 --- a/src/app/application/algorithm/algorithm.h +++ b/src/app/application/algorithm/algorithm.h @@ -43,8 +43,8 @@ * @file algorithm.h * @author foxBMS Team * @date 2017-12-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ALGORITHMS * @prefix ALGO * diff --git a/src/app/application/algorithm/config/algorithm_cfg.c b/src/app/application/algorithm/config/algorithm_cfg.c index a0bc47b7..4d776a57 100644 --- a/src/app/application/algorithm/config/algorithm_cfg.c +++ b/src/app/application/algorithm/config/algorithm_cfg.c @@ -43,8 +43,8 @@ * @file algorithm_cfg.c * @author foxBMS Team * @date 2017-12-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ALGORITHMS_CONFIGURATION * @prefix ALGO * @@ -82,11 +82,11 @@ const uint16_t algo_length = sizeof(algo_algorithms) / sizeof(algo_algorithms[0] extern void ALGO_MarkAsDone(uint32_t algorithmIndex) { FAS_ASSERT(algorithmIndex < algo_length); if (algo_algorithms[algorithmIndex].state == ALGO_REINIT_REQUESTED) { - /* do not alter state if a reinit request is pending */ + /* do not alter state if a reinitialize request is pending */ } else if (algo_algorithms[algorithmIndex].state != ALGO_BLOCKED) { algo_algorithms[algorithmIndex].state = ALGO_READY; } else { - /* algo is in "blocked" state, nothing to do here */ + /* algorithm is in "blocked" state, nothing to do here */ } } diff --git a/src/app/application/algorithm/config/algorithm_cfg.h b/src/app/application/algorithm/config/algorithm_cfg.h index c28420a5..bbbec6bc 100644 --- a/src/app/application/algorithm/config/algorithm_cfg.h +++ b/src/app/application/algorithm/config/algorithm_cfg.h @@ -43,8 +43,8 @@ * @file algorithm_cfg.h * @author foxBMS Team * @date 2017-12-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ALGORITHMS_CONFIGURATION * @prefix ALGO * @@ -63,7 +63,7 @@ /*========== Macros and Definitions =========================================*/ /** * @ingroup ALGORITHMS_CONFIGURATION - * @details task timeslot where the ALGO main function is called. Repetition + * @details task time slot where the ALGO main function is called. Repetition * time of algorithm cycle time must be multiple of this */ #define ALGO_TICK_ms (100u) diff --git a/src/app/application/algorithm/moving_average/moving_average.c b/src/app/application/algorithm/moving_average/moving_average.c index d9dbfd74..e27d812d 100644 --- a/src/app/application/algorithm/moving_average/moving_average.c +++ b/src/app/application/algorithm/moving_average/moving_average.c @@ -43,8 +43,8 @@ * @file moving_average.c * @author foxBMS Team * @date 2017-12-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ALGORITHMS * @prefix ALGO * @@ -104,7 +104,7 @@ /* Arrays in extern SDRAM to calculate moving average current and power */ -/* Check if minimum algo cycle time > current sensor sample time */ +/* Check if minimum algorithm cycle time > current sensor sample time */ #if ALGO_TICK_ms > ISA_CURRENT_CYCLE_TIME_ms #if MOVING_AVERAGE_DURATION_CURRENT_CONFIG_ms / ALGO_TICK_ms > 60000u / ALGO_TICK_ms /* If array length of configured time > 60s array take this array size */ @@ -129,7 +129,7 @@ static uint32_t movingAverageCurrentLength = (60000u / ISA_CURRENT_CYCLE_TIME_ms #endif #endif -/* Check if minimum algo cycle time > current sensor sample time */ +/* Check if minimum algorithm cycle time > current sensor sample time */ #if ALGO_TICK_ms > ISA_POWER_CYCLE_TIME_ms #if (MOVING_AVERAGE_DURATION_POWER_CONFIG_ms / ALGO_TICK_ms) > (60000u / ALGO_TICK_ms) /* If array length of configured time > 60s array take this array size */ diff --git a/src/app/application/algorithm/moving_average/moving_average.h b/src/app/application/algorithm/moving_average/moving_average.h index abdb9868..ab78824f 100644 --- a/src/app/application/algorithm/moving_average/moving_average.h +++ b/src/app/application/algorithm/moving_average/moving_average.h @@ -43,8 +43,8 @@ * @file moving_average.h * @author foxBMS Team * @date 2017-12-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ALGORITHMS * @prefix ALGO * diff --git a/src/app/application/algorithm/state_estimation/soc/counting/soc_counting.c b/src/app/application/algorithm/state_estimation/soc/counting/soc_counting.c index 2c4bdf6d..79844544 100644 --- a/src/app/application/algorithm/state_estimation/soc/counting/soc_counting.c +++ b/src/app/application/algorithm/state_estimation/soc/counting/soc_counting.c @@ -43,8 +43,8 @@ * @file soc_counting.c * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOC * @@ -55,12 +55,13 @@ /*========== Includes =======================================================*/ #include "general.h" -#include "soc_counting.h" +#include "soc_counting_cfg.h" #include "bms.h" #include "database.h" #include "foxmath.h" #include "fram.h" +#include "state_estimation.h" #include #include @@ -112,9 +113,9 @@ static float_t SOC_GetStringSocPercentageFromCharge(uint32_t charge_As); /** * @brief initializes database and FRAM SOC values via lookup table (average, * minimum and maximum). - * @param[out] pTableSoc pointer to database enty with SOC values + * @param[out] pTableSoc pointer to database entry with SOC values */ -static void SOC_RecalibrateViaLookupTable(DATA_BLOCK_SOX_s *pTableSoc); +static void SOC_RecalibrateViaLookupTable(DATA_BLOCK_SOC_s *pTableSoc); /** * @brief sets SOC value with a parameter between 0.0 and 100.0. @@ -128,7 +129,7 @@ static void SOC_RecalibrateViaLookupTable(DATA_BLOCK_SOX_s *pTableSoc); * @param[in] stringNumber addressed string */ static void SOC_SetValue( - DATA_BLOCK_SOX_s *pTableSoc, + DATA_BLOCK_SOC_s *pTableSoc, float_t socMinimumValue_perc, float_t socMaximumValue_perc, float_t socAverageValue_perc, @@ -140,14 +141,14 @@ static void SOC_SetValue( * @param[in,out] pTableSoc pointer to database struct with SOC values * @param[in] stringNumber string that is checked */ -static void SOC_CheckDatabaseSocPercentageLimits(DATA_BLOCK_SOX_s *pTableSoc, uint8_t stringNumber); +static void SOC_CheckDatabaseSocPercentageLimits(DATA_BLOCK_SOC_s *pTableSoc, uint8_t stringNumber); /** * @brief Set SOC-related values in non-volatile memory * @param[in] pTableSoc pointer to database struct with SOC values * @param[in] stringNumber addressed string */ -static void SOC_UpdateNvmValues(DATA_BLOCK_SOX_s *pTableSoc, uint8_t stringNumber); +static void SOC_UpdateNvmValues(DATA_BLOCK_SOC_s *pTableSoc, uint8_t stringNumber); /*========== Static Function Implementations ================================*/ static float_t SOC_GetStringSocPercentageFromCharge(uint32_t charge_As) { @@ -155,7 +156,7 @@ static float_t SOC_GetStringSocPercentageFromCharge(uint32_t charge_As) { return UNIT_CONVERSION_FACTOR_100_FLOAT * (charge_mAs / SOC_STRING_CAPACITY_mAs); } -static void SOC_RecalibrateViaLookupTable(DATA_BLOCK_SOX_s *pTableSoc) { +static void SOC_RecalibrateViaLookupTable(DATA_BLOCK_SOC_s *pTableSoc) { FAS_ASSERT(pTableSoc != NULL_PTR); DATA_BLOCK_MIN_MAX_s tableMinMaxCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; DATA_READ_DATA(&tableMinMaxCellVoltages); @@ -172,7 +173,7 @@ static void SOC_RecalibrateViaLookupTable(DATA_BLOCK_SOX_s *pTableSoc) { } static void SOC_SetValue( - DATA_BLOCK_SOX_s *pTableSoc, + DATA_BLOCK_SOC_s *pTableSoc, float_t socMinimumValue_perc, float_t socMaximumValue_perc, float_t socAverageValue_perc, @@ -207,7 +208,7 @@ static void SOC_SetValue( FRAM_WriteData(FRAM_BLOCK_ID_SOC); } -static void SOC_CheckDatabaseSocPercentageLimits(DATA_BLOCK_SOX_s *pTableSoc, uint8_t stringNumber) { +static void SOC_CheckDatabaseSocPercentageLimits(DATA_BLOCK_SOC_s *pTableSoc, uint8_t stringNumber) { FAS_ASSERT(pTableSoc != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); @@ -231,7 +232,7 @@ static void SOC_CheckDatabaseSocPercentageLimits(DATA_BLOCK_SOX_s *pTableSoc, ui } } -static void SOC_UpdateNvmValues(DATA_BLOCK_SOX_s *pTableSoc, uint8_t stringNumber) { +static void SOC_UpdateNvmValues(DATA_BLOCK_SOC_s *pTableSoc, uint8_t stringNumber) { FAS_ASSERT(pTableSoc != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); fram_soc.averageSoc_perc[stringNumber] = pTableSoc->averageSoc_perc[stringNumber]; @@ -241,7 +242,7 @@ static void SOC_UpdateNvmValues(DATA_BLOCK_SOX_s *pTableSoc, uint8_t stringNumbe /*========== Extern Function Implementations ================================*/ -void SE_InitializeStateOfCharge(DATA_BLOCK_SOX_s *pSocValues, bool ccPresent, uint8_t stringNumber) { +void SE_InitializeStateOfCharge(DATA_BLOCK_SOC_s *pSocValues, bool ccPresent, uint8_t stringNumber) { FAS_ASSERT(pSocValues != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); DATA_READ_DATA(&soc_tableCurrentSensor); @@ -283,7 +284,7 @@ void SE_InitializeStateOfCharge(DATA_BLOCK_SOX_s *pSocValues, bool ccPresent, ui } /* INCLUDE MARKER FOR THE DOCUMENTATION; DO NOT MOVE cc-documentation-start-include */ -void SE_CalculateStateOfCharge(DATA_BLOCK_SOX_s *pSocValues) { +void SE_CalculateStateOfCharge(DATA_BLOCK_SOC_s *pSocValues) { /* INCLUDE MARKER FOR THE DOCUMENTATION; DO NOT MOVE cc-documentation-stop-include */ FAS_ASSERT(pSocValues != NULL_PTR); bool continueFunction = true; diff --git a/src/app/application/algorithm/state_estimation/soc/counting/soc_counting_cfg.h b/src/app/application/algorithm/state_estimation/soc/counting/soc_counting_cfg.h index a943b7e9..9203ee5b 100644 --- a/src/app/application/algorithm/state_estimation/soc/counting/soc_counting_cfg.h +++ b/src/app/application/algorithm/state_estimation/soc/counting/soc_counting_cfg.h @@ -43,8 +43,8 @@ * @file soc_counting_cfg.h * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOC * @@ -68,7 +68,7 @@ * Cell capacity used for SOC calculation, in this case Ah counting * Specified once according to data sheet of cell usually. */ -#define SOC_STRING_CAPACITY_mAh ((float_t)(BS_NR_OF_PARALLEL_CELLS_PER_MODULE * BC_CAPACITY_mAh)) +#define SOC_STRING_CAPACITY_mAh ((float_t)(BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK * BC_CAPACITY_mAh)) /** #SOC_STRING_CAPACITY_mAh in mAs */ #define SOC_STRING_CAPACITY_mAs ((float_t)(SOC_STRING_CAPACITY_mAh * 3600.0f)) diff --git a/src/app/application/algorithm/state_estimation/soc/debug/soc_debug.c b/src/app/application/algorithm/state_estimation/soc/debug/soc_debug.c index db3fc1ea..419e76d7 100644 --- a/src/app/application/algorithm/state_estimation/soc/debug/soc_debug.c +++ b/src/app/application/algorithm/state_estimation/soc/debug/soc_debug.c @@ -43,8 +43,8 @@ * @file soc_debug.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOC * @@ -53,8 +53,6 @@ */ /*========== Includes =======================================================*/ -#include "soc_debug.h" - #include "database_cfg.h" #include @@ -72,12 +70,12 @@ /*========== Static Function Implementations ================================*/ /*========== Extern Function Implementations ================================*/ -extern void SE_InitializeStateOfCharge(DATA_BLOCK_SOX_s *pSocValues, bool ccPresent, uint8_t stringNumber) { +extern void SE_InitializeStateOfCharge(DATA_BLOCK_SOC_s *pSocValues, bool ccPresent, uint8_t stringNumber) { FAS_ASSERT(pSocValues != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); } -extern void SE_CalculateStateOfCharge(DATA_BLOCK_SOX_s *pSocValues) { +extern void SE_CalculateStateOfCharge(DATA_BLOCK_SOC_s *pSocValues) { FAS_ASSERT(pSocValues != NULL_PTR); } diff --git a/src/app/application/algorithm/state_estimation/soc/none/soc_none.c b/src/app/application/algorithm/state_estimation/soc/none/soc_none.c index d702ec8f..127802dc 100644 --- a/src/app/application/algorithm/state_estimation/soc/none/soc_none.c +++ b/src/app/application/algorithm/state_estimation/soc/none/soc_none.c @@ -43,8 +43,8 @@ * @file soc_none.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOC * @@ -53,7 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "soc_none.h" +#include "state_estimation.h" #include #include @@ -69,12 +69,12 @@ /*========== Static Function Implementations ================================*/ /*========== Extern Function Implementations ================================*/ -extern void SE_InitializeStateOfCharge(DATA_BLOCK_SOX_s *pSocValues, bool ccPresent, uint8_t stringNumber) { +extern void SE_InitializeStateOfCharge(DATA_BLOCK_SOC_s *pSocValues, bool ccPresent, uint8_t stringNumber) { FAS_ASSERT(pSocValues != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); } -extern void SE_CalculateStateOfCharge(DATA_BLOCK_SOX_s *pSocValues) { +extern void SE_CalculateStateOfCharge(DATA_BLOCK_SOC_s *pSocValues) { FAS_ASSERT(pSocValues != NULL_PTR); } diff --git a/src/app/application/algorithm/state_estimation/soc/none/soc_none.h b/src/app/application/algorithm/state_estimation/soc/none/soc_none.h deleted file mode 100644 index 18ee47e6..00000000 --- a/src/app/application/algorithm/state_estimation/soc/none/soc_none.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soc_none.h - * @author foxBMS Team - * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOC - * - * @brief Header for SOC module, responsible for calculation state-of-charge - * - */ - -#ifndef FOXBMS__SOC_NONE_H_ -#define FOXBMS__SOC_NONE_H_ - -/*========== Includes =======================================================*/ -#include "state_estimation.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__SOC_NONE_H_ */ diff --git a/src/app/application/algorithm/state_estimation/soe/counting/soe_counting.c b/src/app/application/algorithm/state_estimation/soe/counting/soe_counting.c index b2689602..4d976c93 100644 --- a/src/app/application/algorithm/state_estimation/soe/counting/soe_counting.c +++ b/src/app/application/algorithm/state_estimation/soe/counting/soe_counting.c @@ -43,8 +43,8 @@ * @file soe_counting.c * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOE * @@ -53,8 +53,6 @@ */ /*========== Includes =======================================================*/ -#include "soe_counting.h" - #include "battery_cell_cfg.h" #include "battery_system_cfg.h" #include "soe_counting_cfg.h" @@ -63,6 +61,7 @@ #include "database.h" #include "foxmath.h" #include "fram.h" +#include "state_estimation.h" #include #include @@ -70,7 +69,7 @@ /*========== Macros and Definitions =========================================*/ /** - * This structure contains all the variables relevant for the SOX. + * This structure contains all the variables relevant for the SOE. */ typedef struct { bool soeInitialized; /*!< true if the initialization has passed, false otherwise */ @@ -131,7 +130,7 @@ static float_t SOE_GetStringSoePercentageFromEnergy(uint32_t energy_Wh); * @brief initializes database and FRAM SOE values via lookup table (average, min and max). * @param[out] pSoeValues pointer to SOE database entry */ -static void SOE_RecalibrateViaLookupTable(DATA_BLOCK_SOX_s *pSoeValues); +static void SOE_RecalibrateViaLookupTable(DATA_BLOCK_SOE_s *pSoeValues); /** * @brief look-up table for SOE initialization @@ -147,14 +146,14 @@ static float_t SOE_GetFromVoltage(int16_t voltage_mV); * @details limits the SOE value to 0.0 respectively 100.0 if a value outside * of the allowed SOE range is passed. Updates local fram and database * struct but does *NOT* write them - * @param[out] pSoeValues pointer to SOE database enty + * @param[out] pSoeValues pointer to SOE database entry * @param[in] soeMinimumValue_perc SOE min value to set * @param[in] soeMaximumValue_perc SOE max value to set * @param[in] soeAverageValue_perc SOE average value to set * @param[in] stringNumber string addressed */ static void SOE_SetValue( - DATA_BLOCK_SOX_s *pSoeValues, + DATA_BLOCK_SOE_s *pSoeValues, float_t soeMinimumValue_perc, float_t soeMaximumValue_perc, float_t soeAverageValue_perc, @@ -167,7 +166,7 @@ static void SOE_SetValue( * @param[in,out] pTableSoe pointer to database struct with SOE values * @param[in] stringNumber string that is checked */ -static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOX_s *pTableSoe, uint8_t stringNumber); +static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOE_s *pTableSoe, uint8_t stringNumber); /*========== Static Function Implementations ================================*/ static float_t SOE_GetStringSoePercentageFromEnergy(uint32_t energy_Wh) { @@ -193,7 +192,7 @@ static uint32_t SOE_GetStringEnergyFromSoePercentage(float_t stringSoe_perc) { return (uint32_t)energy_Wh; } -static void SOE_RecalibrateViaLookupTable(DATA_BLOCK_SOX_s *pSoeValues) { +static void SOE_RecalibrateViaLookupTable(DATA_BLOCK_SOE_s *pSoeValues) { FAS_ASSERT(pSoeValues != NULL_PTR); DATA_BLOCK_MIN_MAX_s tableMinimumMaximumAverage = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; @@ -244,7 +243,7 @@ static float_t SOE_GetFromVoltage(int16_t voltage_mV) { } static void SOE_SetValue( - DATA_BLOCK_SOX_s *pSoeValues, + DATA_BLOCK_SOE_s *pSoeValues, float_t soeMinimumValue_perc, float_t soeMaximumValue_perc, float_t soeAverageValue_perc, @@ -287,7 +286,7 @@ static void SOE_SetValue( } } -static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOX_s *pTableSoe, uint8_t stringNumber) { +static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOE_s *pTableSoe, uint8_t stringNumber) { FAS_ASSERT(pTableSoe != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); @@ -313,7 +312,7 @@ static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOX_s *pTableSoe, ui /*========== Extern Function Implementations ================================*/ -extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues, bool ec_present, uint8_t stringNumber) { +extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues, bool ec_present, uint8_t stringNumber) { FAS_ASSERT(pSoeValues != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); FRAM_ReadData(FRAM_BLOCK_ID_SOE); @@ -357,7 +356,7 @@ extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues, bool ec_pre soe_state.soeInitialized = true; } -void SE_CalculateStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues) { +void SE_CalculateStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues) { FAS_ASSERT(pSoeValues != NULL_PTR); bool continueFunction = true; if (soe_state.soeInitialized == false) { diff --git a/src/app/application/algorithm/state_estimation/soe/counting/soe_counting.h b/src/app/application/algorithm/state_estimation/soe/counting/soe_counting.h deleted file mode 100644 index d8263326..00000000 --- a/src/app/application/algorithm/state_estimation/soe/counting/soe_counting.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soe_counting.h - * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOE - * - * @brief Header for SOE module, responsible for calculation of SOE - * - */ - -#ifndef FOXBMS__SOE_COUNTING_H_ -#define FOXBMS__SOE_COUNTING_H_ - -/*========== Includes =======================================================*/ -#include "state_estimation.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__SOE_COUNTING_H_ */ diff --git a/src/app/application/algorithm/state_estimation/soe/counting/soe_counting_cfg.h b/src/app/application/algorithm/state_estimation/soe/counting/soe_counting_cfg.h index b84a59f2..dcf3695c 100644 --- a/src/app/application/algorithm/state_estimation/soe/counting/soe_counting_cfg.h +++ b/src/app/application/algorithm/state_estimation/soe/counting/soe_counting_cfg.h @@ -43,8 +43,8 @@ * @file soe_counting_cfg.h * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOE * @@ -72,7 +72,7 @@ /** Slice energy in Wh */ #define SOE_STRING_ENERGY_Wh \ - (BC_ENERGY_Wh * (float_t)(BS_NR_OF_CELL_BLOCKS_PER_STRING * BS_NR_OF_PARALLEL_CELLS_PER_MODULE)) + (BC_ENERGY_Wh * (float_t)(BS_NR_OF_CELL_BLOCKS_PER_STRING * BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK)) /*========== Extern Constant and Variable Declarations ======================*/ diff --git a/src/app/application/algorithm/state_estimation/soe/debug/soe_debug.c b/src/app/application/algorithm/state_estimation/soe/debug/soe_debug.c index f017beb7..b868970d 100644 --- a/src/app/application/algorithm/state_estimation/soe/debug/soe_debug.c +++ b/src/app/application/algorithm/state_estimation/soe/debug/soe_debug.c @@ -43,8 +43,8 @@ * @file soe_debug.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOE * @@ -53,7 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "soe_debug.h" +#include "state_estimation.h" #include @@ -68,12 +68,12 @@ /*========== Static Function Implementations ================================*/ /*========== Extern Function Implementations ================================*/ -extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues, bool ec_present, uint8_t stringNumber) { +extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues, bool ec_present, uint8_t stringNumber) { FAS_ASSERT(pSoeValues != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); } -extern void SE_CalculateStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues) { +extern void SE_CalculateStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues) { FAS_ASSERT(pSoeValues != NULL_PTR); } diff --git a/src/app/application/algorithm/state_estimation/soe/debug/soe_debug.h b/src/app/application/algorithm/state_estimation/soe/debug/soe_debug.h deleted file mode 100644 index 8ab73003..00000000 --- a/src/app/application/algorithm/state_estimation/soe/debug/soe_debug.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soe_debug.h - * @author foxBMS Team - * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOE - * - * @brief Header for SOE module, responsible for calculation state-of-energy - * - */ - -#ifndef FOXBMS__SOE_DEBUG_H_ -#define FOXBMS__SOE_DEBUG_H_ - -/*========== Includes =======================================================*/ -#include "state_estimation.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__SOE_DEBUG_H_ */ diff --git a/src/app/application/algorithm/state_estimation/soe/debug/soe_debug_cfg.c b/src/app/application/algorithm/state_estimation/soe/debug/soe_debug_cfg.c deleted file mode 100644 index 5a46352f..00000000 --- a/src/app/application/algorithm/state_estimation/soe/debug/soe_debug_cfg.c +++ /dev/null @@ -1,74 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soe_debug_cfg.c - * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOE - * - * @brief SOE calculation configuration file - * - */ - -/*========== Includes =======================================================*/ -#include "soe_debug_cfg.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Static Constant and Variable Definitions =======================*/ - -/*========== Extern Constant and Variable Definitions =======================*/ - -/*========== Static Function Prototypes =====================================*/ - -/*========== Static Function Implementations ================================*/ - -/*========== Extern Function Implementations ================================*/ - -/*========== Externalized Static Function Implementations (Unit Test) =======*/ -#ifdef UNITY_UNIT_TEST -#endif diff --git a/src/app/application/algorithm/state_estimation/soe/debug/soe_debug_cfg.h b/src/app/application/algorithm/state_estimation/soe/debug/soe_debug_cfg.h index 25738ca6..78a8d3fc 100644 --- a/src/app/application/algorithm/state_estimation/soe/debug/soe_debug_cfg.h +++ b/src/app/application/algorithm/state_estimation/soe/debug/soe_debug_cfg.h @@ -43,8 +43,8 @@ * @file soe_debug_cfg.h * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOE * diff --git a/src/app/application/algorithm/state_estimation/soe/none/soe_none.c b/src/app/application/algorithm/state_estimation/soe/none/soe_none.c index d28fd715..e1fb669c 100644 --- a/src/app/application/algorithm/state_estimation/soe/none/soe_none.c +++ b/src/app/application/algorithm/state_estimation/soe/none/soe_none.c @@ -43,8 +43,8 @@ * @file soe_none.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOE * @@ -53,7 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "soe_none.h" +#include "state_estimation.h" #include @@ -68,12 +68,12 @@ /*========== Static Function Implementations ================================*/ /*========== Extern Function Implementations ================================*/ -extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues, bool ec_present, uint8_t stringNumber) { +extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues, bool ec_present, uint8_t stringNumber) { FAS_ASSERT(pSoeValues != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); } -extern void SE_CalculateStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues) { +extern void SE_CalculateStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues) { FAS_ASSERT(pSoeValues != NULL_PTR); } diff --git a/src/app/application/algorithm/state_estimation/soe/none/soe_none.h b/src/app/application/algorithm/state_estimation/soe/none/soe_none.h deleted file mode 100644 index 6385869c..00000000 --- a/src/app/application/algorithm/state_estimation/soe/none/soe_none.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soe_none.h - * @author foxBMS Team - * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOE - * - * @brief Header for SOE module, responsible for calculation state-of-energy - * - */ - -#ifndef FOXBMS__SOE_NONE_H_ -#define FOXBMS__SOE_NONE_H_ - -/*========== Includes =======================================================*/ -#include "state_estimation.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__SOE_NONE_H_ */ diff --git a/src/app/application/algorithm/state_estimation/soe/none/soe_none_cfg.c b/src/app/application/algorithm/state_estimation/soe/none/soe_none_cfg.c deleted file mode 100644 index 38b31b10..00000000 --- a/src/app/application/algorithm/state_estimation/soe/none/soe_none_cfg.c +++ /dev/null @@ -1,74 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soe_none_cfg.c - * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOE - * - * @brief SOE calculation configuration file - * - */ - -/*========== Includes =======================================================*/ -#include "soe_none_cfg.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Static Constant and Variable Definitions =======================*/ - -/*========== Extern Constant and Variable Definitions =======================*/ - -/*========== Static Function Prototypes =====================================*/ - -/*========== Static Function Implementations ================================*/ - -/*========== Extern Function Implementations ================================*/ - -/*========== Externalized Static Function Implementations (Unit Test) =======*/ -#ifdef UNITY_UNIT_TEST -#endif diff --git a/src/app/application/algorithm/state_estimation/soe/none/soe_none_cfg.h b/src/app/application/algorithm/state_estimation/soe/none/soe_none_cfg.h index d5fdaf38..20887e3e 100644 --- a/src/app/application/algorithm/state_estimation/soe/none/soe_none_cfg.h +++ b/src/app/application/algorithm/state_estimation/soe/none/soe_none_cfg.h @@ -43,8 +43,8 @@ * @file soe_none_cfg.h * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOE * diff --git a/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.c b/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.c index 79062cf7..a29211ad 100644 --- a/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.c +++ b/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.c @@ -43,12 +43,12 @@ * @file sof_trapezoid.c * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION_CONFIGURATION * @prefix SOF * - * @brief SOX module responsible for current derating calculation + * @brief SOF modules responsible for current derating calculation * */ diff --git a/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.h b/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.h index f0b66cd3..b96de49d 100644 --- a/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.h +++ b/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.h @@ -43,8 +43,8 @@ * @file sof_trapezoid.h * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOF * diff --git a/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.c b/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.c index 7eb2ec09..e271523c 100644 --- a/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.c +++ b/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.c @@ -43,8 +43,8 @@ * @file sof_trapezoid_cfg.c * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOF * diff --git a/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.h b/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.h index 3651a5fb..a825d466 100644 --- a/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.h +++ b/src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.h @@ -43,8 +43,8 @@ * @file sof_trapezoid_cfg.h * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION_CONFIGURATION * @prefix SOF * @@ -58,6 +58,7 @@ /*========== Includes =======================================================*/ #include "battery_cell_cfg.h" +#include "battery_system_cfg.h" #include #include @@ -68,13 +69,15 @@ * Maximum current in mA in charge direction that a string can sustain. * Normally set once for the specific battery cell from data sheet */ -#define SOF_STRING_CURRENT_CONTINUOUS_CHARGE_mA ((float_t)BC_CURRENT_MAX_CHARGE_MOL_mA) +#define SOF_STRING_CURRENT_CONTINUOUS_CHARGE_mA \ + ((float_t)BC_CURRENT_MAX_CHARGE_MOL_mA * BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK) /** * Maximum current in mA in discharge direction that a string can deliver. * Normally set once for the specific battery cell from data sheet. */ -#define SOF_STRING_CURRENT_CONTINUOUS_DISCHARGE_mA ((float_t)BC_CURRENT_MAX_DISCHARGE_MOL_mA) +#define SOF_STRING_CURRENT_CONTINUOUS_DISCHARGE_mA \ + ((float_t)BC_CURRENT_MAX_DISCHARGE_MOL_mA * BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK) /** * Current in mA that the string should be able to discharge when in diff --git a/src/app/application/algorithm/state_estimation/soh/debug/soh_debug.c b/src/app/application/algorithm/state_estimation/soh/debug/soh_debug.c index 23359532..f4e6ccf2 100644 --- a/src/app/application/algorithm/state_estimation/soh/debug/soh_debug.c +++ b/src/app/application/algorithm/state_estimation/soh/debug/soh_debug.c @@ -43,8 +43,8 @@ * @file soh_debug.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOH * @@ -53,7 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "soh_debug.h" +#include "state_estimation.h" #include @@ -68,7 +68,7 @@ /*========== Static Function Implementations ================================*/ /*========== Extern Function Implementations ================================*/ -extern void SE_InitializeStateOfHealth(DATA_BLOCK_SOX_s *pSohValues, uint8_t stringNumber) { +extern void SE_InitializeStateOfHealth(DATA_BLOCK_SOH_s *pSohValues, uint8_t stringNumber) { FAS_ASSERT(pSohValues != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); if (stringNumber < BS_NR_OF_STRINGS) { @@ -78,7 +78,7 @@ extern void SE_InitializeStateOfHealth(DATA_BLOCK_SOX_s *pSohValues, uint8_t str } } -extern void SE_CalculateStateOfHealth(DATA_BLOCK_SOX_s *pSohValues) { +extern void SE_CalculateStateOfHealth(DATA_BLOCK_SOH_s *pSohValues) { FAS_ASSERT(pSohValues != NULL_PTR); pSohValues->averageSoh_perc[0u] = 50.0f; diff --git a/src/app/application/algorithm/state_estimation/soh/debug/soh_debug.h b/src/app/application/algorithm/state_estimation/soh/debug/soh_debug.h deleted file mode 100644 index 2869d60e..00000000 --- a/src/app/application/algorithm/state_estimation/soh/debug/soh_debug.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soh_debug.h - * @author foxBMS Team - * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOH - * - * @brief Header for SOH module, responsible for calculation state-of-health - * - */ - -#ifndef FOXBMS__SOH_DEBUG_H_ -#define FOXBMS__SOH_DEBUG_H_ - -/*========== Includes =======================================================*/ -#include "state_estimation.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__SOH_DEBUG_H_ */ diff --git a/src/app/application/algorithm/state_estimation/soh/debug/soh_debug_cfg.c b/src/app/application/algorithm/state_estimation/soh/debug/soh_debug_cfg.c deleted file mode 100644 index 425c3526..00000000 --- a/src/app/application/algorithm/state_estimation/soh/debug/soh_debug_cfg.c +++ /dev/null @@ -1,74 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soh_debug_cfg.c - * @author foxBMS Team - * @date 2021-12-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOH - * - * @brief SOH calculation configuration file - * - */ - -/*========== Includes =======================================================*/ -#include "soh_debug_cfg.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Static Constant and Variable Definitions =======================*/ - -/*========== Extern Constant and Variable Definitions =======================*/ - -/*========== Static Function Prototypes =====================================*/ - -/*========== Static Function Implementations ================================*/ - -/*========== Extern Function Implementations ================================*/ - -/*========== Externalized Static Function Implementations (Unit Test) =======*/ -#ifdef UNITY_UNIT_TEST -#endif diff --git a/src/app/application/algorithm/state_estimation/soh/debug/soh_debug_cfg.h b/src/app/application/algorithm/state_estimation/soh/debug/soh_debug_cfg.h deleted file mode 100644 index 1177df9a..00000000 --- a/src/app/application/algorithm/state_estimation/soh/debug/soh_debug_cfg.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soh_debug_cfg.h - * @author foxBMS Team - * @date 2021-12-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOH - * - * @brief Header for SOH configuration - * - */ - -#ifndef FOXBMS__SOH_DEBUG_CFG_H_ -#define FOXBMS__SOH_DEBUG_CFG_H_ - -/*========== Includes =======================================================*/ - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__SOH_DEBUG_CFG_H_ */ diff --git a/src/app/application/algorithm/state_estimation/soh/none/soh_none.c b/src/app/application/algorithm/state_estimation/soh/none/soh_none.c index 2ff982eb..479925f5 100644 --- a/src/app/application/algorithm/state_estimation/soh/none/soh_none.c +++ b/src/app/application/algorithm/state_estimation/soh/none/soh_none.c @@ -43,8 +43,8 @@ * @file soh_none.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOH * @@ -53,7 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "soh_none.h" +#include "state_estimation.h" #include @@ -68,12 +68,12 @@ /*========== Static Function Implementations ================================*/ /*========== Extern Function Implementations ================================*/ -extern void SE_InitializeStateOfHealth(DATA_BLOCK_SOX_s *pSohValues, uint8_t stringNumber) { +extern void SE_InitializeStateOfHealth(DATA_BLOCK_SOH_s *pSohValues, uint8_t stringNumber) { FAS_ASSERT(pSohValues != NULL_PTR); FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); } -extern void SE_CalculateStateOfHealth(DATA_BLOCK_SOX_s *pSohValues) { +extern void SE_CalculateStateOfHealth(DATA_BLOCK_SOH_s *pSohValues) { FAS_ASSERT(pSohValues != NULL_PTR); } diff --git a/src/app/application/algorithm/state_estimation/soh/none/soh_none_cfg.c b/src/app/application/algorithm/state_estimation/soh/none/soh_none_cfg.c deleted file mode 100644 index b70bdb0f..00000000 --- a/src/app/application/algorithm/state_estimation/soh/none/soh_none_cfg.c +++ /dev/null @@ -1,74 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soh_none_cfg.c - * @author foxBMS Team - * @date 2021-12-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOH - * - * @brief SOH calculation configuration file - * - */ - -/*========== Includes =======================================================*/ -#include "soh_none_cfg.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Static Constant and Variable Definitions =======================*/ - -/*========== Extern Constant and Variable Definitions =======================*/ - -/*========== Static Function Prototypes =====================================*/ - -/*========== Static Function Implementations ================================*/ - -/*========== Extern Function Implementations ================================*/ - -/*========== Externalized Static Function Implementations (Unit Test) =======*/ -#ifdef UNITY_UNIT_TEST -#endif diff --git a/src/app/application/algorithm/state_estimation/soh/none/soh_none_cfg.h b/src/app/application/algorithm/state_estimation/soh/none/soh_none_cfg.h deleted file mode 100644 index ff1c029b..00000000 --- a/src/app/application/algorithm/state_estimation/soh/none/soh_none_cfg.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file soh_none_cfg.h - * @author foxBMS Team - * @date 2021-12-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOH - * - * @brief Header for SOH configuration - * - */ - -#ifndef FOXBMS__SOH_NONE_CFG_H_ -#define FOXBMS__SOH_NONE_CFG_H_ - -/*========== Includes =======================================================*/ - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__SOH_NONE_CFG_H_ */ diff --git a/src/app/application/algorithm/state_estimation/state_estimation.c b/src/app/application/algorithm/state_estimation/state_estimation.c index 5a1d49e9..6244150e 100644 --- a/src/app/application/algorithm/state_estimation/state_estimation.c +++ b/src/app/application/algorithm/state_estimation/state_estimation.c @@ -43,8 +43,8 @@ * @file state_estimation.c * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SE * @@ -63,7 +63,9 @@ /*========== Macros and Definitions =========================================*/ /*========== Static Constant and Variable Definitions =======================*/ -static DATA_BLOCK_SOX_s se_tableSocAndSoeEstimation = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s se_tableSocEstimation = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOH_s se_tableSohEstimation = {.header.uniqueId = DATA_BLOCK_ID_SOH}; +static DATA_BLOCK_SOE_s se_tableSoeEstimation = {.header.uniqueId = DATA_BLOCK_ID_SOE}; /*========== Extern Constant and Variable Definitions =======================*/ @@ -74,28 +76,28 @@ static DATA_BLOCK_SOX_s se_tableSocAndSoeEstimation = {.header.uniqueId = DATA_B /*========== Extern Function Implementations ================================*/ extern void SE_InitializeSoc(bool ccPresent, uint8_t stringNumber) { FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); - SE_InitializeStateOfCharge(&se_tableSocAndSoeEstimation, ccPresent, stringNumber); - DATA_WRITE_DATA(&se_tableSocAndSoeEstimation); + SE_InitializeStateOfCharge(&se_tableSocEstimation, ccPresent, stringNumber); + DATA_WRITE_DATA(&se_tableSocEstimation); } extern void SE_InitializeSoe(bool ec_present, uint8_t stringNumber) { FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); - SE_InitializeStateOfEnergy(&se_tableSocAndSoeEstimation, ec_present, stringNumber); - DATA_WRITE_DATA(&se_tableSocAndSoeEstimation); + SE_InitializeStateOfEnergy(&se_tableSoeEstimation, ec_present, stringNumber); + DATA_WRITE_DATA(&se_tableSoeEstimation); } extern void SE_InitializeSoh(uint8_t stringNumber) { FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS); - SE_InitializeStateOfHealth(&se_tableSocAndSoeEstimation, stringNumber); - DATA_WRITE_DATA(&se_tableSocAndSoeEstimation); + SE_InitializeStateOfHealth(&se_tableSohEstimation, stringNumber); + DATA_WRITE_DATA(&se_tableSohEstimation); } extern void SE_RunStateEstimations(void) { - SE_CalculateStateOfCharge(&se_tableSocAndSoeEstimation); - SE_CalculateStateOfEnergy(&se_tableSocAndSoeEstimation); - SE_CalculateStateOfHealth(&se_tableSocAndSoeEstimation); + SE_CalculateStateOfCharge(&se_tableSocEstimation); + SE_CalculateStateOfEnergy(&se_tableSoeEstimation); + SE_CalculateStateOfHealth(&se_tableSohEstimation); - DATA_WRITE_DATA(&se_tableSocAndSoeEstimation); + DATA_WRITE_DATA(&se_tableSocEstimation, &se_tableSohEstimation, &se_tableSoeEstimation); } /*========== Externalized Static Function Implementations (Unit Test) =======*/ diff --git a/src/app/application/algorithm/state_estimation/state_estimation.h b/src/app/application/algorithm/state_estimation/state_estimation.h index ff125cdd..7e40afc2 100644 --- a/src/app/application/algorithm/state_estimation/state_estimation.h +++ b/src/app/application/algorithm/state_estimation/state_estimation.h @@ -43,8 +43,8 @@ * @file state_estimation.h * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SE * @@ -108,13 +108,13 @@ extern void SE_RunStateEstimations(void); * @param[in] ccPresent true if current sensor present, false otherwise * @param[in] stringNumber string addressed */ -extern void SE_InitializeStateOfCharge(DATA_BLOCK_SOX_s *pSocValues, bool ccPresent, uint8_t stringNumber); +extern void SE_InitializeStateOfCharge(DATA_BLOCK_SOC_s *pSocValues, bool ccPresent, uint8_t stringNumber); /** * @brief periodically called algorithm to calculate state-of-charge (SOC) * @param[out] pSocValues pointer to SOC values */ -extern void SE_CalculateStateOfCharge(DATA_BLOCK_SOX_s *pSocValues); +extern void SE_CalculateStateOfCharge(DATA_BLOCK_SOC_s *pSocValues); /** * @brief look-up table for SOC initialization @@ -129,26 +129,26 @@ extern float_t SE_GetStateOfChargeFromVoltage(int16_t voltage_mV); * @param[in] ec_present true if current sensor EC message received, false otherwise * @param[in] stringNumber string addressed */ -extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues, bool ec_present, uint8_t stringNumber); +extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues, bool ec_present, uint8_t stringNumber); /** * @brief periodically called algorithm to calculate state-of-energy (SOE) * @param[out] pSoeValues pointer to SOE database entry */ -extern void SE_CalculateStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues); +extern void SE_CalculateStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues); /** * @brief initializes startup state-of-health related values * @param[out] pSohValues pointer to SOH database entry * @param[in] stringNumber string addressed */ -extern void SE_InitializeStateOfHealth(DATA_BLOCK_SOX_s *pSohValues, uint8_t stringNumber); +extern void SE_InitializeStateOfHealth(DATA_BLOCK_SOH_s *pSohValues, uint8_t stringNumber); /** * @brief calculates state-of-health (SOH) * @param[out] pSohValues pointer to SOH database entry */ -extern void SE_CalculateStateOfHealth(DATA_BLOCK_SOX_s *pSohValues); +extern void SE_CalculateStateOfHealth(DATA_BLOCK_SOH_s *pSohValues); /** INCLUDE MARKER FOR THE DOCUMENTATION; DO NOT MOVE se-state-estimation-api-stop-include * @} diff --git a/src/app/application/algorithm/wscript b/src/app/application/algorithm/wscript index ac6f87f5..eb248226 100644 --- a/src/app/application/algorithm/wscript +++ b/src/app/application/algorithm/wscript @@ -53,15 +53,12 @@ def build(bld): os.path.join("algorithm.c"), os.path.join("config", "algorithm_cfg.c"), os.path.join("moving_average", "moving_average.c"), - os.path.join("state_estimation", "soc", soc, f"soc_{soc}_cfg.c"), os.path.join("state_estimation", "soc", soc, f"soc_{soc}.c"), - os.path.join("state_estimation", "soe", soe, f"soe_{soe}_cfg.c"), os.path.join("state_estimation", "soe", soe, f"soe_{soe}.c"), os.path.join("state_estimation", "sof", sof, f"sof_{sof}.c"), os.path.join("state_estimation", "sof", sof, f"sof_{sof}_cfg.c"), os.path.join("state_estimation", "soh", soh, f"soh_{soh}.c"), - os.path.join("state_estimation", "soh", soh, f"soh_{soh}_cfg.c"), - os.path.join(".", "state_estimation", "state_estimation.c"), + os.path.join("state_estimation", "state_estimation.c"), ] includes = [ ".", diff --git a/src/app/application/bal/bal.c b/src/app/application/bal/bal.c index 5fdcbafd..ca5366b1 100644 --- a/src/app/application/bal/bal.c +++ b/src/app/application/bal/bal.c @@ -43,8 +43,8 @@ * @file bal.c * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix BAL * diff --git a/src/app/application/bal/bal.h b/src/app/application/bal/bal.h index 56dad729..3c41cf18 100644 --- a/src/app/application/bal/bal.h +++ b/src/app/application/bal/bal.h @@ -43,8 +43,8 @@ * @file bal.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix BAL * @@ -97,7 +97,7 @@ typedef enum { } BAL_STATEMACH_SUB_e; /** - * State requests for the BAL statemachine + * State requests for the BAL state machine */ typedef enum { BAL_STATE_INIT_REQUEST, /*!< */ @@ -106,11 +106,11 @@ typedef enum { BAL_STATE_ALLOWBALANCING_REQUEST, /*!< */ BAL_STATE_GLOBAL_DISABLE_REQUEST, /*!< */ BAL_STATE_GLOBAL_ENABLE_REQUEST, /*!< */ - BAL_STATE_NO_REQUEST, /*!< default state: no request to the statemachine */ + BAL_STATE_NO_REQUEST, /*!< default state: no request to the state machine */ } BAL_STATE_REQUEST_e; /** - * Possible return values when state requests are made to the BAL statemachine + * Possible return values when state requests are made to the BAL state machine */ typedef enum { BAL_OK, /*!< BAL --> ok */ @@ -137,7 +137,7 @@ typedef struct { uint8_t lastSubstate; /*!< previous substate of the state machine */ uint8_t triggerEntry; /*!< counter for re-entrance protection (function running flag) */ uint32_t errorRequestCounter; /*!< counts the number of illegal requests to the BAL state machine */ - STD_RETURN_TYPE_e initializationFinished; /*!< #STD_OK if statemachine initialized, otherwise #STD_NOT_OK */ + STD_RETURN_TYPE_e initializationFinished; /*!< #STD_OK if state machine initialized, otherwise #STD_NOT_OK */ bool active; /*!< indicate if balancing active or not */ int32_t balancingThreshold; /*!< effective balancing threshold */ bool balancingAllowed; /*!< flag to disable balancing */ diff --git a/src/app/application/bal/history/bal_strategy_history.c b/src/app/application/bal/history/bal_strategy_history.c index 7d9de85f..8c51cf01 100644 --- a/src/app/application/bal/history/bal_strategy_history.c +++ b/src/app/application/bal/history/bal_strategy_history.c @@ -43,8 +43,8 @@ * @file bal_strategy_history.c * @author foxBMS Team * @date 2020-05-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix BAL * @@ -53,10 +53,9 @@ */ /*========== Includes =======================================================*/ -#include "bal_strategy_history.h" - #include "battery_cell_cfg.h" +#include "bal.h" #include "bms.h" #include "database.h" #include "os.h" @@ -131,16 +130,17 @@ static void BAL_ActivateBalancing(void) { for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { uint16_t nrBalancedCells = 0u; - for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_STRING; c++) { + for (uint16_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_STRING; c++) { if (bal_state.balancingAllowed == false) { bal_balancing.balancingState[s][c] = 0; } else { if (bal_balancing.deltaCharge_mAs[s][c] > 0) { bal_balancing.balancingState[s][c] = 1; nrBalancedCells++; - cellBalancingCurrent = ((float_t)(bal_cellVoltage.cellVoltage_mV[s][c])) / + uint8_t moduleNumber = c / BS_NR_OF_CELL_BLOCKS_PER_MODULE; + cellBalancingCurrent = ((float_t)(bal_cellVoltage.cellVoltage_mV[s][moduleNumber][c])) / BS_BALANCING_RESISTANCE_ohm; - difference = (BAL_STATEMACH_BALANCINGTIME_100ms / 10) * (uint32_t)(cellBalancingCurrent); + difference = (BAL_STATEMACH_BALANCINGTIME_100ms / 10u) * (uint32_t)(cellBalancingCurrent); bal_state.active = true; bal_balancing.enableBalancing = 1; /* we are working with unsigned integers */ @@ -268,38 +268,50 @@ static bool BAL_CheckImbalances(void) { } static void BAL_ComputeImbalances(void) { - uint16_t voltageMin = 0; - uint16_t minVoltageIndex = 0; - float_t SOC = 0.0f; - uint32_t DOD = 0; - uint32_t maxDOD = 0; + int16_t voltageMin_mV = 0; + uint16_t minVoltageModuleIndex = 0; + uint16_t minVoltageModuleCellBlockIndex = 0; + float_t SOC = 0.0f; + uint32_t DOD = 0; + uint32_t maxDOD = 0; DATA_READ_DATA(&bal_balancing, &bal_cellVoltage); for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { - voltageMin = bal_cellVoltage.cellVoltage_mV[s][0]; - minVoltageIndex = 0; - - for (uint16_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_STRING; c++) { - if (bal_cellVoltage.cellVoltage_mV[s][c] <= voltageMin) { - voltageMin = bal_cellVoltage.cellVoltage_mV[s][c]; - minVoltageIndex = c; + /* Assign first cell voltage to*/ + voltageMin_mV = INT16_MAX; + minVoltageModuleIndex = 0u; + minVoltageModuleCellBlockIndex = 0u; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint16_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + if (bal_cellVoltage.cellVoltage_mV[s][m][cb] <= voltageMin_mV) { + voltageMin_mV = bal_cellVoltage.cellVoltage_mV[s][m][cb]; + minVoltageModuleIndex = m; + minVoltageModuleCellBlockIndex = cb; + } } } - SOC = SE_GetStateOfChargeFromVoltage(((float_t)(bal_cellVoltage.cellVoltage_mV[s][minVoltageIndex])) / 1000.0f); - maxDOD = BC_CAPACITY_mAh * (uint32_t)((1.0f - SOC) * 3600.0f); - bal_balancing.deltaCharge_mAs[s][minVoltageIndex] = 0; + SOC = SE_GetStateOfChargeFromVoltage( + ((float_t)(bal_cellVoltage.cellVoltage_mV[s][minVoltageModuleIndex][minVoltageModuleCellBlockIndex])) / + 1000.0f); + maxDOD = BC_CAPACITY_mAh * (uint32_t)((1.0f - SOC) * 3600.0f); + bal_balancing.deltaCharge_mAs[s] + [(minVoltageModuleIndex * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + + minVoltageModuleCellBlockIndex] = 0u; /* update balancing threshold */ bal_state.balancingThreshold = BAL_GetBalancingThreshold_mV() + BAL_HYSTERESIS_mV; - for (uint16_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_STRING; c++) { - if (c != minVoltageIndex) { - if (bal_cellVoltage.cellVoltage_mV[s][c] >= (voltageMin + bal_state.balancingThreshold)) { - SOC = SE_GetStateOfChargeFromVoltage(((float_t)(bal_cellVoltage.cellVoltage_mV[s][c])) / 1000.0f); - DOD = BC_CAPACITY_mAh * (uint32_t)((1.0f - SOC) * 3600.0f); - bal_balancing.deltaCharge_mAs[s][c] = (maxDOD - DOD); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint16_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + if ((m != minVoltageModuleIndex) || (cb != minVoltageModuleCellBlockIndex)) { + if (bal_cellVoltage.cellVoltage_mV[s][m][cb] >= (voltageMin_mV + bal_state.balancingThreshold)) { + SOC = SE_GetStateOfChargeFromVoltage( + ((float_t)(bal_cellVoltage.cellVoltage_mV[s][m][cb])) / 1000.0f); + DOD = BC_CAPACITY_mAh * (uint32_t)((1.0f - SOC) * 3600.0f); + bal_balancing.deltaCharge_mAs[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + cb] = (maxDOD - DOD); + } } } } diff --git a/src/app/application/bal/history/bal_strategy_history.h b/src/app/application/bal/history/bal_strategy_history.h deleted file mode 100644 index 35727ed4..00000000 --- a/src/app/application/bal/history/bal_strategy_history.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file bal_strategy_history.h - * @author foxBMS Team - * @date 2020-05-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix BALS - * - * @brief Header for the history-based balancing strategy module - * - */ - -#ifndef FOXBMS__BAL_STRATEGY_HISTORY_H_ -#define FOXBMS__BAL_STRATEGY_HISTORY_H_ - -/*========== Includes =======================================================*/ -#include "bal.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__BAL_STRATEGY_HISTORY_H_ */ diff --git a/src/app/application/bal/none/bal_strategy_none.c b/src/app/application/bal/none/bal_strategy_none.c index 299602f0..b4e2a602 100644 --- a/src/app/application/bal/none/bal_strategy_none.c +++ b/src/app/application/bal/none/bal_strategy_none.c @@ -43,8 +43,8 @@ * @file bal_strategy_none.c * @author foxBMS Team * @date 2020-07-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix BAL * diff --git a/src/app/application/bal/none/bal_strategy_none.h b/src/app/application/bal/none/bal_strategy_none.h deleted file mode 100644 index 2c08fd15..00000000 --- a/src/app/application/bal/none/bal_strategy_none.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file bal_strategy_none.h - * @author foxBMS Team - * @date 2020-08-03 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix BALS - * - * @brief Header for the voltage-based balancing strategy module - * - */ - -#ifndef FOXBMS__BAL_STRATEGY_NONE_H_ -#define FOXBMS__BAL_STRATEGY_NONE_H_ - -/*========== Includes =======================================================*/ -#include "bal.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__BAL_STRATEGY_NONE_H_ */ diff --git a/src/app/application/bal/voltage/bal_strategy_voltage.c b/src/app/application/bal/voltage/bal_strategy_voltage.c index 306273fd..954ed683 100644 --- a/src/app/application/bal/voltage/bal_strategy_voltage.c +++ b/src/app/application/bal/voltage/bal_strategy_voltage.c @@ -43,8 +43,8 @@ * @file bal_strategy_voltage.c * @author foxBMS Team * @date 2020-05-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix BAL * @@ -131,17 +131,19 @@ static bool BAL_ActivateBalancing(void) { for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { int16_t min = minMax.minimumCellVoltage_mV[s]; uint16_t nrBalancedCells = 0u; - for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_STRING; c++) { - if (cellVoltage.cellVoltage_mV[s][c] > (min + bal_state.balancingThreshold)) { - bal_balancing.balancingState[s][c] = 1; - finished = false; - /* set without hysteresis so that we now balance all cells that are below the initial threshold */ - bal_state.balancingThreshold = BAL_GetBalancingThreshold_mV(); - bal_state.active = true; - bal_balancing.enableBalancing = 1; - nrBalancedCells++; - } else { - bal_balancing.balancingState[s][c] = 0; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + if (cellVoltage.cellVoltage_mV[s][m][cb] > (min + bal_state.balancingThreshold)) { + bal_balancing.balancingState[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + cb] = 1u; + finished = false; + /* set without hysteresis so that we now balance all cells that are below the initial threshold */ + bal_state.balancingThreshold = BAL_GetBalancingThreshold_mV(); + bal_state.active = true; + bal_balancing.enableBalancing = 1; + nrBalancedCells++; + } else { + bal_balancing.balancingState[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + cb] = 0; + } } } bal_balancing.nrBalancedCells[s] = nrBalancedCells; diff --git a/src/app/application/bal/voltage/bal_strategy_voltage.h b/src/app/application/bal/voltage/bal_strategy_voltage.h index b6357ba5..2db6fad6 100644 --- a/src/app/application/bal/voltage/bal_strategy_voltage.h +++ b/src/app/application/bal/voltage/bal_strategy_voltage.h @@ -43,8 +43,8 @@ * @file bal_strategy_voltage.h * @author foxBMS Team * @date 2020-05-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix BALS * diff --git a/src/app/application/bms/bms.c b/src/app/application/bms/bms.c index 7cf6e066..a4238baf 100644 --- a/src/app/application/bms/bms.c +++ b/src/app/application/bms/bms.c @@ -43,8 +43,8 @@ * @file bms.c * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix BMS * @@ -98,7 +98,7 @@ static BMS_STATE_s bms_state = { .initFinished = STD_NOT_OK, .counter = 0u, .OscillationTimeout = 0u, - .PrechargeTryCounter = 0u, + .prechargeTryCounter = 0u, .powerPath = BMS_POWER_PATH_OPEN, .closedStrings = {0u}, .closedPrechargeContactors = {0u}, @@ -481,7 +481,7 @@ static STD_RETURN_TYPE_e BMS_IsBatterySystemStateOkay(void) { } /* Check if delay from a new error is shorter then active delay from - * previously detected error in BMS statemachine */ + * previously detected error in BMS state machine */ if (bms_state.remainingDelay_ms >= bms_state.minimumActiveDelay_ms) { bms_state.remainingDelay_ms = bms_state.minimumActiveDelay_ms; } @@ -496,7 +496,7 @@ static STD_RETURN_TYPE_e BMS_IsBatterySystemStateOkay(void) { /** Set previous timestamp for next call */ previousTimestamp = timestamp; - /* Check if bms statemachine should switch to error state. This is the case + /* Check if bms state machine should switch to error state. This is the case * if the delay is activated and the remaining delay is down to 0 */ if ((bms_state.transitionToErrorState == true) && (bms_state.remainingDelay_ms == 0u)) { retVal = STD_NOT_OK; @@ -1182,7 +1182,8 @@ void BMS_Trigger(void) { bms_state.substate = BMS_ENTRY; break; } - bms_state.firstClosedString = stringNumber; + bms_state.prechargeTryCounter = 0u; + bms_state.firstClosedString = stringNumber; if (bms_state.OscillationTimeout == 0u) { /* Close MINUS string contactor */ if (CONT_CloseContactor(bms_state.firstClosedString, CONT_MINUS) == STD_OK) { @@ -1213,9 +1214,8 @@ void BMS_Trigger(void) { contRetVal = CONT_ClosePrecharge(bms_state.firstClosedString); bms_state.closedPrechargeContactors[stringNumber] = 1u; if (contRetVal == STD_OK) { - bms_state.timer = BMS_TIME_WAIT_AFTER_CLOSING_PRECHARGE; - bms_state.substate = BMS_CHECK_ERROR_FLAGS_CLOSINGPRECHARGE; - bms_state.PrechargeTryCounter = 0u; + bms_state.timer = BMS_TIME_WAIT_AFTER_CLOSING_PRECHARGE; + bms_state.substate = BMS_CHECK_ERROR_FLAGS_CLOSINGPRECHARGE; } else { bms_state.timer = BMS_STATEMACH_SHORTTIME; bms_state.state = BMS_STATEMACH_OPEN_CONTACTORS; @@ -1272,12 +1272,12 @@ void BMS_Trigger(void) { /* Precharging failed. Open precharge contactor. */ contRetVal = CONT_OpenPrecharge(bms_state.firstClosedString); /* Check if retry limit has been reached */ - if (bms_state.PrechargeTryCounter < (BMS_PRECHARGE_TRIES - 1u)) { + if (bms_state.prechargeTryCounter < (BMS_PRECHARGE_TRIES - 1u)) { bms_state.closedPrechargeContactors[stringNumber] = 0u; if (contRetVal == STD_OK) { bms_state.timer = BMS_TIME_WAIT_AFTERPRECHARGEFAIL; bms_state.substate = BMS_PRECHARGE_CLOSE_PRECHARGE; - bms_state.PrechargeTryCounter++; + bms_state.prechargeTryCounter++; } else { bms_state.timer = BMS_STATEMACH_SHORTTIME; bms_state.state = BMS_STATEMACH_OPEN_CONTACTORS; diff --git a/src/app/application/bms/bms.h b/src/app/application/bms/bms.h index 000ef11a..7ac8135a 100644 --- a/src/app/application/bms/bms.h +++ b/src/app/application/bms/bms.h @@ -43,8 +43,8 @@ * @file bms.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix BMS * @@ -200,7 +200,7 @@ typedef struct { BMS_CURRENT_FLOW_STATE_e currentFlowState; /*!< state of battery system */ uint32_t restTimer_10ms; /*!< timer until battery system is at rest */ uint16_t OscillationTimeout; /*!< timeout to prevent oscillation of contactors */ - uint8_t PrechargeTryCounter; /*!< timeout to prevent oscillation of contactors */ + uint8_t prechargeTryCounter; /*!< timeout to prevent oscillation of contactors */ BMS_POWER_PATH_TYPE_e powerPath; /*!< power path type (discharge or charge) */ uint8_t numberOfClosedStrings; /*!< number of closed strings */ uint16_t stringOpenTimeout; /*!< timeout to abort if string opening takes too long */ diff --git a/src/app/application/config/bal_cfg.c b/src/app/application/config/bal_cfg.c index 8c58901e..4f6e1679 100644 --- a/src/app/application/config/bal_cfg.c +++ b/src/app/application/config/bal_cfg.c @@ -43,8 +43,8 @@ * @file bal_cfg.c * @author foxBMS Team * @date 2022-02-26 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix BAL * diff --git a/src/app/application/config/bal_cfg.h b/src/app/application/config/bal_cfg.h index 833ddc5d..b3c4d1ee 100644 --- a/src/app/application/config/bal_cfg.h +++ b/src/app/application/config/bal_cfg.h @@ -43,8 +43,8 @@ * @file bal_cfg.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix BAL * @@ -61,14 +61,14 @@ /*========== Macros and Definitions =========================================*/ -/** BAL statemachine short time definition in 100*ms */ +/** BAL state machine short time definition in 100*ms */ #define BAL_STATEMACH_SHORTTIME_100ms (1u) -/** BAL statemachine long time definition in 100*ms */ +/** BAL state machine long time definition in 100*ms */ #define BAL_STATEMACH_LONGTIME_100ms (50u) -/** BAL statemachine balancing time in 100*ms */ +/** BAL state machine balancing time in 100*ms */ #define BAL_STATEMACH_BALANCINGTIME_100ms (10u) /** default value for the BAL voltage threshold */ diff --git a/src/app/application/config/battery_cell_cfg.c b/src/app/application/config/battery_cell_cfg.c index dd169740..b214fced 100644 --- a/src/app/application/config/battery_cell_cfg.c +++ b/src/app/application/config/battery_cell_cfg.c @@ -43,8 +43,8 @@ * @file battery_cell_cfg.c * @author foxBMS Team * @date 2020-10-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup BATTERY_CELL_CONFIGURATION * @prefix BC * diff --git a/src/app/application/config/battery_cell_cfg.h b/src/app/application/config/battery_cell_cfg.h index bc496d29..6f3b8ce8 100644 --- a/src/app/application/config/battery_cell_cfg.h +++ b/src/app/application/config/battery_cell_cfg.h @@ -43,8 +43,8 @@ * @file battery_cell_cfg.h * @author foxBMS Team * @date 2017-03-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup BATTERY_CELL_CONFIGURATION * @prefix BC * @@ -113,7 +113,7 @@ /**@}*/ /** - * @brief Minimum temperature limit during discharge. + * @brief Minimum temperature limit during charge. * @details When maximum safety limit (MSL) is violated, error state is * requested and contactors will open. When recommended safety limit * (RSL) or maximum operating limit (MOL) is violated, the respective diff --git a/src/app/application/config/battery_system_cfg.c b/src/app/application/config/battery_system_cfg.c index 5321aa94..42f8b928 100644 --- a/src/app/application/config/battery_system_cfg.c +++ b/src/app/application/config/battery_system_cfg.c @@ -43,8 +43,8 @@ * @file battery_system_cfg.c * @author foxBMS Team * @date 2019-12-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup BATTERY_SYSTEM_CONFIGURATION * @prefix BS * diff --git a/src/app/application/config/battery_system_cfg.h b/src/app/application/config/battery_system_cfg.h index d4637460..2177e7bd 100644 --- a/src/app/application/config/battery_system_cfg.h +++ b/src/app/application/config/battery_system_cfg.h @@ -43,8 +43,8 @@ * @file battery_system_cfg.h * @author foxBMS Team * @date 2019-12-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup BATTERY_SYSTEM_CONFIGURATION * @prefix BS * @@ -122,13 +122,12 @@ typedef enum { #define BS_NR_OF_CELL_BLOCKS_PER_MODULE (18u) /** - * @brief number of battery cells in a parallel cell connection per battery - * module + * @brief number of parallel connected battery cells in a cell block * @details For details see * Naming Conventions. * @ptype uint */ -#define BS_NR_OF_PARALLEL_CELLS_PER_MODULE (1u) +#define BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK (1u) /** Value of the balancing resistors on the slave-board */ #define BS_BALANCING_RESISTANCE_ohm (100.0) diff --git a/src/app/application/config/bms_cfg.h b/src/app/application/config/bms_cfg.h index 6f5a385a..1fb1868d 100644 --- a/src/app/application/config/bms_cfg.h +++ b/src/app/application/config/bms_cfg.h @@ -43,8 +43,8 @@ * @file bms_cfg.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE_CONFIGURATION * @prefix BMS * diff --git a/src/app/application/config/plausibility_cfg.h b/src/app/application/config/plausibility_cfg.h index 1cab36a2..ef280d0b 100644 --- a/src/app/application/config/plausibility_cfg.h +++ b/src/app/application/config/plausibility_cfg.h @@ -43,8 +43,8 @@ * @file plausibility_cfg.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION_CONFIGURATION * @prefix PL * diff --git a/src/app/application/config/soa_cfg.c b/src/app/application/config/soa_cfg.c index 3f479b8f..1876994e 100644 --- a/src/app/application/config/soa_cfg.c +++ b/src/app/application/config/soa_cfg.c @@ -43,8 +43,8 @@ * @file soa_cfg.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION_CONFIGURATION * @prefix SOA * @@ -98,11 +98,11 @@ bool SOA_IsCellCurrentLimitViolated(uint32_t current_mA, BMS_CURRENT_FLOW_STATE_ bool currentLimitViolated = false; /* Only check if battery is not at rest. No overcurrent possible if battery is resting */ if (currentDirection == BMS_CHARGING) { - if (current_mA > (BS_NR_OF_PARALLEL_CELLS_PER_MODULE * BC_CURRENT_MAX_CHARGE_MSL_mA)) { + if (current_mA > (BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK * BC_CURRENT_MAX_CHARGE_MSL_mA)) { currentLimitViolated = true; } } else if (currentDirection == BMS_DISCHARGING) { - if (current_mA > (BS_NR_OF_PARALLEL_CELLS_PER_MODULE * BC_CURRENT_MAX_DISCHARGE_MSL_mA)) { + if (current_mA > (BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK * BC_CURRENT_MAX_DISCHARGE_MSL_mA)) { currentLimitViolated = true; } } else { diff --git a/src/app/application/config/soa_cfg.h b/src/app/application/config/soa_cfg.h index 070b4897..97a10f36 100644 --- a/src/app/application/config/soa_cfg.h +++ b/src/app/application/config/soa_cfg.h @@ -43,8 +43,8 @@ * @file soa_cfg.h * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION_CONFIGURATION * @prefix SOA * diff --git a/src/app/application/plausibility/plausibility.c b/src/app/application/plausibility/plausibility.c index abd8768d..b5737c9b 100644 --- a/src/app/application/plausibility/plausibility.c +++ b/src/app/application/plausibility/plausibility.c @@ -43,8 +43,8 @@ * @file plausibility.c * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix PL * @@ -135,16 +135,16 @@ extern STD_RETURN_TYPE_e PL_CheckVoltageSpread( for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { STD_RETURN_TYPE_e plausibilityIssueDetected = STD_OK; for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { /* Only do check for valid voltages */ - if ((pCellVoltages->invalidCellVoltage[s][m] & (0x01u << c)) == 0) { - if (abs(pCellVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] - - pMinMaxAverageValues->averageCellVoltage_mV[s]) > PL_CELL_VOLTAGE_SPREAD_TOLERANCE_mV) { + if ((pCellVoltages->invalidCellVoltage[s][m] & (0x01uLL << cb)) == 0uLL) { + if (abs(pCellVoltages->cellVoltage_mV[s][m][cb] - pMinMaxAverageValues->averageCellVoltage_mV[s]) > + PL_CELL_VOLTAGE_SPREAD_TOLERANCE_mV) { /* Voltage difference too large */ plausibilityIssueDetected = STD_NOT_OK; retval = STD_NOT_OK; /* Set this cell voltage invalid */ - pCellVoltages->invalidCellVoltage[s][m] |= (0x01u << c); + pCellVoltages->invalidCellVoltage[s][m] |= (0x01u << cb); } } } @@ -167,17 +167,17 @@ extern STD_RETURN_TYPE_e PL_CheckTemperatureSpread( for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { STD_RETURN_TYPE_e plausibilityIssueDetected = STD_OK; for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { /* Only do check for valid temperatures */ - if ((pCellTemperatures->invalidCellTemperature[s][m] & (0x01u << c)) == 0) { - if (abs(pCellTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] - + if ((pCellTemperatures->invalidCellTemperature[s][m] & (0x01u << ts)) == 0) { + if (abs(pCellTemperatures->cellTemperature_ddegC[s][m][ts] - (int16_t)pMinMaxAverageValues->averageTemperature_ddegC[s]) > PL_CELL_TEMPERATURE_SPREAD_TOLERANCE_dK) { /* temperature difference too large */ plausibilityIssueDetected = STD_NOT_OK; retval = STD_NOT_OK; /* Set this cell temperature invalid */ - pCellTemperatures->invalidCellTemperature[s][m] |= (0x01u << c); + pCellTemperatures->invalidCellTemperature[s][m] |= (0x01u << ts); } else { pCellTemperatures->nrValidTemperatures[s]++; } diff --git a/src/app/application/plausibility/plausibility.h b/src/app/application/plausibility/plausibility.h index d5b01773..73fa1254 100644 --- a/src/app/application/plausibility/plausibility.h +++ b/src/app/application/plausibility/plausibility.h @@ -43,8 +43,8 @@ * @file plausibility.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix PL * diff --git a/src/app/application/redundancy/redundancy.c b/src/app/application/redundancy/redundancy.c index 012812d6..2a3d54a4 100644 --- a/src/app/application/redundancy/redundancy.c +++ b/src/app/application/redundancy/redundancy.c @@ -43,8 +43,8 @@ * @file redundancy.c * @author foxBMS Team * @date 2020-07-31 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix MRC * @@ -754,11 +754,11 @@ static void MRC_ValidatePowerMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurr if ((calculatePower == true) && (mrc_tablePackValues.invalidStringCurrent[s] == 0u) && (mrc_tablePackValues.invalidStringVoltage[s] == 0u)) { /* Power measurement is invalid, but current and string voltage measurement are valid */ - int64_t stringPower_W = - ((mrc_tablePackValues.stringCurrent_mA[s] * mrc_tablePackValues.stringVoltage_mV[s]) / - (UNIT_CONVERSION_FACTOR_1000_INTEGER * /* convert: mV -> V */ - UNIT_CONVERSION_FACTOR_1000_INTEGER)); /* convert: mA -> A */ - mrc_tablePackValues.stringPower_W[s] = (int32_t)stringPower_W; + const float_t stringCurrent_A = (float_t)mrc_tablePackValues.stringCurrent_mA[s] / + UNIT_CONVERSION_FACTOR_1000_FLOAT; + const float_t stringVoltage_V = (float_t)mrc_tablePackValues.stringVoltage_mV[s] / + UNIT_CONVERSION_FACTOR_1000_FLOAT; + mrc_tablePackValues.stringPower_W[s] = (int32_t)(stringCurrent_A * stringVoltage_V); mrc_tablePackValues.invalidStringPower[s] = 0u; } if (mrc_tablePackValues.invalidStringPower[s] == 0u) { @@ -794,21 +794,21 @@ static STD_RETURN_TYPE_e MRC_CalculateCellVoltageMinMaxAverage( uint16_t cellNumberMaximum = 0u; /* Iterate over all cells in each string */ for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { - if ((pValidatedVoltages->invalidCellVoltage[s][m] & (0x01u << c)) == 0u) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + if ((pValidatedVoltages->invalidCellVoltage[s][m] & (0x01u << cb)) == 0u) { /* Cell voltage is valid -> use this voltage for subsequent calculations */ nrValidCellVoltages++; - sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; + sum += pValidatedVoltages->cellVoltage_mV[s][m][cb]; - if (pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] < min) { - min = pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; + if (pValidatedVoltages->cellVoltage_mV[s][m][cb] < min) { + min = pValidatedVoltages->cellVoltage_mV[s][m][cb]; moduleNumberMinimum = m; - cellNumberMinimum = c; + cellNumberMinimum = cb; } - if (pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] > max) { - max = pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; + if (pValidatedVoltages->cellVoltage_mV[s][m][cb] > max) { + max = pValidatedVoltages->cellVoltage_mV[s][m][cb]; moduleNumberMaximum = m; - cellNumberMaximum = c; + cellNumberMaximum = cb; } } } @@ -852,26 +852,21 @@ static STD_RETURN_TYPE_e MRC_CalculateCellTemperatureMinMaxAverage( float_t sum_ddegC = 0.0f; for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) { - if ((pValidatedTemperatures->invalidCellTemperature[s][m] & (0x01u << c)) == 0u) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { + if ((pValidatedTemperatures->invalidCellTemperature[s][m] & (0x01u << ts)) == 0u) { /* Cell temperature is valid -> use this voltage for subsequent calculations */ nrValidCelltemperatures++; - sum_ddegC += (float_t)pValidatedTemperatures - ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c]; + sum_ddegC += (float_t)pValidatedTemperatures->cellTemperature_ddegC[s][m][ts]; - if (pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] < - min) { - min = pValidatedTemperatures - ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c]; + if (pValidatedTemperatures->cellTemperature_ddegC[s][m][ts] < min) { + min = pValidatedTemperatures->cellTemperature_ddegC[s][m][ts]; moduleNumberMinimum = m; - sensorNumberMinimum = c; + sensorNumberMinimum = ts; } - if (pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] > - max) { - max = pValidatedTemperatures - ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c]; + if (pValidatedTemperatures->cellTemperature_ddegC[s][m][ts] > max) { + max = pValidatedTemperatures->cellTemperature_ddegC[s][m][ts]; moduleNumberMaximum = m; - sensorNumberMaximum = c; + sensorNumberMaximum = ts; } } } @@ -884,7 +879,7 @@ static STD_RETURN_TYPE_e MRC_CalculateCellTemperatureMinMaxAverage( pMinMaxAverageValues->nrModuleMaximumTemperature[s] = moduleNumberMaximum; pMinMaxAverageValues->validMeasuredCellTemperatures[s] = nrValidCelltemperatures; - /* Prevent division by 0, if all cell voltages are invalid */ + /* Prevent division by 0, if all cell temperatures are invalid */ if (nrValidCelltemperatures > 0u) { pMinMaxAverageValues->averageTemperature_ddegC[s] = (sum_ddegC / (float_t)nrValidCelltemperatures); } else { @@ -912,54 +907,50 @@ static STD_RETURN_TYPE_e MRC_ValidateCellVoltage( for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { int32_t sum = 0; for (uint8_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { - if (((pCellVoltageBase->invalidCellVoltage[s][m] & (1u << c)) == 0u) && - ((pCellVoltageRedundancy0->invalidCellVoltage[s][m] & (1u << c)) == 0u)) { + for (uint8_t cb = 0; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + if (((pCellVoltageBase->invalidCellVoltage[s][m] & (1u << cb)) == 0u) && + ((pCellVoltageRedundancy0->invalidCellVoltage[s][m] & (1u << cb)) == 0u)) { /* Check if cell voltage of base AND redundant measurement is valid -> do plausibility check */ - if (STD_OK == - PL_CheckCellVoltage( - pCellVoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c], - pCellVoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c], - &pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c])) { + if (STD_OK == PL_CheckCellVoltage( + pCellVoltageBase->cellVoltage_mV[s][m][cb], + pCellVoltageRedundancy0->cellVoltage_mV[s][m][cb], + &pValidatedVoltages->cellVoltage_mV[s][m][cb])) { /* Clear valid flag */ pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] & - (~(1u << c)); + (~(1u << cb)); numberValidMeasurements++; - sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; + sum += pValidatedVoltages->cellVoltage_mV[s][m][cb]; } else { /* Set invalid flag */ noPlausibilityIssueDetected = STD_NOT_OK; - pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << c); + pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << cb); /* Set return value to #STD_NOT_OK as not all cell voltages have a valid measurement value */ retval = STD_NOT_OK; } - } else if ((pCellVoltageBase->invalidCellVoltage[s][m] & (1u << c)) == 0u) { + } else if ((pCellVoltageBase->invalidCellVoltage[s][m] & (1u << cb)) == 0u) { /* Only base measurement value is valid -> use this voltage without further plausibility checks */ - pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] = - pCellVoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; + pValidatedVoltages->cellVoltage_mV[s][m][cb] = pCellVoltageBase->cellVoltage_mV[s][m][cb]; /* Reset valid flag */ pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] & - (~(1u << c)); + (~(1u << cb)); numberValidMeasurements++; - sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; - } else if ((pCellVoltageRedundancy0->invalidCellVoltage[s][m] & (1u << c)) == 0u) { + sum += pValidatedVoltages->cellVoltage_mV[s][m][cb]; + } else if ((pCellVoltageRedundancy0->invalidCellVoltage[s][m] & (1u << cb)) == 0u) { /* Only redundant measurement value is valid -> use this voltage without further plausibility checks */ - pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] = - pCellVoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; + pValidatedVoltages->cellVoltage_mV[s][m][cb] = pCellVoltageRedundancy0->cellVoltage_mV[s][m][cb]; /* Reset valid flag */ pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] & - (~(1u << c)); + (~(1u << cb)); numberValidMeasurements++; - sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; + sum += pValidatedVoltages->cellVoltage_mV[s][m][cb]; } else { /* Both, base and redundant measurement value are invalid */ /* Save average cell voltage value of base and redundant */ - pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] = - (pCellVoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] + - pCellVoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]) / - 2u; + pValidatedVoltages->cellVoltage_mV[s][m][cb] = (pCellVoltageBase->cellVoltage_mV[s][m][cb] + + pCellVoltageRedundancy0->cellVoltage_mV[s][m][cb]) / + 2; /* Set invalid flag */ - pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << c); + pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << cb); /* Set return value to #STD_NOT_OK as not all cell voltages have a valid measurement value */ retval = STD_NOT_OK; } @@ -1008,55 +999,50 @@ static STD_RETURN_TYPE_e MRC_ValidateCellTemperature( /* Iterate over all cell measurements */ for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) { - if (((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << c)) == 0u) && - ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << c)) == 0u)) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { + if (((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << ts)) == 0u) && + ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << ts)) == 0u)) { /* Check if cell voltage of base AND redundant measurement is valid -> do plausibility check */ - if (STD_OK == - PL_CheckCelltemperature( - pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c], - pCelltemperatureRedundancy0 - ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c], - &pValidatedTemperatures - ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c])) { + if (STD_OK == PL_CheckCelltemperature( + pCelltemperatureBase->cellTemperature_ddegC[s][m][ts], + pCelltemperatureRedundancy0->cellTemperature_ddegC[s][m][ts], + &pValidatedTemperatures->cellTemperature_ddegC[s][m][ts])) { /* Clear valid flag */ pValidatedTemperatures->invalidCellTemperature[s][m] = - pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c)); + pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << ts)); numberValidMeasurements++; } else { /* Set invalid flag */ noPlausibilityIssueDetected = STD_NOT_OK; - pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << c); + pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << ts); /* Set return value to #STD_NOT_OK as not all cell temperatures have a valid measurement value */ retval = STD_NOT_OK; } - } else if ((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << c)) == 0u) { + } else if ((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << ts)) == 0u) { /* Only base measurement value is valid -> use this temperature without further plausibility checks */ - pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] = - pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c]; + pValidatedTemperatures->cellTemperature_ddegC[s][m][ts] = + pCelltemperatureBase->cellTemperature_ddegC[s][m][ts]; /* Reset valid flag */ pValidatedTemperatures->invalidCellTemperature[s][m] = - pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c)); + pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << ts)); numberValidMeasurements++; - } else if ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << c)) == 0u) { + } else if ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << ts)) == 0u) { /* Only redundant measurement value is valid -> use this temperature without further plausibility checks */ - pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] = - pCelltemperatureRedundancy0 - ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c]; + pValidatedTemperatures->cellTemperature_ddegC[s][m][ts] = + pCelltemperatureRedundancy0->cellTemperature_ddegC[s][m][ts]; /* Reset valid flag */ pValidatedTemperatures->invalidCellTemperature[s][m] = - pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c)); + pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << ts)); numberValidMeasurements++; } else { /* Both, base and redundant measurement value are invalid */ /* Save average cell voltage value of base and redundant */ - pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] = - (pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] + - pCelltemperatureRedundancy0 - ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c]) / + pValidatedTemperatures->cellTemperature_ddegC[s][m][ts] = + (pCelltemperatureBase->cellTemperature_ddegC[s][m][ts] + + pCelltemperatureRedundancy0->cellTemperature_ddegC[s][m][ts]) / 2u; /* Set invalid flag */ - pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << c); + pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << ts); /* Set return value to #STD_NOT_OK as not all cell temperatures have a valid measurement value */ retval = STD_NOT_OK; } @@ -1094,7 +1080,7 @@ extern STD_RETURN_TYPE_e MRC_Initialize(void) { for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { /* Invalidate cell voltage values */ - mrc_tableCellVoltages.invalidCellVoltage[s][m] = 0xFFFFFFFFFFFFFFFFULL; + mrc_tableCellVoltages.invalidCellVoltage[s][m] = 0xFFFFFFFFFFFFFFFFuLL; mrc_tableCellVoltages.validModuleVoltage[s][m] = false; /* Invalidate cell temperature values */ mrc_tableCellTemperatures.invalidCellTemperature[s][m] = 0xFFFF; diff --git a/src/app/application/redundancy/redundancy.h b/src/app/application/redundancy/redundancy.h index 2ad6781e..c79fb0a2 100644 --- a/src/app/application/redundancy/redundancy.h +++ b/src/app/application/redundancy/redundancy.h @@ -43,8 +43,8 @@ * @file redundancy.h * @author foxBMS Team * @date 2020-07-31 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix MRC * diff --git a/src/app/application/soa/soa.c b/src/app/application/soa/soa.c index 305e55d5..702865b9 100644 --- a/src/app/application/soa/soa.c +++ b/src/app/application/soa/soa.c @@ -43,8 +43,8 @@ * @file soa.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOA * diff --git a/src/app/application/soa/soa.h b/src/app/application/soa/soa.h index 0cc11993..efc5cc38 100644 --- a/src/app/application/soa/soa.h +++ b/src/app/application/soa/soa.h @@ -43,8 +43,8 @@ * @file soa.h * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix SOA * diff --git a/src/app/driver/adc/adc.c b/src/app/driver/adc/adc.c index 6c66f804..22e5112f 100644 --- a/src/app/driver/adc/adc.c +++ b/src/app/driver/adc/adc.c @@ -43,8 +43,8 @@ * @file adc.c * @author foxBMS Team * @date 2019-01-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix ADC * diff --git a/src/app/driver/adc/adc.h b/src/app/driver/adc/adc.h index 1f830ebc..fb0082ff 100644 --- a/src/app/driver/adc/adc.h +++ b/src/app/driver/adc/adc.h @@ -43,8 +43,8 @@ * @file adc.h * @author foxBMS Team * @date 2019-01-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix ADC * diff --git a/src/app/driver/afe/adi/ades1830/adi_ades1830.json b/src/app/driver/afe/adi/ades1830/adi_ades1830.json new file mode 100644 index 00000000..5428fc6b --- /dev/null +++ b/src/app/driver/afe/adi/ades1830/adi_ades1830.json @@ -0,0 +1,11 @@ +{ + "include": [ + ".", + "config", + "../common/ades183x", + "../common/ades183x/api", + "../common/ades183x/config", + "../common/ades183x/pec", + "../../api" + ] +} diff --git a/src/app/driver/afe/adi/ades1830/adi_ades1830_balancing.c b/src/app/driver/afe/adi/ades1830/adi_ades1830_balancing.c new file mode 100644 index 00000000..c4df14ee --- /dev/null +++ b/src/app/driver/afe/adi/ades1830/adi_ades1830_balancing.c @@ -0,0 +1,144 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades1830_balancing.c + * @author foxBMS Team + * @date 2019-08-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup SOME_GROUP + * @prefix ADI + * + * @brief Implementation of some software + * + */ + +/*========== Includes =======================================================*/ +/* clang-format off */ +#include "adi_ades183x_balancing.h" +/* clang-format on */ + +#include "adi_ades183x_cfg.h" + +#include "adi_ades183x_buffers.h" +#include "adi_ades183x_commands.h" +#include "adi_ades183x_defs.h" +#include "adi_ades183x_helpers.h" +#include "adi_ades183x_voltages.h" + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ +extern void ADI_DeactivateBalancing(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /* Deactivate balancing before sending unmute command */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + const uint16_t reverseModuleNumber = BS_NR_OF_MODULES_PER_STRING - m - 1u; + ADI_WriteDataBits( + &adi_configurationRegisterBgroup[adiState->currentString] + [(reverseModuleNumber * ADI_WRCFGB_LEN) + ADI_REGISTER_OFFSET4], + 0u, + ADI_CFGRB4_DCC_1_8_POS, + ADI_CFGRB4_DCC_1_8_MASK); + ADI_WriteDataBits( + &adi_configurationRegisterBgroup[adiState->currentString] + [(reverseModuleNumber * ADI_WRCFGB_LEN) + ADI_REGISTER_OFFSET5], + 0u, + ADI_CFGRB5_DCC_9_16_POS, + ADI_CFGRB5_DCC_9_16_MASK); + } + ADI_StoredConfigurationWriteToAfeGlobal(adiState); + /* Send Unmute command */ + ADI_CopyCommandBits(adi_cmdUnmute, adi_command); + ADI_TransmitCommand(adi_command, adiState); +} + +extern void ADI_DetermineBalancingRegisterConfiguration(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + uint16_t storedVoltageIndex = 0u; + + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + const uint16_t reverseModuleNumber = BS_NR_OF_MODULES_PER_STRING - m - 1u; + uint8_t dccRegisterLow = 0u; + uint8_t dccRegisterHigh = 0u; + for (uint8_t c = 0u; c < ADI_MAX_SUPPORTED_CELLS; c++) { + if (adi_voltageInputsUsed[c] == 1u) { + storedVoltageIndex = ADI_GetStoredVoltageIndex(c); + if (adiState->data.balancingControl + ->balancingState[adiState->currentString] + [(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE)) + storedVoltageIndex] == 1u) { + if (c < ADI_CFGRB_NUMBER_OF_DCC_BITS_PER_BYTE) { /* 0 - 7 cells */ + dccRegisterLow |= (uint8_t)(1u << c); + } else { /* 8 - 15 cells */ + dccRegisterHigh |= (uint8_t)(1u << (c - ADI_CFGRB_NUMBER_OF_DCC_BITS_PER_BYTE)); + } + } + } + } + ADI_WriteDataBits( + &adi_configurationRegisterBgroup[adiState->currentString] + [(reverseModuleNumber * ADI_WRCFGB_LEN) + ADI_REGISTER_OFFSET4], + dccRegisterLow, + ADI_CFGRB4_DCC_1_8_POS, + ADI_CFGRB4_DCC_1_8_MASK); + ADI_WriteDataBits( + &adi_configurationRegisterBgroup[adiState->currentString] + [(reverseModuleNumber * ADI_WRCFGB_LEN) + ADI_REGISTER_OFFSET5], + dccRegisterHigh, + ADI_CFGRB5_DCC_9_16_POS, + ADI_CFGRB5_DCC_9_16_MASK); + } + ADI_StoredConfigurationWriteToAfeGlobal(adiState); +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/driver/afe/debug/default/api/debug_default_afe.h b/src/app/driver/afe/adi/ades1830/adi_ades1830_defs.h similarity index 84% rename from src/app/driver/afe/debug/default/api/debug_default_afe.h rename to src/app/driver/afe/adi/ades1830/adi_ades1830_defs.h index be888403..768d828e 100644 --- a/src/app/driver/afe/debug/default/api/debug_default_afe.h +++ b/src/app/driver/afe/adi/ades1830/adi_ades1830_defs.h @@ -40,29 +40,28 @@ */ /** - * @file debug_default_afe.h + * @file adi_ades1830_defs.h * @author foxBMS Team - * @date 2020-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2015-09-01 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS - * @prefix FAKE + * @prefix ADI * - * @brief Header for the driver for the fake AFE driver + * @brief Headers for the driver for the ADES1830 analog front-end. * */ -#ifndef FOXBMS__DEBUG_DEFAULT_AFE_H_ -#define FOXBMS__DEBUG_DEFAULT_AFE_H_ +#ifndef FOXBMS__ADI_ADES1830_DEFS_H_ +#define FOXBMS__ADI_ADES1830_DEFS_H_ /*========== Includes =======================================================*/ -/* clang-format off */ -#include "afe.h" -/* clang-format on */ - -#include +#include /*========== Macros and Definitions =========================================*/ +#define ADI_MAX_SUPPORTED_CELLS (16u) +#define ADI_TOTAL_GPIO_NUMBER (10u) +#define ADI_HIGHEST_AUX_CHANNEL (10u) /*========== Extern Constant and Variable Declarations ======================*/ @@ -72,4 +71,4 @@ #ifdef UNITY_UNIT_TEST #endif -#endif /* FOXBMS__DEBUG_DEFAULT_AFE_H_ */ +#endif /* FOXBMS__ADI_ADES1830_DEFS_H_ */ diff --git a/src/app/driver/afe/adi/ades1830/adi_ades1830_gpio_voltages.c b/src/app/driver/afe/adi/ades1830/adi_ades1830_gpio_voltages.c new file mode 100644 index 00000000..41677245 --- /dev/null +++ b/src/app/driver/afe/adi/ades1830/adi_ades1830_gpio_voltages.c @@ -0,0 +1,263 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades1830_gpio_voltages.c + * @author foxBMS Team + * @date 2019-08-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup SOME_GROUP + * @prefix ADI + * + * @brief Implementation of some software + * + */ + +/*========== Includes =======================================================*/ +/* clang-format off */ +#include "adi_ades183x_gpio_voltages.h" +/* clang-format on */ + +#include "adi_ades183x_cfg.h" + +#include "adi_ades183x_buffers.h" +#include "adi_ades183x_commands.h" +#include "adi_ades183x_commands_voltages.h" +#include "adi_ades183x_defs.h" +#include "adi_ades183x_helpers.h" +#include "adi_ades183x_voltages.h" +#include "fassert.h" + +#include +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ +/** + * @brief Saves the GPIO voltage values read from the daisy-chain. + * @details There are up to 5 registers to read _(A, B, C, D, E) to get all + * GPIO voltages. + * This function is called to store the result from the transmission + * buffer to the appropriate location in the driver. + * @param adiState state of the ADI driver + * @param data receive buffer + * @param registerSet auxiliary register that was read (voltage register + * A, B, C or D). + * @param storeLocation location where read data has to be stored + */ +static void ADI_SaveRxToGpioVoltageBuffer( + ADI_STATE_s *adiState, + uint8_t *data, + uint8_t registerSet, + ADI_AUXILIARY_STORE_LOCATION_e storeLocation); + +/*========== Static Function Implementations ================================*/ +/* RequirementId: D7.1 V0R4 FUN-2.10.01.02 */ +static void ADI_SaveRxToGpioVoltageBuffer( + ADI_STATE_s *adiState, + uint8_t *data, + uint8_t registerSet, + ADI_AUXILIARY_STORE_LOCATION_e storeLocation) { + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(data != NULL_PTR); + FAS_ASSERT( + (registerSet == ADI_AUXILIARY_RESULT_REGISTER_SET_A) || (registerSet == ADI_AUXILIARY_RESULT_REGISTER_SET_B) || + (registerSet == ADI_AUXILIARY_RESULT_REGISTER_SET_C) || (registerSet == ADI_AUXILIARY_RESULT_REGISTER_SET_D) || + (registerSet == ADI_AUXILIARY_RESULT_REGISTER_SET_E)); + FAS_ASSERT( + (storeLocation == ADI_AUXILIARY_VOLTAGE) || (storeLocation == ADI_REDUNDANT_AUXILIARY_VOLTAGE) || + (storeLocation == ADI_AUXILIARY_VOLTAGE_OPEN_WIRE)); + + uint16_t cellOffset = 0u; + uint16_t voltageIndex = 0u; + uint16_t rawValue = 0u; + int16_t signedValue = 0; + float_t floatVoltage = 0.0f; + int16_t voltage = 0; + uint16_t bufferLSB = 0u; + uint16_t bufferMSB = 0u; + uint8_t numberOfVoltagesInRegister = 0u; + uint8_t voltageStartNumber = 0u; + DATA_BLOCK_ALL_GPIO_VOLTAGES_s *pGpioVoltageTable = NULL_PTR; + + switch (storeLocation) { + case ADI_AUXILIARY_VOLTAGE: + pGpioVoltageTable = adiState->data.allGpioVoltages; + break; + case ADI_REDUNDANT_AUXILIARY_VOLTAGE: + pGpioVoltageTable = adiState->data.allGpioVoltagesRedundant; + break; + case ADI_AUXILIARY_VOLTAGE_OPEN_WIRE: + pGpioVoltageTable = adiState->data.allGpioVoltageOpenWire; + break; + default: /* LCOV_EXCL_LINE */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } + + /* Default: 3 GPIO voltages in AUX registers */ + numberOfVoltagesInRegister = ADI_MAX_NUMBER_OF_GPIO_VOLTAGES_IN_REGISTER; + + switch (registerSet) { + case ADI_AUXILIARY_RESULT_REGISTER_SET_A: + /* RDAUXA command -> auxiliary register group A */ + cellOffset = ADI_VOLTAGE_00_02_OFFSET; + break; + case ADI_AUXILIARY_RESULT_REGISTER_SET_B: + /* RDAUXB command -> auxiliary register group B */ + cellOffset = ADI_VOLTAGE_03_05_OFFSET; + break; + case ADI_AUXILIARY_RESULT_REGISTER_SET_C: + /* RDAUXC command -> auxiliary register group C */ + cellOffset = ADI_VOLTAGE_06_08_OFFSET; + break; + case ADI_AUXILIARY_RESULT_REGISTER_SET_D: + /* RDAUXD command -> auxiliary register group D */ + cellOffset = ADI_VOLTAGE_09_11_OFFSET; + numberOfVoltagesInRegister = ADI_NUMBER_OF_GPIO_VOLTAGES_IN_REGISTER_D; + break; + default: /* LCOV_EXCL_LINE */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } + + for (uint16_t m = 0u; m < ADI_N_ADI; m++) { + /* parse voltages contained in one register */ + for (uint16_t gpio = voltageStartNumber; gpio < numberOfVoltagesInRegister; gpio++) { + voltageIndex = gpio + cellOffset; + if (voltageIndex < BS_NR_OF_GPIOS_PER_MODULE) { + bufferMSB = (uint16_t)(data + [(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * gpio) + + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES) + 1u]); + bufferLSB = + (uint16_t)(data[(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * gpio) + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)]); + rawValue = bufferLSB | (bufferMSB << ADI_BYTE_SHIFT); + signedValue = (int16_t)rawValue; + floatVoltage = ((float_t)signedValue * ADI_VOLTAGE_CONVERSION_FACTOR * ADI_VOLTAGE_CONVERSION_UNIT) + + ADI_VOLTAGE_CONVERSION_OFFSET; + voltage = (int16_t)floatVoltage; /* Unit mV */ + + /* RequirementId: D7.1 V0R4 SIF-4.40.02.01 */ + /* Check that register does not contain cleared value */ + if (rawValue != ADI_REGISTER_CLEARED_VALUE) { + adiState->data.errorTable->auxiliaryRegisterContentIsNotStuck[adiState->currentString][m] = true; + /* Check PEC for every IC in the daisy-chain */ + if (adiState->data.errorTable->crcIsOk[adiState->currentString][m] == true) { + pGpioVoltageTable->gpioVoltages_mV[adiState->currentString] + [voltageIndex + (m * BS_NR_OF_GPIOS_PER_MODULE)] = voltage; + } + } else { + adiState->data.errorTable->auxiliaryRegisterContentIsNotStuck[adiState->currentString][m] = false; + } + } + } + } +} + +/*========== Extern Function Implementations ================================*/ +extern void ADI_GetGpioVoltages( + ADI_STATE_s *adiState, + ADI_AUXILIARY_REGISTER_TYPE_e registerType, + ADI_AUXILIARY_STORE_LOCATION_e storeLocation) { + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT((registerType == ADI_AUXILIARY_REGISTER) || (registerType == ADI_REDUNDANT_AUXILIARY_REGISTER)); + FAS_ASSERT( + (storeLocation == ADI_AUXILIARY_VOLTAGE) || (storeLocation == ADI_REDUNDANT_AUXILIARY_VOLTAGE) || + (storeLocation == ADI_AUXILIARY_VOLTAGE_OPEN_WIRE)); + uint16_t registerA[ADI_COMMAND_DEFINITION_LENGTH] = {0}; + uint16_t registerB[ADI_COMMAND_DEFINITION_LENGTH] = {0}; + uint16_t registerC[ADI_COMMAND_DEFINITION_LENGTH] = {0}; + uint16_t registerD[ADI_COMMAND_DEFINITION_LENGTH] = {0}; + uint16_t registerE[ADI_COMMAND_DEFINITION_LENGTH] = {0}; + + switch (registerType) { + case ADI_AUXILIARY_REGISTER: + ADI_CopyCommandBits(adi_cmdRdauxa, registerA); + ADI_CopyCommandBits(adi_cmdRdauxb, registerB); + ADI_CopyCommandBits(adi_cmdRdauxc, registerC); + ADI_CopyCommandBits(adi_cmdRdauxd, registerD); + ADI_CopyCommandBits(adi_cmdRdauxe, registerE); + break; + case ADI_REDUNDANT_AUXILIARY_REGISTER: + ADI_CopyCommandBits(adi_cmdRdraxa, registerA); + ADI_CopyCommandBits(adi_cmdRdraxb, registerB); + ADI_CopyCommandBits(adi_cmdRdraxc, registerC); + ADI_CopyCommandBits(adi_cmdRdraxd, registerD); + break; + default: /* LCOV_EXCL_LINE */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } + + ADI_CopyCommandBits(registerA, adi_command); + ADI_ReadRegister(adi_command, adi_dataReceive, adiState); + ADI_SaveRxToGpioVoltageBuffer(adiState, adi_dataReceive, ADI_AUXILIARY_RESULT_REGISTER_SET_A, storeLocation); + + ADI_CopyCommandBits(registerB, adi_command); + ADI_ReadRegister(adi_command, adi_dataReceive, adiState); + ADI_SaveRxToGpioVoltageBuffer(adiState, adi_dataReceive, ADI_AUXILIARY_RESULT_REGISTER_SET_B, storeLocation); + + ADI_CopyCommandBits(registerC, adi_command); + ADI_ReadRegister(adi_command, adi_dataReceive, adiState); + ADI_SaveRxToGpioVoltageBuffer(adiState, adi_dataReceive, ADI_AUXILIARY_RESULT_REGISTER_SET_C, storeLocation); + + ADI_CopyCommandBits(registerD, adi_command); + ADI_ReadRegister(adi_command, adi_dataReceive, adiState); + ADI_SaveRxToGpioVoltageBuffer(adiState, adi_dataReceive, ADI_AUXILIARY_RESULT_REGISTER_SET_D, storeLocation); +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_ADI_SaveRxToGpioVoltageBuffer( + ADI_STATE_s *adiState, + uint8_t *data, + uint8_t registerSet, + ADI_AUXILIARY_STORE_LOCATION_e storeLocation) { + ADI_SaveRxToGpioVoltageBuffer(adiState, data, registerSet, storeLocation); +} +#endif diff --git a/src/app/driver/afe/ltc/common/config/ltc_afe_dma_cfg.c b/src/app/driver/afe/adi/ades1830/config/adi_ades1830_cfg.c similarity index 83% rename from src/app/driver/afe/ltc/common/config/ltc_afe_dma_cfg.c rename to src/app/driver/afe/adi/ades1830/config/adi_ades1830_cfg.c index 1527cb80..b953d82b 100644 --- a/src/app/driver/afe/ltc/common/config/ltc_afe_dma_cfg.c +++ b/src/app/driver/afe/adi/ades1830/config/adi_ades1830_cfg.c @@ -40,20 +40,20 @@ */ /** - * @file ltc_afe_dma_cfg.c + * @file adi_ades1830_cfg.c * @author foxBMS Team - * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2020-12-09 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION - * @prefix DMA + * @prefix ADI * - * @brief Configuration for the DMA module + * @brief Configuration for the ADI analog front-end * */ /*========== Includes =======================================================*/ -#include "ltc_afe_dma_cfg.h" +#include "adi_ades183x_cfg.h" #include @@ -62,6 +62,37 @@ /*========== Static Constant and Variable Definitions =======================*/ /*========== Extern Constant and Variable Definitions =======================*/ +const uint8_t adi_voltageInputsUsed[ADI_MAX_SUPPORTED_CELLS] = { + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; + +const uint8_t adi_temperatureInputsUsed[BS_NR_OF_GPIOS_PER_MODULE] = { + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; /*========== Static Function Prototypes =====================================*/ @@ -70,5 +101,3 @@ /*========== Extern Function Implementations ================================*/ /*========== Externalized Static Function Implementations (Unit Test) =======*/ -#ifdef UNITY_UNIT_TEST -#endif diff --git a/src/app/driver/afe/adi/ades1830/wscript b/src/app/driver/afe/adi/ades1830/wscript new file mode 100644 index 00000000..e4c91cbf --- /dev/null +++ b/src/app/driver/afe/adi/ades1830/wscript @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Builds the AFE measurement library for the ADI ADES1830 device""" + +import os + + +def build(bld): + """builds the AFE driver library for ADI ADES1830""" + bld.recurse(os.path.join("..", "common", "ades183x")) + source = [ + "adi_ades1830_balancing.c", + "adi_ades1830_gpio_voltages.c", + os.path.join("config", "adi_ades1830_cfg.c"), + ] + + # only build the diagnostics objects when these are available + diagnostics = os.path.join("..", "common", "ades183x", "adi_ades183x_diagnostic.c") + if bld.path.find_node(diagnostics): + bld.recurse("diag") + includes = [ + os.path.join("..", "..", "..", "config"), + os.path.join("..", "..", "..", "mcu"), + os.path.join("..", "..", "..", "pex"), + os.path.join("..", "..", "..", "rtc"), + os.path.join("..", "..", "..", "spi"), + os.path.join("..", "..", "..", "ts"), + os.path.join("..", "..", "..", "ts", "api"), + os.path.join("..", "..", "..", "..", "application", "config"), + os.path.join("..", "..", "..", "..", "engine", "config"), + os.path.join("..", "..", "..", "..", "engine", "database"), + os.path.join("..", "..", "..", "..", "engine", "diag"), + os.path.join("..", "..", "..", "..", "main", "include"), + os.path.join("..", "..", "..", "..", "task", "config"), + os.path.join("..", "..", "..", "..", "task", "ftask"), + os.path.join("..", "..", "..", "..", "task", "os"), + ] + includes.extend(bld.env.INCLUDES_AFE) + includes.extend(bld.env.INCLUDES_RTOS) + cflags = bld.env.CFLAGS_FOXBMS + target = f"{bld.env.APPNAME.lower()}-afe-driver" + bld.stlib( + source=source, + includes=includes, + cflags=cflags, + use=[ + f"{bld.env.APPNAME.lower()}-afe-driver-adi-ades183x-common", + # not existing names in 'use' are ignored + f"{bld.env.APPNAME.lower()}-afe-driver-adi-ades1830-diag-objects", + f"{bld.env.APPNAME.lower()}-afe-driver-adi-ades183x-diag-objects", + ], + target=target, + ) diff --git a/src/app/driver/afe/adi/api/README.md b/src/app/driver/afe/adi/api/README.md new file mode 100644 index 00000000..0b0f68c0 --- /dev/null +++ b/src/app/driver/afe/adi/api/README.md @@ -0,0 +1,4 @@ +# ADI API + +This is a dummy file in order to add the directory to git. This README.md can +be deleted as soon as ADI API headers are committed in this directory deleted. diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x.c b/src/app/driver/afe/adi/common/ades183x/adi_ades183x.c new file mode 100644 index 00000000..70354abf --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x.c @@ -0,0 +1,418 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x.c + * @author foxBMS Team + * @date 2020-12-09 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Driver for the ADI analog front-end. + * + */ + +/*========== Includes =======================================================*/ +/* clang-format off */ +#include "adi_ades183x.h" +/* clang-format on */ + +#include "adi_ades183x_balancing.h" +#include "adi_ades183x_buffers.h" +#include "adi_ades183x_commands.h" +#include "adi_ades183x_diagnostic.h" +#include "adi_ades183x_gpio_voltages.h" +#include "adi_ades183x_helpers.h" +#include "adi_ades183x_initialization.h" +#include "adi_ades183x_pec.h" +#include "adi_ades183x_temperatures.h" +#include "adi_ades183x_voltages.h" +#include "database.h" +#include "ftask.h" +#include "infinite-loop-helper.h" +#include "os.h" +#include "pex.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ +/** + * PEC buffer for RX and TX + * @{ + */ +#pragma SET_DATA_SECTION(".sharedRAM") +static uint16_t adi_bufferRxPec[ADI_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; +static uint16_t adi_bufferTxPec[ADI_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; +#pragma SET_DATA_SECTION() +/**@}*/ + +/** local copies of database tables */ +/**@{*/ +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltage = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageAverage = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageFiltered = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageRedundant = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_TEMPERATURE_s adi_cellTemperature = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE_BASE}; +static DATA_BLOCK_BALANCING_CONTROL_s adi_balancingControl = {.header.uniqueId = DATA_BLOCK_ID_BALANCING_CONTROL}; +static DATA_BLOCK_ALL_GPIO_VOLTAGES_s adi_allGpioVoltage = {.header.uniqueId = DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE}; +static DATA_BLOCK_ALL_GPIO_VOLTAGES_s adi_allGpioVoltageRedundant = { + .header.uniqueId = DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageOpenWireEven = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageOpenWireOdd = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageAverageOpenWire = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageRedundantOpenWire = { + .header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_ALL_GPIO_VOLTAGES_s adi_allGpioVoltageOpenWire = { + .header.uniqueId = DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE}; +static DATA_BLOCK_OPEN_WIRE_s adi_openWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static ADI_ERROR_TABLE_s adi_errorTable = {0}; /*!< init in ADI_ResetErrorTable-function */ +/**@}*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +ADI_STATE_s adi_stateBase = { + .measurementStarted = false, + .firstMeasurementMade = false, + .firstDiagnosticMade = false, + .currentString = 0u, + .redundantAuxiliaryChannel = {0u}, + .data.txBuffer = adi_bufferTxPec, + .data.rxBuffer = adi_bufferRxPec, + .data.cellVoltage = &adi_cellVoltage, + .data.cellVoltageAverage = &adi_cellVoltageAverage, + .data.cellVoltageFiltered = &adi_cellVoltageFiltered, + .data.cellVoltageRedundant = &adi_cellVoltageRedundant, + .data.cellTemperature = &adi_cellTemperature, + .data.balancingControl = &adi_balancingControl, + .data.errorTable = &adi_errorTable, + .data.allGpioVoltages = &adi_allGpioVoltage, + .data.allGpioVoltagesRedundant = &adi_allGpioVoltageRedundant, + .data.cellVoltageOpenWireEven = &adi_cellVoltageOpenWireEven, + .data.cellVoltageOpenWireOdd = &adi_cellVoltageOpenWireOdd, + .data.cellVoltageAverageOpenWire = &adi_cellVoltageAverageOpenWire, + .data.cellVoltageRedundantOpenWire = &adi_cellVoltageRedundantOpenWire, + .data.allGpioVoltageOpenWire = &adi_allGpioVoltageOpenWire, + .data.openWire = &adi_openWire, +}; + +/*========== Static Function Prototypes =====================================*/ + +/** + * @brief Read local variables from database and write local variables to + * database. + * @param adiState state of the ADI driver + */ + +static void ADI_AccessToDatabase(ADI_STATE_s *adiState); + +/** + * @brief Sets the balancing according to the control values read in the + * database. + * @brief To set balancing for the cells, the corresponding bits have to be + * written in the configuration register. + * The ades183x driver only executes the balancing orders written by + * the BMS in the database. + * @param adiState state of the ADI driver + */ +static void ADI_BalanceControl(ADI_STATE_s *adiState); + +/** + * @brief Checks the requests made to the ades183x driver. + * @param request request to be made with string addressed + * @return STD_OK if request queue was full, STD_NOT_OK otherwise + */ +static STD_RETURN_TYPE_e ADI_GetRequest(AFE_REQUEST_e *request); + +/** + * @brief Runs the initialization sequence of the driver. + * @param adiState state of the ADI driver + * @param request request to be made with string addressed + * @return true if measurement has been started, false otherwise + * + */ +static bool ADI_ProcessMeasurementNotStartedState(ADI_STATE_s *adiState, AFE_REQUEST_e *request); + +/** + * @brief sets the measurement initialization status. + */ +static void ADI_SetFirstMeasurementCycleFinished(ADI_STATE_s *adiState); + +/*========== Static Function Implementations ================================*/ + +static void ADI_AccessToDatabase(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /* Increment state variable each time new values are written into database */ + (void)DATA_WRITE_DATA( + adiState->data.cellVoltage, + adiState->data.cellVoltageFiltered, + adiState->data.allGpioVoltages, + adiState->data.cellTemperature); + ADI_Wait(2u); /* Block task to leave CPU time for the other tasks */ + + (void)DATA_READ_DATA(adiState->data.balancingControl); +} + +/* RequirementId: D7.1 V0R4 FUN-6.10.01.01 */ +static void ADI_BalanceControl(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /* Unmute balancing, cell voltage measurements must have been stopped before */ + ADI_CopyCommandBits(adi_cmdUnmute, adi_command); + ADI_TransmitCommand(adi_command, adiState); + + /* Write the balancing registers of the ades183x */ + ADI_DetermineBalancingRegisterConfiguration(adiState); + + /* Wait ADI_BALANCING_TIME_ms milliseconds in order to balance + Measurements are stopped during this time */ + ADI_Wait(ADI_BALANCING_TIME_ms); + + /* Mute balancing, so that cell voltage measurements can be restarted */ + ADI_CopyCommandBits(adi_cmdMute, adi_command); + ADI_TransmitCommand(adi_command, adiState); +} + +static STD_RETURN_TYPE_e ADI_GetRequest(AFE_REQUEST_e *request) { + FAS_ASSERT(request != NULL_PTR); + STD_RETURN_TYPE_e requestReceived = STD_NOT_OK; + OS_STD_RETURN_e receivedFromQueue = + OS_ReceiveFromQueue(ftsk_afeRequestQueue, (void *)request, ADI_QUEUE_TIMEOUT_MS); + if (receivedFromQueue == OS_SUCCESS) { + /* request queue was full, request retrieved */ + requestReceived = STD_OK; + } + return requestReceived; +} + +static bool ADI_ProcessMeasurementNotStartedState(ADI_STATE_s *adiState, AFE_REQUEST_e *request) { + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(request != NULL_PTR); + + bool measurementStarted = false; + STD_RETURN_TYPE_e requestReceived = ADI_GetRequest(request); + if (requestReceived == STD_OK) { /* request queue was not empty */ + if (*request == AFE_START_REQUEST) { + ADI_InitializeMeasurement(adiState); + measurementStarted = true; + } else { /* Until requested to start, block task to leave CPU time for the other tasks */ + ADI_Wait(1u); + } + } else { /* Until requested to start, block task to leave CPU time for the other tasks */ + ADI_Wait(1u); + } + return measurementStarted; +} + +static void ADI_RunCurrentStringMeasurement(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /* Start auxiliary voltage measurement, all channels */ + ADI_CopyCommandBits(adi_cmdAdax, adi_command); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADAX_OW_POS, ADI_ADAX_OW_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADAX_PUP_POS, ADI_ADAX_PUP_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADAX_CH4_POS, ADI_ADAX_CH4_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADAX_CH03_POS, ADI_ADAX_CH03_LEN, 0u); + ADI_TransmitCommand(adi_command, adiState); + /* Start redundant auxiliary voltage measurement, one channel */ + ADI_CopyCommandBits(adi_cmdAdax2, adi_command); + ADI_WriteCommandConfigurationBits( + adi_command, + ADI_ADAX2_CH03_POS, + ADI_ADAX2_CH03_LEN, + adiState->redundantAuxiliaryChannel[adiState->currentString]); + ADI_TransmitCommand(adi_command, adiState); + + ADI_Wait(ADI_WAIT_TIME_1_FOR_ADAX_FULL_CYCLE); + + /* Snapshot to freeze cell voltage measurement result registers */ + ADI_CopyCommandBits(adi_cmdSnap, adi_command); + ADI_TransmitCommand(adi_command, adiState); + /* Retrieve filtered cell voltages */ + ADI_GetVoltages(adiState, ADI_CELL_VOLTAGE_REGISTER, ADI_CELL_VOLTAGE); + ADI_GetVoltages(adiState, ADI_FILTERED_CELL_VOLTAGE_REGISTER, ADI_FILTERED_CELL_VOLTAGE); + /* Release snapshot to refresh cell voltage measurement result registers again */ + ADI_CopyCommandBits(adi_cmdUnsnap, adi_command); + ADI_TransmitCommand(adi_command, adiState); + + /* Wait until auxiliary measurement cycle is finished */ + ADI_Wait(ADI_WAIT_TIME_2_FOR_ADAX_FULL_CYCLE); + + /* Retrieve GPIO voltages (all channels) */ + ADI_GetGpioVoltages(adiState, ADI_AUXILIARY_REGISTER, ADI_AUXILIARY_VOLTAGE); + /* Get temperatures via GPIO voltages */ + ADI_GetTemperatures(adiState); + + ADI_AccessToDatabase(adiState); + + /* If at least one cell is balanced, measurements are stopped before activating balancing */ + if (adiState->data.balancingControl->nrBalancedCells[adiState->currentString] > 0u) { + /* Stop cell voltage measurements before activating balancing */ + ADI_StopContinuousCellVoltageMeasurements(adiState); + /* Activate balancing (if necessary) */ + ADI_BalanceControl(adiState); + /* Wait ADI_BALANCING_TIME_ms milliseconds in order to balance + Measurements are stopped during this time */ + ADI_Wait(ADI_BALANCING_TIME_ms); + /* Restart cell voltage measurements before activating balancing */ + ADI_RestartContinuousCellVoltageMeasurements(adiState); + } + + ADI_Diagnostic(adiState); + + /* Cycle finished for string, clear values to check that they are not stuck during next reading */ + ADI_CopyCommandBits(adi_cmdClrcell, adi_command); + ADI_TransmitCommand(adi_command, adiState); +} + +static void ADI_SetFirstMeasurementCycleFinished(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + OS_EnterTaskCritical(); + adiState->firstMeasurementMade = true; + OS_ExitTaskCritical(); +} + +/*========== Extern Function Implementations ================================*/ + +/* START extern functions to adapt if running in other environment (e.g., bare metal) */ + +extern void ADI_ActivateInterfaceBoard(void) { + /* Set 3rd PE pins to enable daisy chains */ + PEX_SetPinDirectionOutput(PEX_PORT_EXPANDER3, PEX_PIN10); + PEX_SetPinDirectionOutput(PEX_PORT_EXPANDER3, PEX_PIN11); + PEX_SetPinDirectionOutput(PEX_PORT_EXPANDER3, PEX_PIN12); + PEX_SetPinDirectionOutput(PEX_PORT_EXPANDER3, PEX_PIN13); + PEX_SetPinDirectionOutput(PEX_PORT_EXPANDER3, PEX_PIN14); + PEX_SetPinDirectionOutput(PEX_PORT_EXPANDER3, PEX_PIN15); + PEX_SetPinDirectionOutput(PEX_PORT_EXPANDER3, PEX_PIN16); + PEX_SetPinDirectionOutput(PEX_PORT_EXPANDER3, PEX_PIN17); + PEX_SetPin(PEX_PORT_EXPANDER3, PEX_PIN10); + PEX_SetPin(PEX_PORT_EXPANDER3, PEX_PIN11); + PEX_SetPin(PEX_PORT_EXPANDER3, PEX_PIN12); + PEX_SetPin(PEX_PORT_EXPANDER3, PEX_PIN13); + PEX_SetPin(PEX_PORT_EXPANDER3, PEX_PIN14); + PEX_SetPin(PEX_PORT_EXPANDER3, PEX_PIN15); + PEX_SetPin(PEX_PORT_EXPANDER3, PEX_PIN16); + PEX_SetPin(PEX_PORT_EXPANDER3, PEX_PIN17); +} + +extern STD_RETURN_TYPE_e ADI_MakeRequest(AFE_REQUEST_e request) { + FAS_ASSERT(request < AFE_REQUEST_E_MAX); + + STD_RETURN_TYPE_e requestSubmitted = STD_NOT_OK; + + if (OS_SUCCESS == OS_SendToBackOfQueue(ftsk_afeRequestQueue, (void *)&request, ADI_QUEUE_TIMEOUT_MS)) { + /* request queue was empty, request submitted */ + requestSubmitted = STD_OK; + } + return requestSubmitted; +} + +extern bool ADI_IsFirstMeasurementCycleFinished(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + return (adiState->firstMeasurementMade); +} + +/* END extern functions to adapt if running in other environment (e.g., bare metal) */ + +/* RequirementId: D7.1 V0R4 FUN-1.10.01.03 */ +/* RequirementId: D7.1 V0R4 FUN-2.10.01.03 */ +/* RequirementId: D7.1 V0R4 FUN-4.10.01.03 */ +extern void ADI_MeasurementCycle(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + STD_RETURN_TYPE_e requestReceived = STD_OK; + AFE_REQUEST_e request = AFE_NO_REQUEST; + + /* AXIVION Next Line Style MisraC2012-2.2 FaultDetection-DeadBranches: non-blocking driver requires an infinite + * loop for the driver implementation */ + while (FOREVER()) { + if (adiState->measurementStarted == false) { /* Wait until requested to start */ + adiState->measurementStarted = ADI_ProcessMeasurementNotStartedState(adiState, &request); + } else { + while (adiState->currentString < adiState->spiNumberInterfaces) { + ADI_RunCurrentStringMeasurement(adiState); + ++adiState->currentString; + } + adiState->currentString = 0u; + if (ADI_IsFirstMeasurementCycleFinished(adiState) == false) { + ADI_SetFirstMeasurementCycleFinished(adiState); + } + requestReceived = ADI_GetRequest(&request); + if (requestReceived == STD_OK) { + /* request queue was not empty */ + if (request == AFE_STOP_REQUEST) { + adiState->measurementStarted = false; + } + } + } + +#ifdef UNITY_UNIT_TEST /* break out of loop in unit test*/ + break; +#endif + } +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_ADI_AccessToDatabase(ADI_STATE_s *adiState) { + ADI_AccessToDatabase(adiState); +} +extern void TEST_ADI_BalanceControl(ADI_STATE_s *adiState) { + ADI_BalanceControl(adiState); +} +extern STD_RETURN_TYPE_e TEST_ADI_GetRequest(AFE_REQUEST_e *request) { + return ADI_GetRequest(request); +} +extern bool TEST_ADI_ProcessMeasurementNotStartedState(ADI_STATE_s *adiState, AFE_REQUEST_e *request) { + return ADI_ProcessMeasurementNotStartedState(adiState, request); +} +extern void TEST_ADI_RunCurrentStringMeasurement(ADI_STATE_s *adiState) { + ADI_RunCurrentStringMeasurement(adiState); +} +extern void TEST_ADI_SetFirstMeasurementCycleFinished(ADI_STATE_s *adiState) { + ADI_SetFirstMeasurementCycleFinished(adiState); +} +#endif diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x.h new file mode 100644 index 00000000..43dbd9a6 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x.h @@ -0,0 +1,119 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x.h + * @author foxBMS Team + * @date 2015-09-01 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Headers for the driver for the ADI analog front-end. + * + */ + +#ifndef FOXBMS__ADI_ADES183X_H_ +#define FOXBMS__ADI_ADES183X_H_ + +/*========== Includes =======================================================*/ +/* clang-format off */ +#include "adi_ades183x_cfg.h" +/* clang-format on */ + +#include "adi_ades183x_defs.h" +#include "afe.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/* Value notified to the AFE task in the DMA callback called when + the SPI transaction for the communication with the ADI AFE is + finished */ +#define ADI_DMA_SPI_FINISHED_NOTIFICATION_VALUE (0x50u) + +/*========== Extern Constant and Variable Declarations ======================*/ + +/** Contains the internal state of the adi driver. */ +extern ADI_STATE_s adi_stateBase; + +/*========== Extern Function Prototypes =====================================*/ + +/** + * @brief Sets the pins to activate the interface board. + */ +extern void ADI_ActivateInterfaceBoard(void); + +/** + * @brief Makes a request to the ADI driver. + * @param request request to be made with string addressed + * @return STD_OK if request queue was empty, STD_NOT_OK otherwise + */ +extern STD_RETURN_TYPE_e ADI_MakeRequest(AFE_REQUEST_e request); + +/** + * @brief Implements the actual measurement sequence for the ADI driver. + * @details This function contains the sequence of events + * @param adiState state of the adi driver + */ +extern void ADI_MeasurementCycle(ADI_STATE_s *adiState); + +/** + * @brief Gets the measurement initialization status. + * @param adiState state of the adi driver + * @return true if a first measurement cycle was made, false otherwise + */ +extern bool ADI_IsFirstMeasurementCycleFinished(ADI_STATE_s *adiState); + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_ADI_AccessToDatabase(ADI_STATE_s *adiState); +extern void TEST_ADI_BalanceControl(ADI_STATE_s *adiState); +extern STD_RETURN_TYPE_e TEST_ADI_GetRequest(AFE_REQUEST_e *request); +extern bool TEST_ADI_ProcessMeasurementNotStartedState(ADI_STATE_s *adiState, AFE_REQUEST_e *request); +extern void TEST_ADI_RunCurrentStringMeasurement(ADI_STATE_s *adiState); +extern void TEST_ADI_SetFirstMeasurementCycleFinished(ADI_STATE_s *adiState); +#endif + +#endif /* FOXBMS__ADI_ADES183X_H_ */ diff --git a/src/app/driver/afe/ltc/common/config/ltc_afe_dma_cfg.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_balancing.h similarity index 75% rename from src/app/driver/afe/ltc/common/config/ltc_afe_dma_cfg.h rename to src/app/driver/afe/adi/common/ades183x/adi_ades183x_balancing.h index d77f5e90..8ff444a9 100644 --- a/src/app/driver/afe/ltc/common/config/ltc_afe_dma_cfg.h +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_balancing.h @@ -40,34 +40,45 @@ */ /** - * @file ltc_afe_dma_cfg.h + * @file adi_ades183x_balancing.h * @author foxBMS Team - * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2015-09-01 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS - * @prefix DMA - * - * @brief Headers for the configuration for the DMA module + * @prefix ADI * + * @brief Headers for the driver for the ADI analog front-end. * */ -#ifndef FOXBMS__LTC_AFE_DMA_CFG_H_ -#define FOXBMS__LTC_AFE_DMA_CFG_H_ +#ifndef FOXBMS__ADI_ADES183X_BALANCING_H_ +#define FOXBMS__ADI_ADES183X_BALANCING_H_ /*========== Includes =======================================================*/ - -#include +#include "adi_ades183x_defs.h" /*========== Macros and Definitions =========================================*/ /*========== Extern Constant and Variable Declarations ======================*/ /*========== Extern Function Prototypes =====================================*/ +/** + * @brief Disable balancing + * @param adiState state of the driver + */ +extern void ADI_DeactivateBalancing(ADI_STATE_s *adiState); + +/** + * @brief Determines how the balancing registers need to be set + * @details Dependent on the actually used cell inputs this functions sets the + * registers accordingly. + * @param adiState state of the driver + */ +extern void ADI_DetermineBalancingRegisterConfiguration(ADI_STATE_s *adiState); /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST #endif -#endif /* FOXBMS__LTC_AFE_DMA_CFG_H_ */ +#endif /* FOXBMS__ADI_ADES183X_BALANCING_H_ */ diff --git a/src/app/driver/config/nxpfs85xx_cfg.c b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_buffers.c similarity index 62% rename from src/app/driver/config/nxpfs85xx_cfg.c rename to src/app/driver/afe/adi/common/ades183x/adi_ades183x_buffers.c index cca45137..1d1d2cb4 100644 --- a/src/app/driver/config/nxpfs85xx_cfg.c +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_buffers.c @@ -40,22 +40,27 @@ */ /** - * @file nxpfs85xx_cfg.c + * @file adi_ades183x_buffers.c * @author foxBMS Team - * @date 2020-03-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup DRIVERS_CONFIGURATION - * @prefix SBC + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI * - * @brief Config source file for SBC module + * @brief Buffers used by the driver for the ADI analog front-end. * - * @details It must always be used when creating new c source files. + * @details The buffer are defined here and used throughout the driver. + * This is to avoid either allocation on the stack or static + * definition in each function: as the table size is proportional + * to the number of modules, its size can be huge. * */ /*========== Includes =======================================================*/ -#include "nxpfs85xx_cfg.h" +#include "adi_ades183x_buffers.h" + +#include "adi_ades183x.h" #include @@ -65,6 +70,25 @@ /*========== Extern Constant and Variable Definitions =======================*/ +uint8_t adi_configurationRegisterAgroup[BS_NR_OF_STRINGS] + [BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES] = {0}; +uint8_t adi_configurationRegisterBgroup[BS_NR_OF_STRINGS] + [BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES] = {0}; + +uint8_t adi_readConfigurationRegisterAgroup[BS_NR_OF_STRINGS] + [BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES] = {0}; +uint8_t adi_readConfigurationRegisterBgroup[BS_NR_OF_STRINGS] + [BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES] = {0}; + +uint16_t adi_command[ADI_COMMAND_DEFINITION_LENGTH] = {0}; + +uint8_t adi_dataTransmit[BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES] = {0}; +uint8_t adi_dataReceive[BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES] = {0}; + +uint8_t adi_writeGlobal[ADI_MAX_REGISTER_SIZE_IN_BYTES] = {0}; + +uint8_t adi_clearFlagData[ADI_CLRFLAG_DATA_LENGTH] = {0}; + /*========== Static Function Prototypes =====================================*/ /*========== Static Function Implementations ================================*/ diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_buffers.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_buffers.h new file mode 100644 index 00000000..e6d9e211 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_buffers.h @@ -0,0 +1,120 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_buffers.h + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Header for the buffers used by the driver for the ADI analog front-end. + * + * @details The buffer are defined in a separate file and used throughout the + * driver. Their definition is included with this header. + * + */ + +#ifndef FOXBMS__ADI_ADES183X_BUFFERS_H_ +#define FOXBMS__ADI_ADES183X_BUFFERS_H_ + +/*========== Includes =======================================================*/ +#include "adi_ades183x.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Declarations ======================*/ + +/* RequirementId: D7.1 V0R4 SIF-4.20.01.01 */ +/** Driver copy of the configuration stored in the AFE configuration registers */ +extern uint8_t adi_configurationRegisterAgroup[BS_NR_OF_STRINGS] + [BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]; +extern uint8_t adi_configurationRegisterBgroup[BS_NR_OF_STRINGS] + [BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]; + +/** Configuration read from the AFE configuration registers, used for comparison with written values */ +extern uint8_t adi_readConfigurationRegisterAgroup[BS_NR_OF_STRINGS] + [BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]; +extern uint8_t adi_readConfigurationRegisterBgroup[BS_NR_OF_STRINGS] + [BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]; + +/* Variable used to set configuration bits in commands */ +extern uint16_t adi_command[ADI_COMMAND_DEFINITION_LENGTH]; + +/** + * Buffer used to write data to a register on the AFEs + * 6 bytes per module, which is the maximum size of a register in the AFE + * Same buffer used for 4 bytes wide registers + */ +extern uint8_t adi_dataTransmit[BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]; + +/** + * Buffer used to read data from a register on the AFEs + * 6 bytes per module, which is the maximum size of a register in the AFE + * Same buffer used for 4 bytes wide registers + */ +extern uint8_t adi_dataReceive[BS_NR_OF_MODULES_PER_STRING * ADI_MAX_REGISTER_SIZE_IN_BYTES]; + +/** + * Buffer used to write the same data to a register for all the AFEs + * 6 bytes, which is the maximum size of a register in the AFE + * Same buffer used for 4 bytes wide registers + * Used in the function ADI_WriteRegisterGlobal(): there the content of + * adi_diagnosticWriteGlobal is copied everywhere in adi_dataTransmit + */ +extern uint8_t adi_writeGlobal[ADI_MAX_REGISTER_SIZE_IN_BYTES]; + +/* Bytes used by CLRFLAG command to indicate which flags have to be cleared */ +extern uint8_t adi_clearFlagData[ADI_CLRFLAG_DATA_LENGTH]; + +/*========== Extern Function Prototypes =====================================*/ + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +#endif + +#endif /* FOXBMS__ADI_ADES183X_BUFFERS_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands.c b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands.c new file mode 100644 index 00000000..926e2793 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands.c @@ -0,0 +1,264 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_commands.c + * @author foxBMS Team + * @date 2019-08-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Implementation of some software + * + */ + +/*========== Includes =======================================================*/ +#include "adi_ades183x_commands.h" + +#include "adi_ades183x_defs.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ +const uint16_t adi_cmdAdcv[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_ADCV_BYTE0, ADI_ADCV_BYTE1, ADI_ADCV_INC, ADI_ADCV_LEN}; +FAS_STATIC_ASSERT( + (ADI_ADCV_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdAdsv[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_ADSV_BYTE0, ADI_ADSV_BYTE1, ADI_ADSV_INC, ADI_ADSV_LEN}; +FAS_STATIC_ASSERT( + (ADI_ADSV_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdWrcfga[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_WRCFGA_BYTE0, ADI_WRCFGA_BYTE1, ADI_WRCFGA_INC, ADI_WRCFGA_LEN}; +FAS_STATIC_ASSERT( + (ADI_WRCFGA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdWrcfgb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_WRCFGB_BYTE0, ADI_WRCFGB_BYTE1, ADI_WRCFGB_INC, ADI_WRCFGB_LEN}; +FAS_STATIC_ASSERT( + (ADI_WRCFGB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdcfga[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDCFGA_BYTE0, ADI_RDCFGA_BYTE1, ADI_RDCFGA_INC, ADI_RDCFGA_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDCFGA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdcfgb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDCFGB_BYTE0, ADI_RDCFGB_BYTE1, ADI_RDCFGB_INC, ADI_RDCFGB_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDCFGB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdSnap[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_SNAPSHOT_BYTE0, ADI_SNAPSHOT_BYTE1, ADI_SNAPSHOT_INC, ADI_SNAPSHOT_LEN}; +FAS_STATIC_ASSERT( + (ADI_SNAPSHOT_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdUnsnap[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_UNSNAPSHOT_BYTE0, ADI_UNSNAPSHOT_BYTE1, ADI_UNSNAPSHOT_INC, ADI_UNSNAPSHOT_LEN}; +FAS_STATIC_ASSERT( + (ADI_UNSNAPSHOT_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdMute[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_MUTE_BYTE0, ADI_MUTE_BYTE1, ADI_MUTE_INC, ADI_MUTE_LEN}; +FAS_STATIC_ASSERT( + (ADI_MUTE_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdUnmute[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_UNMUTE_BYTE0, ADI_UNMUTE_BYTE1, ADI_UNMUTE_INC, ADI_UNMUTE_LEN}; +FAS_STATIC_ASSERT( + (ADI_UNMUTE_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdRstcc[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RSTCC_BYTE0, ADI_RSTCC_BYTE1, ADI_RSTCC_INC, ADI_RSTCC_LEN}; +FAS_STATIC_ASSERT( + (ADI_RSTCC_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdAdax[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_ADAX_BYTE0, ADI_ADAX_BYTE1, ADI_ADAX_INC, ADI_ADAX_LEN}; +FAS_STATIC_ASSERT( + (ADI_ADAX_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdAdax2[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_ADAX2_BYTE0, ADI_ADAX2_BYTE1, ADI_ADAX2_INC, ADI_ADAX2_LEN}; +FAS_STATIC_ASSERT( + (ADI_ADAX2_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdRdauxa[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDAUXA_BYTE0, ADI_RDAUXA_BYTE1, ADI_RDAUXA_INC, ADI_RDAUXA_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDAUXA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdauxb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDAUXB_BYTE0, ADI_RDAUXB_BYTE1, ADI_RDAUXB_INC, ADI_RDAUXB_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDAUXB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdauxc[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDAUXC_BYTE0, ADI_RDAUXC_BYTE1, ADI_RDAUXC_INC, ADI_RDAUXC_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDAUXC_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdauxd[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDAUXD_BYTE0, ADI_RDAUXD_BYTE1, ADI_RDAUXD_INC, ADI_RDAUXD_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDAUXD_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdauxe[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDAUXE_BYTE0, ADI_RDAUXE_BYTE1, ADI_RDAUXE_INC, ADI_RDAUXE_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDAUXE_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdRdraxa[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDRAXA_BYTE0, ADI_RDRAXA_BYTE1, ADI_RDRAXA_INC, ADI_RDRAXA_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDRAXA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdraxb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDRAXB_BYTE0, ADI_RDRAXB_BYTE1, ADI_RDRAXB_INC, ADI_RDRAXB_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDRAXB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdraxc[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDRAXC_BYTE0, ADI_RDRAXC_BYTE1, ADI_RDRAXC_INC, ADI_RDRAXC_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDRAXC_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdraxd[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDRAXD_BYTE0, ADI_RDRAXD_BYTE1, ADI_RDRAXD_INC, ADI_RDRAXD_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDRAXD_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdClraux[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_CLRAUX_BYTE0, ADI_CLRAUX_BYTE1, ADI_CLRAUX_INC, ADI_CLRAUX_LEN}; +FAS_STATIC_ASSERT( + (ADI_CLRAUX_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdRdstata[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSTATA_BYTE0, ADI_RDSTATA_BYTE1, ADI_RDSTATA_INC, ADI_RDSTATA_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSTATA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdstatb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSTATB_BYTE0, ADI_RDSTATB_BYTE1, ADI_RDSTATB_INC, ADI_RDSTATB_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSTATB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdstatc[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSTATC_BYTE0, ADI_RDSTATC_BYTE1, ADI_RDSTATC_INC, ADI_RDSTATC_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSTATC_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdstatd[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSTATD_BYTE0, ADI_RDSTATD_BYTE1, ADI_RDSTATD_INC, ADI_RDSTATD_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSTATD_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdstate[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSTATE_BYTE0, ADI_RDSTATE_BYTE1, ADI_RDSTATE_INC, ADI_RDSTATE_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSTATE_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdClrcell[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_CLRCELL_BYTE0, ADI_CLRCELL_BYTE1, ADI_CLRCELL_INC, ADI_CLRCELL_LEN}; +FAS_STATIC_ASSERT( + (ADI_CLRCELL_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdClrflag[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_CLRFLAG_BYTE0, ADI_CLRFLAG_BYTE1, ADI_CLRFLAG_INC, ADI_CLRFLAG_LEN}; +FAS_STATIC_ASSERT( + (ADI_CLRFLAG_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdWrpwma[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_WRPWMA_BYTE0, ADI_WRPWMA_BYTE1, ADI_WRPWMA_INC, ADI_WRPWMA_LEN}; +FAS_STATIC_ASSERT( + (ADI_WRPWMA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdWrpwmb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_WRPWMB_BYTE0, ADI_WRPWMB_BYTE1, ADI_WRPWMB_INC, ADI_WRPWMB_LEN}; +FAS_STATIC_ASSERT( + (ADI_WRPWMB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdpwma[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDPWMA_BYTE0, ADI_RDPWMA_BYTE1, ADI_RDPWMA_INC, ADI_RDPWMA_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDPWMA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdRdsid[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSID_BYTE0, ADI_RDSID_BYTE1, ADI_RDSID_INC, ADI_RDSID_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSID_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdSrst[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_SRST_BYTE0, ADI_SRST_BYTE1, ADI_SRST_INC, ADI_SRST_LEN}; +FAS_STATIC_ASSERT( + (ADI_SRST_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands.h new file mode 100644 index 00000000..df58d0b1 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands.h @@ -0,0 +1,127 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_commands.h + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Header file of some software + * + */ + +#ifndef FOXBMS__ADI_ADES183X_COMMANDS_H_ +#define FOXBMS__ADI_ADES183X_COMMANDS_H_ + +/*========== Includes =======================================================*/ +#include "adi_ades183x_defs.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Extern Constant and Variable Declarations ======================*/ + +/** Declarations of commands */ +/**@{*/ + +extern const uint16_t adi_cmdAdcv[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdAdsv[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdWrcfga[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdWrcfgb[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdcfga[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdcfgb[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdSnap[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdUnsnap[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdMute[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdUnmute[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdRstcc[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdAdax[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdAdax2[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdRdauxa[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdauxb[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdauxc[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdauxd[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdauxe[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdRdraxa[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdraxb[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdraxc[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdraxd[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdClraux[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdRdstata[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdstatb[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdstatc[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdstatd[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdstate[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdClrcell[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdClrflag[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdRdcva[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdWrpwma[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdWrpwmb[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdpwma[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdRdsid[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdSrst[ADI_COMMAND_DEFINITION_LENGTH]; +/**@}*/ + +/*========== Extern Function Prototypes =====================================*/ + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +#endif + +#endif /* FOXBMS__ADI_ADES183X_COMMANDS_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands_voltages.c b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands_voltages.c new file mode 100644 index 00000000..516afdd2 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands_voltages.c @@ -0,0 +1,201 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_commands_voltages.c + * @author foxBMS Team + * @date 2022-12-06 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Command definitions related to voltage measurement only specific to + * the driver for the ADI ades183x. + * + */ + +/*========== Includes =======================================================*/ +#include "adi_ades183x_commands_voltages.h" + +#include "adi_ades183x_defs.h" +#include "fassert.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ +const uint16_t adi_cmdRdcva[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDCVA_BYTE0, ADI_RDCVA_BYTE1, ADI_RDCVA_INC, ADI_RDCVA_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDCVA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdcvb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDCVB_BYTE0, ADI_RDCVB_BYTE1, ADI_RDCVB_INC, ADI_RDCVB_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDCVB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdcvc[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDCVC_BYTE0, ADI_RDCVC_BYTE1, ADI_RDCVC_INC, ADI_RDCVC_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDCVC_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdcvd[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDCVD_BYTE0, ADI_RDCVD_BYTE1, ADI_RDCVD_INC, ADI_RDCVD_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDCVD_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdcve[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDCVE_BYTE0, ADI_RDCVE_BYTE1, ADI_RDCVE_INC, ADI_RDCVE_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDCVE_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdcvf[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDCVF_BYTE0, ADI_RDCVF_BYTE1, ADI_RDCVF_INC, ADI_RDCVF_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDCVF_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdRdaca[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDACA_BYTE0, ADI_RDACA_BYTE1, ADI_RDACA_INC, ADI_RDACA_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDACA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdacb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDACB_BYTE0, ADI_RDACB_BYTE1, ADI_RDACB_INC, ADI_RDACB_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDACB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdacc[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDACC_BYTE0, ADI_RDACC_BYTE1, ADI_RDACC_INC, ADI_RDACC_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDACC_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdacd[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDACD_BYTE0, ADI_RDACD_BYTE1, ADI_RDACD_INC, ADI_RDACD_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDACD_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdace[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDACE_BYTE0, ADI_RDACE_BYTE1, ADI_RDACE_INC, ADI_RDACE_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDACE_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdacf[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDACF_BYTE0, ADI_RDACF_BYTE1, ADI_RDACF_INC, ADI_RDACF_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDACF_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdRdfca[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDFCA_BYTE0, ADI_RDFCA_BYTE1, ADI_RDFCA_INC, ADI_RDFCA_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDFCA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdfcb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDFCB_BYTE0, ADI_RDFCB_BYTE1, ADI_RDFCB_INC, ADI_RDFCB_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDFCB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdfcc[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDFCC_BYTE0, ADI_RDFCC_BYTE1, ADI_RDFCC_INC, ADI_RDFCC_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDFCC_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdfcd[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDFCD_BYTE0, ADI_RDFCD_BYTE1, ADI_RDFCD_INC, ADI_RDFCD_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDFCD_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdfce[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDFCE_BYTE0, ADI_RDFCE_BYTE1, ADI_RDFCE_INC, ADI_RDFCE_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDFCE_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdfcf[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDFCF_BYTE0, ADI_RDFCF_BYTE1, ADI_RDFCF_INC, ADI_RDFCF_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDFCF_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +const uint16_t adi_cmdRdsva[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSVA_BYTE0, ADI_RDSVA_BYTE1, ADI_RDSVA_INC, ADI_RDSVA_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSVA_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdsvb[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSVB_BYTE0, ADI_RDSVB_BYTE1, ADI_RDSVB_INC, ADI_RDSVB_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSVB_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdsvc[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSVC_BYTE0, ADI_RDSVC_BYTE1, ADI_RDSVC_INC, ADI_RDSVC_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSVC_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdsvd[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSVD_BYTE0, ADI_RDSVD_BYTE1, ADI_RDSVD_INC, ADI_RDSVD_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSVD_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdsve[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSVE_BYTE0, ADI_RDSVE_BYTE1, ADI_RDSVE_INC, ADI_RDSVE_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSVE_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); +const uint16_t adi_cmdRdsvf[ADI_COMMAND_DEFINITION_LENGTH] = + {ADI_RDSVF_BYTE0, ADI_RDSVF_BYTE1, ADI_RDSVF_INC, ADI_RDSVF_LEN}; +FAS_STATIC_ASSERT( + (ADI_RDSVF_LEN <= ADI_MAX_REGISTER_SIZE_IN_BYTES), + "Register length must not be greater than ADI_MAX_REGISTER_SIZE_IN_BYTES"); + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands_voltages.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands_voltages.h new file mode 100644 index 00000000..959ce798 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands_voltages.h @@ -0,0 +1,105 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_commands_voltages.h + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Header file of some software + * + */ + +#ifndef FOXBMS__ADI_ADES183X_COMMANDS_VOLTAGES_H_ +#define FOXBMS__ADI_ADES183X_COMMANDS_VOLTAGES_H_ + +/*========== Includes =======================================================*/ +#include "adi_ades183x_defs.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Extern Constant and Variable Declarations ======================*/ + +/** Declarations of voltage measurement related commands */ +/**@{*/ + +extern const uint16_t adi_cmdRdcvb[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdcvc[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdcvd[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdcve[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdcvf[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdRdaca[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdacb[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdacc[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdacd[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdace[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdacf[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdRdfca[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdfcb[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdfcc[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdfcd[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdfce[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdfcf[ADI_COMMAND_DEFINITION_LENGTH]; + +extern const uint16_t adi_cmdRdsva[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdsvb[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdsvc[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdsvd[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdsve[ADI_COMMAND_DEFINITION_LENGTH]; +extern const uint16_t adi_cmdRdsvf[ADI_COMMAND_DEFINITION_LENGTH]; + +/**@}*/ + +/*========== Extern Function Prototypes =====================================*/ + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +#endif + +#endif /* FOXBMS__ADI_ADES183X_COMMANDS_VOLTAGES_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_defs.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_defs.h new file mode 100644 index 00000000..6dc86626 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_defs.h @@ -0,0 +1,1220 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_defs.h + * @author foxBMS Team + * @date 2015-09-01 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Headers for the driver for the ades183x analog front-end. + * + */ + +#ifndef FOXBMS__ADI_ADES183X_DEFS_H_ +#define FOXBMS__ADI_ADES183X_DEFS_H_ + +/*========== Includes =======================================================*/ +#if defined(FOXBMS_AFE_DRIVER_ADI_ADES1830) +#include "adi_ades1830_defs.h" +#endif + +#include "battery_system_cfg.h" + +#include "database.h" +#include "spi.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/** used to determine if a PEC fault should be injected in the register write function */ +typedef enum { + ADI_PEC_NO_FAULT_INJECTION, + ADI_COMMAND_PEC_FAULT_INJECTION, + ADI_DATA_PEC_FAULT_INJECTION, +} ADI_PEC_FAULT_INJECTION_e; + +/** used to determine which voltage register has to be read */ +typedef enum { + ADI_CELL_VOLTAGE_REGISTER, + ADI_AVERAGE_CELL_VOLTAGE_REGISTER, + ADI_FILTERED_CELL_VOLTAGE_REGISTER, + ADI_REDUNDANT_CELL_VOLTAGE_REGISTER, + ADI_VOLTAGE_REGISTER_TYPE_E_MAX, +} ADI_VOLTAGE_REGISTER_TYPE_e; + +/** used to determine where read voltages have to be stored */ +typedef enum { + ADI_CELL_VOLTAGE, + ADI_AVERAGE_CELL_VOLTAGE, + ADI_FILTERED_CELL_VOLTAGE, + ADI_REDUNDANT_CELL_VOLTAGE, + ADI_CELL_VOLTAGE_OPEN_WIRE_EVEN, + ADI_CELL_VOLTAGE_OPEN_WIRE_ODD, + ADI_CELL_VOLTAGE_AVERAGE_OPEN_WIRE, + ADI_CELL_VOLTAGE_REDUNDANT_OPEN_WIRE, + ADI_VOLTAGE_STORE_LOCATION_E_MAX, +} ADI_VOLTAGE_STORE_LOCATION_e; + +/** used to determine which voltage register has to be read */ +typedef enum { + ADI_AUXILIARY_REGISTER, + ADI_REDUNDANT_AUXILIARY_REGISTER, + ADI_AUXILIARY_REGISTER_TYPE_E_MAX, +} ADI_AUXILIARY_REGISTER_TYPE_e; + +/** used to determine where read voltages have to be stored */ +typedef enum { + ADI_AUXILIARY_VOLTAGE, + ADI_REDUNDANT_AUXILIARY_VOLTAGE, + ADI_AUXILIARY_VOLTAGE_OPEN_WIRE, + ADI_AUXILIARY_STORE_LOCATION_E_MAX, +} ADI_AUXILIARY_STORE_LOCATION_e; + +/* configuration sanitation */ +#if BS_NR_OF_CELL_BLOCKS_PER_MODULE > ADI_MAX_SUPPORTED_CELLS +#error "Number of cell blocks per module cannot be higher than maximum number of cells per module" +#endif +#if BS_NR_OF_GPIOS_PER_MODULE != ADI_TOTAL_GPIO_NUMBER +#error "Number of GPIOs must be 10" +#endif +#if BS_NR_OF_TEMP_SENSORS_PER_MODULE > BS_NR_OF_GPIOS_PER_MODULE +#error "Number of temperature sensors cannot be higher than number of GPIOs" +#endif + +/** + * Default configuration + * @{ + */ +#define ADI_DEFAULT_CTH_COMPARISON_THRESHOLD (ADI_COMPARISON_THRESHOLD_9_1_mV) +#define ADI_DEFAULT_REFON_SETUP (1u) +#define ADI_DEFAULT_FLAG_D_SETUP (ADI_FLAG_D_DEFAULT) +#define ADI_DEFAULT_OWA_SETUP (0u) +#define ADI_DEFAULT_OWRNG_SETUP (0u) +#define ADI_DEFAULT_SOAKON_SETUP (0u) +#define ADI_DEFAULT_GPO_1_8_SETUP (0xFFu) +#define ADI_DEFAULT_GPO_9_10_SETUP (0x03u) +#define ADI_DEFAULT_IIR_SETUP (ADI_IIR_FILTER_PARAMETER_32) +#define ADI_DEFAULT_COMM_BK_SETUP (0u) +#define ADI_DEFAULT_MUTE_ST_SETUP (0u) +#define ADI_DEFAULT_SNAP_ST_SETUP (0u) +#define ADI_DEFAULT_VUV_0_7_SETUP (0u) +#define ADI_DEFAULT_VUV_8_11_SETUP (0x8u) +#define ADI_DEFAULT_VOV_0_3_SETUP (0xFu) +#define ADI_DEFAULT_VOV_4_11_SETUP (0x7Fu) +#define ADI_DEFAULT_DCT0_0_5_SETUP (0u) +#define ADI_DEFAULT_DTRNG_SETUP (0u) +#define ADI_DEFAULT_DTMEN_SETUP (0u) +#define ADI_DEFAULT_DCC_1_8_SETUP (0u) +#define ADI_DEFAULT_DCC_9_16_SETUP (0u) +/**@}*/ + +/* First wait this time after issuing ADAX command for all channels */ +#define ADI_WAIT_TIME_1_FOR_ADAX_FULL_CYCLE (10u) +/* Retrieve voltages, then wait this time, all channels will have been measured */ +#define ADI_WAIT_TIME_2_FOR_ADAX_FULL_CYCLE (8u) + +/* When OW check activated for cell N, cell N voltage must be reduced compared to the + value without check activated. This value for the reduction arises from the voltage + divider formed by the 470 Ohm resistor activated for the check between cell N and + cell N-1 and the input RC filter resistances. */ +#define ADI_NO_OW_CELL_VOLTAGE_REDUCTION (9.0f / 10.0f) +/* Margin for the check of the voltage reduction */ +#define ADI_OW_CELL_VOLTAGE_REDUCTION_MARGIN_mV (1000.0f) +/* Margin for the check of the voltage reduction during OW latent fault check */ +#define ADI_OW_LATENT_CHECK_MARGIN (0.95f) + +/* Mask to select even cells, AFE starts counting from 1 */ +#define ADI_ODD_CELLS_MASK (0x5555u) +/* Mask to select odd cells, AFE starts counting from 1 */ +#define ADI_EVEN_CELLS_MASK (0xAAAAu) + +/* TODO: check reduction */ +/* When OW check activated for GPIO, GPIO voltage must be reduced compared to the + value without check activated. This value for the reduction arises from the voltage + divider formed by the pull-up resistor activated for the check and the input RC + filter resistances. */ +#define ADI_NO_OW_GPIO_VOLTAGE_REDUCTION (10.0f / 12.0f) +/* Margin for the check of the voltage reduction */ +#define ADI_OW_GPIO_VOLTAGE_REDUCTION_MARGIN_mV (1000.0f) + +/* Number of DCC bits in one byte of configuration register group B*/ +#define ADI_CFGRB_NUMBER_OF_DCC_BITS_PER_BYTE (8u) + +/* IC maximum wake-up time */ +#define ADI_T_WAKE_us (500u) +/* IC maximum ready time */ +#define ADI_T_READY_us (10u) +/* T_wake is max 500 us, wait time set for ADI_N_ADI ICs */ +#define ADI_DAISY_CHAIN_WAKE_UP_TIME_us (ADI_N_ADI * ADI_T_WAKE_us) +/* T_ready is max 10 us, wait time set for ADI_N_ADI ICs */ +#define ADI_DAISY_CHAIN_READY_TIME_us (ADI_N_ADI * ADI_T_READY_us) +/* Conversion coefficient for us to ms */ +#define ADI_COEFFICIENT_US_TO_MS (1000u) + +/** Timeout in milliseconds for interrupt-based SPI transmission. */ +#define ADI_TRANSMISSION_TIMEOUT (10u) + +/** isoSPI wakeup time */ +#define ADI_SPI_WAKEUP_WAIT_TIME_US (100u) + +/** Number of used ADI ICs */ +/* Start auxiliary channel number */ +#define ADI_START_AUX_CHANNEL (1u) + +/** Number of used ADI ICs */ +#define ADI_N_ADI (BS_NR_OF_MODULES_PER_STRING) + +/* Maximum value for cell voltages */ +#define ADI_MAX_CELL_VOLTAGE_mV (4500) +/* Minimum value for cell voltages */ +#define ADI_MIN_CELL_VOLTAGE_mV (2000) + +/* Comparison threshold between auxiliary and redundant auxiliary measurements */ +#define ADI_AUXILIARY_COMPARISON_THRESHOLD_mV (9) +/* Minimum value for GPIO voltages (given in SM) */ +#define ADI_MIN_GPIO_VOLTAGE_mV (100) + +/* Maximum value for digital supply voltage VD */ +#define ADI_MAX_VD_mV (3528.0f) +/* Minimum value for digital supply voltage VD */ +#define ADI_MIN_VD_mV (2754.0f) +/* Maximum value for analog supply voltage VA */ +#define ADI_MAX_VA_mV (5486.0f) +/* Minimum value for analog supply voltage VA */ +#define ADI_MIN_VA_mV (4512.0f) +/* Maximum value for secondary reference voltage VREF2 */ +#define ADI_MAX_VREF2_mV (3015.0f) +/* Minimum value for secondary reference voltage VREF2 */ +#define ADI_MIN_VREF2_mV (2985.0f) +/* Maximum value for die temperature ITMP */ +#define ADI_MAX_ITMP_degC (125.0f) +/* Minimum value for die temperature ITMP */ +#define ADI_MIN_ITMP_degC (-40.0f) + +/* Threshold for diagnostic when oscillator is set to run faster */ +#define ADI_OSCILLATOR_FASTER_THRESHOLD (70u) +/* Threshold for diagnostic when oscillator is set to run slower */ +#define ADI_OSCILLATOR_SLOWER_THRESHOLD (52u) + +/** + * Values used for PEC latent fault check + * @{ + */ +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA0_BYTE0 (1u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA0_BYTE1 (2u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA0_BYTE2 (3u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA0_BYTE3 (4u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA0_BYTE4 (5u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA0_BYTE5 (6u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA1_BYTE0 (7u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA1_BYTE1 (8u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA1_BYTE2 (9u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA1_BYTE3 (10u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA1_BYTE4 (11u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA1_BYTE5 (12u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA2_BYTE0 (13u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA2_BYTE1 (14u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA2_BYTE2 (15u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA2_BYTE3 (16u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA2_BYTE4 (17u) +#define ADI_PEC_LATENT_FAULT_CHECK_TESTDATA2_BYTE5 (18u) +/**@}*/ + +/** + * Values to write in FLAG_D bits in configuration register A + * to activate diagnostics + * @{ + */ +#define ADI_FLAG_D_DEFAULT (0x00u) /* 0b00000000u */ +#define ADI_FLAG_D_UV_CHECK (0x04u) /* 0b00000100u */ +#define ADI_FLAG_D_OV_CHECK (0x0Cu) /* 0b00001100u */ +#define ADI_FLAG_D_OSC_FASTER (0x01u) /* 0b00000001u */ +#define ADI_FLAG_D_OSC_SLOWER (0x02u) /* 0b00000010u */ +#define ADI_FLAG_D_FORCE_THSD (0x10u) /* 0b00010000u */ +#define ADI_FLAG_D_FORCE_TMODCHK (0x80u) /* 0b10000000u */ +#define ADI_FLAG_D_INDUCE_ECC_ERROR (0x60u) /* 0b01100000u */ +/**@}*/ + +/** + * Maximum queue timeout time in milliseconds + */ +#define ADI_QUEUE_TIMEOUT_MS ((TickType_t)0u) + +/** + * voltage conversion coefficients + * @{ + */ +#define ADI_VOLTAGE_CONVERSION_FACTOR (150e-6f) +#define ADI_VOLTAGE_CONVERSION_UNIT (1000.0f) +#define ADI_VOLTAGE_CONVERSION_OFFSET (1500.0f) +/**@}*/ + +/** + * die temperature conversion coefficients + * @{ + */ +#define ADI_DIE_TEMPERATURE_VOLTAGE_OFFSET (1.5f) +#define ADI_DIE_TEMPERATURE_KELVIN_OFFSET (273.0f) +#define ADI_DIE_TEMPERATURE_SCALING_FACTOR (7.5f) +/**@}*/ + +/* Define to shift a full byte*/ +#define ADI_BYTE_SHIFT (8u) +/* Define to select complete PEC10 without command counter */ +#define ADI_PEC10_FULL_EXCLUDE_COMMAND_COUNTER (0x3Fu) +/* Define to select PEC10 bit8 and bit9 without command counter */ +#define ADI_PEC10_MSB_EXCLUDE_COMMAND_COUNTER (0x3u) +/* Mask to select one byte */ +#define ADI_ONE_BYTE_MASK (0xFFu) +/* Maximum size of a register */ +#define ADI_MAX_REGISTER_SIZE_IN_BYTES (6u) +/* Size of command plus associated PEC in bytes */ +#define ADI_COMMAND_AND_PEC_SIZE_IN_BYTES (4u) +/* Size of command in bytes */ +#define ADI_COMMAND_SIZE_IN_BYTES (2u) +/* Size of PEC in bytes */ +#define ADI_PEC_SIZE_IN_BYTES (2u) +/* Maximum position of a bit in a bytes */ +#define ADI_MAX_BIT_POSITION_IN_BYTE (7u) +/* Size of a raw voltage measurement in bytes*/ +#define ADI_RAW_VOLTAGE_SIZE_IN_BYTES (2u) +/* Maximum number of voltages per register */ +#define ADI_MAX_NUMBER_OF_VOLTAGES_IN_REGISTER (3u) +/* Maximum number of GPIO voltages per register */ +#define ADI_MAX_NUMBER_OF_GPIO_VOLTAGES_IN_REGISTER (3u) +/* Number of GPIO voltages in AUX register D */ +#define ADI_NUMBER_OF_GPIO_VOLTAGES_IN_REGISTER_D (1u) +/* Number of bytes used to compute PEC */ +#define ADI_SIZE_OF_DATA_FOR_PEC_COMPUTATION (6u) +/* Number of bytes used to compute PEC */ +#define ADI_SIZE_OF_DATA_FOR_PEC_COMPUTATION_WITH_COUNTER (7u) + +/** + * Number of Bytes to be transmitted in daisy-chain + * For first 4 Bytes: + * - 2 Bytes: command + * - 2 Bytes: CRC + * Following Bytes: Data + * - 6 Bytes data per IC + * - 2 Bytes CRC per IC + */ +#define ADI_N_BYTES_FOR_DATA_TRANSMISSION \ + (ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + ((ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES) * ADI_N_ADI)) + +/** + * Offset to select voltages of specific voltage register + * in a table containing all voltages in a linear fashion + * @{ + */ +#define ADI_VOLTAGE_00_02_OFFSET (0u) +#define ADI_VOLTAGE_03_05_OFFSET (3u) +#define ADI_VOLTAGE_06_08_OFFSET (6u) +#define ADI_VOLTAGE_09_11_OFFSET (9u) +#define ADI_VOLTAGE_12_14_OFFSET (12u) +#define ADI_VOLTAGE_15_18_OFFSET (15u) +/**@}*/ + +/** + * position of command bytes and PEC bytes in frame + * @{ + */ +#define ADI_COMMAND_FIRST_BYTE_POSITION (0u) +#define ADI_COMMAND_SECOND_BYTE_POSITION (1u) +#define ADI_COMMAND_PEC_FIRST_BYTE_POSITION (2u) +#define ADI_COMMAND_PEC_SECOND_BYTE_POSITION (3u) +/**@}*/ + +/** + * position of PEC bytes in data frame + * @{ + */ +#define ADI_DATA_PEC_FIRST_BYTE_POSITION (0u) +#define ADI_DATA_PEC_SECOND_BYTE_POSITION (1u) +/**@}*/ + +/** + * COMM definitions + * @{ + */ +#define ADI_ICOM_START (0x60u) +#define ADI_ICOM_STOP (0x10u) +#define ADI_ICOM_BLANK (0x00u) +#define ADI_ICOM_NO_TRANSMIT (0x70u) +#define ADI_FCOM_MASTER_ACK (0x00u) +#define ADI_FCOM_MASTER_NACK (0x08u) +#define ADI_FCOM_MASTER_NACK_STOP (0x09u) +/**@}*/ + +/* RequirementId: D7.1 V0R4 SIF-4.30.03.01 */ +/** error table for the driver */ +typedef struct { + bool spiIsOk[BS_NR_OF_STRINGS]; + /* RequirementId: D7.1 V0R4 SIF-4.10.02.02 */ + /* RequirementId: D7.1 V0R4 SIF-4.20.03.01 */ + bool crcIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool commandCounterIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + /* RequirementId: D7.1 V0R4 SIF-4.20.02.01 */ + bool configurationAIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool configurationBIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + /* RequirementId: D7.1 V0R4 SIF-4.40.01.03 */ + bool voltageRegisterContentIsNotStuck[BS_NR_OF_STRINGS][ADI_N_ADI]; + /* RequirementId: D7.1 V0R4 SIF-4.40.02.03 */ + bool auxiliaryRegisterContentIsNotStuck[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool adcComparisonIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool compFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool spiFltFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool filteredVoltageRangeIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool evenWireIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool oddWireIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool evenWireHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool oddWireHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool adcCompFlagsHaveNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool auxComparisonIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool auxVoltageRangeIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool analogSupplyOvervoltageFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool analogSupplyUndervoltageFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool digitalSupplyOvervoltageFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool digitalSupplyUndervoltageFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool vdeFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool oscchkFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool analogSupplyOvervoltageFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool analogSupplyUndervoltageFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool digitalSupplyOvervoltageFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool digitalSupplyUndervoltageFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool vdeFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool vdelFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool analogSupplyRangeIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool digitalSupplyRangeIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool vresRangeIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool dieTemperatureIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool oscchkFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool ocCounterFasterFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool ocCounterSlowerFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool ocCounterNormalFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool thsdFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool tmodchkFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool tmodchkFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool cmedFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool smedFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool sleepFlagIsCleared[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool cmedFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool smedFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool initResetAuxValuesAreOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool initClearedAuxValuesAreOk[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool pecCheckHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + bool compareLogicFaultFlagHasNoLatentFault[BS_NR_OF_STRINGS][ADI_N_ADI]; + /* RequirementId: D7.1 V0R4 SIF-4.40.01.03 */ + bool noClockFreezeDetectorIsOk[BS_NR_OF_STRINGS][ADI_N_ADI]; +} ADI_ERROR_TABLE_s; + +/** Define used to access bytes in answer frames */ +#define ADI_FIRST_DATA_BYTE_POSITION_IN_TRANSMISSION_FRAME (4u) + +/** Defines to access voltage register set */ +/**@{*/ +#define ADI_RESULT_REGISTER_SET_A (0u) +#define ADI_RESULT_REGISTER_SET_B (1u) +#define ADI_RESULT_REGISTER_SET_C (2u) +#define ADI_RESULT_REGISTER_SET_D (3u) +#define ADI_RESULT_REGISTER_SET_E (4u) +#define ADI_RESULT_REGISTER_SET_F (5u) +/**@}*/ + +/** Generic defines to access the bytes of a register set */ +/**@{*/ +#define ADI_REGISTER_OFFSET0 (0u) +#define ADI_REGISTER_OFFSET1 (1u) +#define ADI_REGISTER_OFFSET2 (2u) +#define ADI_REGISTER_OFFSET3 (3u) +#define ADI_REGISTER_OFFSET4 (4u) +#define ADI_REGISTER_OFFSET5 (5u) +/**@}*/ + +/* 16 bit-values in registers are often stored as two bytes, so the higher byte + must be shifted by 8 bits to reconstruct the value */ +#define ADI_DATA_BUFFER_OFFSET_IN_BITS (8u) + +/** Defines for to access auxiliary register set */ +/**@{*/ +#define ADI_AUXILIARY_RESULT_REGISTER_SET_A (0u) +#define ADI_AUXILIARY_RESULT_REGISTER_SET_B (1u) +#define ADI_AUXILIARY_RESULT_REGISTER_SET_C (2u) +#define ADI_AUXILIARY_RESULT_REGISTER_SET_D (3u) +#define ADI_AUXILIARY_RESULT_REGISTER_SET_E (4u) +/**@}*/ + +/** Mask to select command counter value in received data */ +#define ADI_COMMAND_COUNTER_MASK (0xFCu) +/** Position of command counter in answer byte */ +#define ADI_COMMAND_COUNTER_POSITION (2u) + +/** Command counter loops back to start value when incremented further after having reached this value */ +#define ADI_COMMAND_COUNTER_MAX_VALUE (63u) +/** Command counter loops back to this value when incremented further after having reached max value */ +#define ADI_COMMAND_COUNTER_RESTART_VALUE (1u) +/** Command counter loops set to this value after power cycling, transition to sleep or with RSTCC command */ +#define ADI_COMMAND_COUNTER_RESET_VALUE (0u) + +/** In command definitions, first byte value put at first position */ +#define ADI_COMMAND_BYTE0_POSITION (0u) +/** In command definitions, second byte value put at second position */ +#define ADI_COMMAND_BYTE1_POSITION (1u) +/** In command definitions, INC value put at third position */ +#define ADI_COMMAND_INC_POSITION (2u) +/** In definition of command, position of the length of the data */ +#define ADI_COMMAND_DATA_LENGTH_POSITION (3u) + +/* C-ADC vs S-ADC comparison voltage threshold */ +#define ADI_COMPARISON_THRESHOLD_5_1_mV (0x00u) /* 0b000u */ +#define ADI_COMPARISON_THRESHOLD_8_1_mV (0x01u) /* 0b001u */ +#define ADI_COMPARISON_THRESHOLD_9_1_mV (0x02u) /* 0b010u */ +#define ADI_COMPARISON_THRESHOLD_10_05_mV (0x03u) /* 0b011u */ +#define ADI_COMPARISON_THRESHOLD_15_mV (0x04u) /* 0b100u */ +#define ADI_COMPARISON_THRESHOLD_19_95_mV (0x05u) /* 0b101u */ +#define ADI_COMPARISON_THRESHOLD_25_05_mV (0x06u) /* 0b110u */ +#define ADI_COMPARISON_THRESHOLD_45_05_mV (0x07u) /* 0b111u */ + +/* IIR filter setting */ +#define ADI_IIR_FILTER_DISABLED (0x00u) /* 0b000u */ +#define ADI_IIR_FILTER_PARAMETER_2 (0x01u) /* 0b001u */ +#define ADI_IIR_FILTER_PARAMETER_4 (0x02u) /* 0b010u */ +#define ADI_IIR_FILTER_PARAMETER_8 (0x03u) /* 0b011u */ +#define ADI_IIR_FILTER_PARAMETER_16 (0x04u) /* 0b100u */ +#define ADI_IIR_FILTER_PARAMETER_32 (0x05u) /* 0b101u */ +#define ADI_IIR_FILTER_PARAMETER_128 (0x06u) /* 0b110u */ +#define ADI_IIR_FILTER_PARAMETER_256 (0x07u) /* 0b111u */ + +/** Time to wait for the IIR filter to settle after it was reset and preloaded with samples */ +#define ADI_IIR_SETTLING_TIME_ms (5u) + +/** Time to wait after restarting measurements */ +#define ADI_MEASUREMENT_RESTART_WAIT_TIME_ms (1u) + +/** Time to wait after stopping measurements */ +#define ADI_MEASUREMENT_STOP_WAIT_TIME_ms (1u) + +/** Time to balance after having stopped measurement and before restarting them */ +#define ADI_BALANCING_TIME_ms (20u) + +/* Time in ms needed for a redundant ADC measurement */ +#define ADI_REDUNDANT_ADC_MEASUREMENT_TIME_ms (8u) + +/* Time in ms needed for a redundant ADC measurement in OW latent fault check */ +#define ADI_OW_LATENT_FAULT_MEASUREMENT_TIME_ms (16u) + +/* Commands are made out of 11 bits according to data sheet */ +#define ADI_COMMAND_CODE_LENGTH (11u) + +/* Each command is defined through 4 bytes: 2 command bytes, 1 command counter byte, 1 length byte */ +#define ADI_COMMAND_DEFINITION_LENGTH (4u) + +/* Value used as initialization when creating a mask to set configuration bits in commands */ +#define ADI_COMMAND_MASK_SEED (0xFFFFu) + +/* Value used as initialization when creating a mask to set bits in data written to the AFEs */ +#define ADI_DATA_MASK_SEED (0xFFFFu) + +/* Reset value of registers */ +#define ADI_REGISTER_POR_VALUE (0x7FFFu) + +/* Value of registers after a clear command was issued */ +#define ADI_REGISTER_CLEARED_VALUE (0x8000u) + +/* Time to wait for reference to be on, max 4.5ms */ +#define ADI_TREFUP_ms (5u) + +/* Time to wait after soft reset */ +#define ADI_TSOFTRESET_ms (50u) + +/** + * ades183x command definitions + * @{ + */ +/** Start cell voltage conversion */ +#define ADI_ADCV_BYTE0 (0x02u) /* Table 52 - */ +#define ADI_ADCV_BYTE1 (0x60u) +#define ADI_ADCV_INC (1u) +#define ADI_ADCV_LEN (0u) +/**/ +#define ADI_ADCV_RD_POS (8u) +#define ADI_ADCV_RD_LEN (1u) +#define ADI_ADCV_CONT_POS (7u) +#define ADI_ADCV_CONT_LEN (1u) +#define ADI_ADCV_DCP_POS (4u) +#define ADI_ADCV_DCP_LEN (1u) +#define ADI_ADCV_RSTF_POS (2u) +#define ADI_ADCV_RSTF_LEN (1u) +#define ADI_ADCV_OW01_POS (0u) +#define ADI_ADCV_OW01_LEN (2u) +/**/ +/** Start redundant cell voltage conversion */ +#define ADI_ADSV_BYTE0 (0x01u) +#define ADI_ADSV_BYTE1 (0x68u) +#define ADI_ADSV_INC (1u) +#define ADI_ADSV_LEN (0u) +/**/ +#define ADI_ADSV_CONT_POS (7u) +#define ADI_ADSV_CONT_LEN (1u) +#define ADI_ADSV_DCP_POS (4u) +#define ADI_ADSV_DCP_LEN (1u) +#define ADI_ADSV_OW01_POS (0u) +#define ADI_ADSV_OW01_LEN (2u) +/** Start GPIO voltage conversion */ +#define ADI_ADAX_BYTE0 (0x04u) +#define ADI_ADAX_BYTE1 (0x10u) +#define ADI_ADAX_INC (1u) +#define ADI_ADAX_LEN (0u) +/**/ +#define ADI_ADAX_OW_POS (8u) +#define ADI_ADAX_OW_LEN (1u) +#define ADI_ADAX_PUP_POS (7u) +#define ADI_ADAX_PUP_LEN (1u) +#define ADI_ADAX_CH4_POS (6u) +#define ADI_ADAX_CH4_LEN (1u) +#define ADI_ADAX_CH03_POS (0u) +#define ADI_ADAX_CH03_LEN (4u) +/** Start redundant GPIO voltage conversion */ +#define ADI_ADAX2_BYTE0 (0x04u) +#define ADI_ADAX2_BYTE1 (0x00u) +#define ADI_ADAX2_INC (1u) +#define ADI_ADAX2_LEN (0u) +/**/ +#define ADI_ADAX2_CH03_POS (0u) +#define ADI_ADAX2_CH03_LEN (4u) +/** Write configuration registers */ +#define ADI_WRCFGA_BYTE0 (0x00u) +#define ADI_WRCFGA_BYTE1 (0x01u) +#define ADI_WRCFGA_INC (1u) +#define ADI_WRCFGA_LEN (6u) +/**/ +#define ADI_WRCFGB_BYTE0 (0x00u) +#define ADI_WRCFGB_BYTE1 (0x24u) +#define ADI_WRCFGB_INC (1u) +#define ADI_WRCFGB_LEN (6u) +/** Read configuration registers */ +#define ADI_RDCFGA_BYTE0 (0x00u) +#define ADI_RDCFGA_BYTE1 (0x02u) +#define ADI_RDCFGA_INC (0u) +#define ADI_RDCFGA_LEN (6u) +/**/ +#define ADI_RDCFGB_BYTE0 (0x00u) +#define ADI_RDCFGB_BYTE1 (0x26u) +#define ADI_RDCFGB_INC (0u) +#define ADI_RDCFGB_LEN (6u) +/** Read cell voltage registers */ +#define ADI_RDCVA_BYTE0 (0x00u) +#define ADI_RDCVA_BYTE1 (0x04u) +#define ADI_RDCVA_INC (0u) +#define ADI_RDCVA_LEN (6u) +/**/ +#define ADI_RDCVB_BYTE0 (0x00u) +#define ADI_RDCVB_BYTE1 (0x06u) +#define ADI_RDCVB_INC (0u) +#define ADI_RDCVB_LEN (6u) +/**/ +#define ADI_RDCVC_BYTE0 (0x00u) +#define ADI_RDCVC_BYTE1 (0x08u) +#define ADI_RDCVC_INC (0u) +#define ADI_RDCVC_LEN (6u) +/**/ +#define ADI_RDCVD_BYTE0 (0x00u) +#define ADI_RDCVD_BYTE1 (0x0Au) +#define ADI_RDCVD_INC (0u) +#define ADI_RDCVD_LEN (6u) +/**/ +#define ADI_RDCVE_BYTE0 (0x00u) +#define ADI_RDCVE_BYTE1 (0x09u) +#define ADI_RDCVE_INC (0u) +#define ADI_RDCVE_LEN (6u) +/**/ +#define ADI_RDCVF_BYTE0 (0x00u) +#define ADI_RDCVF_BYTE1 (0x0Bu) +#define ADI_RDCVF_INC (0u) +#define ADI_RDCVF_LEN (6u) +/** Read averaged voltage registers */ +#define ADI_RDACA_BYTE0 (0x00u) +#define ADI_RDACA_BYTE1 (0x44u) +#define ADI_RDACA_INC (0u) +#define ADI_RDACA_LEN (6u) +/**/ +#define ADI_RDACB_BYTE0 (0x00u) +#define ADI_RDACB_BYTE1 (0x46u) +#define ADI_RDACB_INC (0u) +#define ADI_RDACB_LEN (6u) +/**/ +#define ADI_RDACC_BYTE0 (0x00u) +#define ADI_RDACC_BYTE1 (0x48u) +#define ADI_RDACC_INC (0u) +#define ADI_RDACC_LEN (6u) +/**/ +#define ADI_RDACD_BYTE0 (0x00u) +#define ADI_RDACD_BYTE1 (0x4Au) +#define ADI_RDACD_INC (0u) +#define ADI_RDACD_LEN (6u) +/**/ +#define ADI_RDACE_BYTE0 (0x00u) +#define ADI_RDACE_BYTE1 (0x49u) +#define ADI_RDACE_INC (0u) +#define ADI_RDACE_LEN (6u) +/**/ +#define ADI_RDACF_BYTE0 (0x00u) +#define ADI_RDACF_BYTE1 (0x4Bu) +#define ADI_RDACF_INC (0u) +#define ADI_RDACF_LEN (6u) +/** Read filtered voltage registers */ +#define ADI_RDFCA_BYTE0 (0x00u) +#define ADI_RDFCA_BYTE1 (0x12u) +#define ADI_RDFCA_INC (0u) +#define ADI_RDFCA_LEN (6u) +/**/ +#define ADI_RDFCB_BYTE0 (0x00u) +#define ADI_RDFCB_BYTE1 (0x13u) +#define ADI_RDFCB_INC (0u) +#define ADI_RDFCB_LEN (6u) +/**/ +#define ADI_RDFCC_BYTE0 (0x00u) +#define ADI_RDFCC_BYTE1 (0x14u) +#define ADI_RDFCC_INC (0u) +#define ADI_RDFCC_LEN (6u) +/**/ +#define ADI_RDFCD_BYTE0 (0x00u) +#define ADI_RDFCD_BYTE1 (0x15u) +#define ADI_RDFCD_INC (0u) +#define ADI_RDFCD_LEN (6u) +/**/ +#define ADI_RDFCE_BYTE0 (0x00u) +#define ADI_RDFCE_BYTE1 (0x16u) +#define ADI_RDFCE_INC (0u) +#define ADI_RDFCE_LEN (6u) +/**/ +#define ADI_RDFCF_BYTE0 (0x00u) +#define ADI_RDFCF_BYTE1 (0x17u) +#define ADI_RDFCF_INC (0u) +#define ADI_RDFCF_LEN (6u) +/** Read redundant voltage registers */ +#define ADI_RDSVA_BYTE0 (0x00u) +#define ADI_RDSVA_BYTE1 (0x03u) +#define ADI_RDSVA_INC (0u) +#define ADI_RDSVA_LEN (6u) +/**/ +#define ADI_RDSVB_BYTE0 (0x00u) +#define ADI_RDSVB_BYTE1 (0x05u) +#define ADI_RDSVB_INC (0u) +#define ADI_RDSVB_LEN (6u) +/**/ +#define ADI_RDSVC_BYTE0 (0x00u) +#define ADI_RDSVC_BYTE1 (0x07u) +#define ADI_RDSVC_INC (0u) +#define ADI_RDSVC_LEN (6u) +/**/ +#define ADI_RDSVD_BYTE0 (0x00u) +#define ADI_RDSVD_BYTE1 (0x0Du) +#define ADI_RDSVD_INC (0u) +#define ADI_RDSVD_LEN (6u) +/**/ +#define ADI_RDSVE_BYTE0 (0x00u) +#define ADI_RDSVE_BYTE1 (0x0Eu) +#define ADI_RDSVE_INC (0u) +#define ADI_RDSVE_LEN (6u) +/**/ +#define ADI_RDSVF_BYTE0 (0x00u) +#define ADI_RDSVF_BYTE1 (0x0Fu) +#define ADI_RDSVF_INC (0u) +#define ADI_RDSVF_LEN (6u) +/** Snapshot commands */ +#define ADI_SNAPSHOT_BYTE0 (0x00u) +#define ADI_SNAPSHOT_BYTE1 (0x2Du) +#define ADI_SNAPSHOT_INC (1u) +#define ADI_SNAPSHOT_LEN (0u) +#define ADI_UNSNAPSHOT_BYTE0 (0x00u) +#define ADI_UNSNAPSHOT_BYTE1 (0x2Fu) +#define ADI_UNSNAPSHOT_INC (1u) +#define ADI_UNSNAPSHOT_LEN (0u) +/** Read auxiliary registers */ +#define ADI_RDAUXA_BYTE0 (0x00u) +#define ADI_RDAUXA_BYTE1 (0x19u) +#define ADI_RDAUXA_INC (0u) +#define ADI_RDAUXA_LEN (6u) +/**/ +#define ADI_RDAUXB_BYTE0 (0x00u) +#define ADI_RDAUXB_BYTE1 (0x1Au) +#define ADI_RDAUXB_INC (0u) +#define ADI_RDAUXB_LEN (6u) +/**/ +#define ADI_RDAUXC_BYTE0 (0x00u) +#define ADI_RDAUXC_BYTE1 (0x1Bu) +#define ADI_RDAUXC_INC (0u) +#define ADI_RDAUXC_LEN (6u) +/**/ +#define ADI_RDAUXD_BYTE0 (0x00u) +#define ADI_RDAUXD_BYTE1 (0x1Fu) +#define ADI_RDAUXD_INC (0u) +#define ADI_RDAUXD_LEN (6u) +/**/ +#define ADI_RDAUXE_BYTE0 (0x00u) +#define ADI_RDAUXE_BYTE1 (0x36u) +#define ADI_RDAUXE_INC (0u) +#define ADI_RDAUXE_LEN (6u) +/** Read redundant auxiliary registers */ +#define ADI_RDRAXA_BYTE0 (0x00u) +#define ADI_RDRAXA_BYTE1 (0x1Cu) +#define ADI_RDRAXA_INC (0u) +#define ADI_RDRAXA_LEN (6u) +/**/ +#define ADI_RDRAXB_BYTE0 (0x00u) +#define ADI_RDRAXB_BYTE1 (0x1Du) +#define ADI_RDRAXB_INC (0u) +#define ADI_RDRAXB_LEN (6u) +/**/ +#define ADI_RDRAXC_BYTE0 (0x00u) +#define ADI_RDRAXC_BYTE1 (0x1Eu) +#define ADI_RDRAXC_INC (0u) +#define ADI_RDRAXC_LEN (6u) +/**/ +#define ADI_RDRAXD_BYTE0 (0x00u) +#define ADI_RDRAXD_BYTE1 (0x25u) +#define ADI_RDRAXD_INC (0u) +#define ADI_RDRAXD_LEN (6u) +/** Clear AUX registers */ +#define ADI_CLRAUX_BYTE0 (0x07u) +#define ADI_CLRAUX_BYTE1 (0x12u) +#define ADI_CLRAUX_INC (1u) +#define ADI_CLRAUX_LEN (0u) +/** Write PWM registers */ +#define ADI_WRPWMA_BYTE0 (0x00u) +#define ADI_WRPWMA_BYTE1 (0x20u) +#define ADI_WRPWMA_INC (1u) +#define ADI_WRPWMA_LEN (6u) +#define ADI_WRPWMB_BYTE0 (0x00u) +#define ADI_WRPWMB_BYTE1 (0x21u) +#define ADI_WRPWMB_INC (1u) +#define ADI_WRPWMB_LEN (6u) +/** Read PWM registers */ +#define ADI_RDPWMA_BYTE0 (0x00u) +#define ADI_RDPWMA_BYTE1 (0x22u) +#define ADI_RDPWMA_INC (0u) +#define ADI_RDPWMA_LEN (6u) +#define ADI_RDPWMB_BYTE0 (0x00u) +#define ADI_RDPWMB_BYTE1 (0x23u) +#define ADI_RDPWMB_INC (0u) +#define ADI_RDPWMB_LEN (6u) +/** Mute discharge */ +#define ADI_MUTE_BYTE0 (0x00u) +#define ADI_MUTE_BYTE1 (0x28u) +#define ADI_MUTE_INC (1u) +#define ADI_MUTE_LEN (0u) +/** Unmute discharge */ +#define ADI_UNMUTE_BYTE0 (0x00u) +#define ADI_UNMUTE_BYTE1 (0x29u) +#define ADI_UNMUTE_INC (1u) +#define ADI_UNMUTE_LEN (0u) +/** Clear command counter */ +#define ADI_RSTCC_BYTE0 (0x00u) +#define ADI_RSTCC_BYTE1 (0x2Eu) +#define ADI_RSTCC_INC (0u) +#define ADI_RSTCC_LEN (0u) +/** Clear cell registers */ +#define ADI_CLRCELL_BYTE0 (0x07u) +#define ADI_CLRCELL_BYTE1 (0x11u) +#define ADI_CLRCELL_INC (1u) +#define ADI_CLRCELL_LEN (0u) +/** Clear flags in Status Register Group C */ +#define ADI_CLRFLAG_BYTE0 (0x07u) +#define ADI_CLRFLAG_BYTE1 (0x17u) +#define ADI_CLRFLAG_INC (1u) +#define ADI_CLRFLAG_LEN (6u) +/**/ +#define ADI_CLRFLAG_DATA_LENGTH (6u) +/** Read status register */ +#define ADI_RDSTATA_BYTE0 (0x00u) +#define ADI_RDSTATA_BYTE1 (0x30u) +#define ADI_RDSTATA_INC (0u) +#define ADI_RDSTATA_LEN (6u) +/**/ +#define ADI_RDSTATB_BYTE0 (0x00u) +#define ADI_RDSTATB_BYTE1 (0x31u) +#define ADI_RDSTATB_INC (0u) +#define ADI_RDSTATB_LEN (6u) +/**/ +#define ADI_RDSTATC_BYTE0 (0x00u) +#define ADI_RDSTATC_BYTE1 (0x32u) +#define ADI_RDSTATC_INC (0u) +#define ADI_RDSTATC_LEN (6u) +/**/ +#define ADI_RDSTATC_ERR_POS (6u) +#define ADI_RDSTATC_ERR_LEN (1u) +/**/ +#define ADI_RDSTATD_BYTE0 (0x00u) +#define ADI_RDSTATD_BYTE1 (0x33u) +#define ADI_RDSTATD_INC (0u) +#define ADI_RDSTATD_LEN (6u) +/**/ +#define ADI_RDSTATE_BYTE0 (0x00u) +#define ADI_RDSTATE_BYTE1 (0x34u) +#define ADI_RDSTATE_INC (0u) +#define ADI_RDSTATE_LEN (6u) +/** Read serial ID */ +#define ADI_RDSID_BYTE0 (0x00u) +#define ADI_RDSID_BYTE1 (0x2Cu) +#define ADI_RDSID_INC (0u) +#define ADI_RDSID_LEN (6u) +/** Soft Reset */ +#define ADI_SRST_BYTE0 (0x00u) +#define ADI_SRST_BYTE1 (0x27u) +#define ADI_SRST_INC (0u) +#define ADI_SRST_LEN (0u) +/**@}*/ + +/* Configuration Register A */ +/* CFGRA0 */ +#define ADI_CFGRA0_CTH_0_2_POS (0u) +#define ADI_CFGRA0_CTH_0_2_MASK (0x7u) +#define ADI_CFGRA0_REFON_POS (7u) +#define ADI_CFGRA0_REFON_MASK (0x80u) +/* CFGRA1 */ +#define ADI_CFGRA1_FLAG_D_0_7_POS (0u) +#define ADI_CFGRA1_FLAG_D_0_7_MASK (0xFFu) +/* CFGRA2 */ +#define ADI_CFGRA2_OWA_0_2_POS (3u) +#define ADI_CFGRA2_OWA_0_2_MASK (0x38u) +#define ADI_CFGRA2_OWRNG_POS (6u) +#define ADI_CFGRA2_OWRNG_MASK (0x40u) +#define ADI_CFGRA2_SOAKON_POS (7u) +#define ADI_CFGRA2_SOAKON_MASK (0x80u) +/* CFGRA3 */ +#define ADI_CFGRA3_GPO_1_8_POS (0u) +#define ADI_CFGRA3_GPO_1_8_MASK (0xFFu) +/* CFGRA4 */ +#define ADI_CFGRA4_GPO_9_10_POS (0u) +#define ADI_CFGRA4_GPO_9_10_MASK (0x3u) +/* CFGRA5 */ +#define ADI_CFGRA5_FC_0_2_POS (0u) +#define ADI_CFGRA5_FC_0_2_MASK (0x7u) +#define ADI_CFGRA5_COMM_BK_POS (3u) +#define ADI_CFGRA5_COMM_BK_MASK (0x8u) +#define ADI_CFGRA5_MUTE_ST_POS (4u) +#define ADI_CFGRA5_MUTE_ST_MASK (0x10u) +#define ADI_CFGRA5_SNAP_ST_POS (5u) +#define ADI_CFGRA5_SNAP_ST_MASK (0x20u) + +/* Configuration Register B */ +/* CFGRB0 */ +#define ADI_CFGRB0_VUV_0_7_POS (0u) +#define ADI_CFGRB0_VUV_0_7_MASK (0xFFu) +/* CFGRB1 */ +#define ADI_CFGRB1_VUV_8_11_POS (0u) +#define ADI_CFGRB1_VUV_8_11_MASK (0xFu) +#define ADI_CFGRB1_VOV_0_3_POS (4u) +#define ADI_CFGRB1_VOV_0_3_MASK (0xF0u) +/* CFGRB2 */ +#define ADI_CFGRB2_VOV_4_11_POS (0u) +#define ADI_CFGRB2_VOV_4_11_MASK (0xFFu) +/* CFGRB3 */ +#define ADI_CFGRB3_DCT0_0_5_POS (0u) +#define ADI_CFGRB3_DCT0_0_5_MASK (0x3Fu) +#define ADI_CFGRB3_DTRNG_POS (6u) +#define ADI_CFGRB3_DTRNG_MASK (0x40u) +#define ADI_CFGRB3_DTMEN_POS (7u) +#define ADI_CFGRB3_DTMEN_MASK (0x80u) +/* CFGRB4 */ +#define ADI_CFGRB4_DCC_1_8_POS (0u) +#define ADI_CFGRB4_DCC_1_8_MASK (0xFFu) +/* CFGRB5 */ +#define ADI_CFGRB5_DCC_9_16_POS (0u) +#define ADI_CFGRB5_DCC_9_16_MASK (0xFFu) + +/* Status Register A */ +/* STAR0 */ +#define ADI_STAR0_VREF2_0_7_POS (0u) +#define ADI_STAR0_VREF2_0_7_MASK (0xFFu) +/* STAR1 */ +#define ADI_STAR1_VREF2_8_15_POS (0u) +#define ADI_STAR1_VREF2_8_15_MASK (0xFFu) +/* STAR2 */ +#define ADI_STAR2_ITMP_0_7_POS (0u) +#define ADI_STAR2_ITMP_0_7_MASK (0xFFu) +/* STAR3 */ +#define ADI_STAR3_ITMP_8_15_POS (0u) +#define ADI_STAR3_ITMP_8_15_MASK (0xFFu) + +/* Status Register B */ +/* STBR0 */ +#define ADI_STBR0_VD_0_7_POS (0u) +#define ADI_STBR0_VD_0_7_MASK (0xFFu) +/* STBR1 */ +#define ADI_STBR1_VD_8_15_POS (0u) +#define ADI_STBR1_VD_8_15_MASK (0xFFu) +/* STBR2 */ +#define ADI_STBR2_VA_0_7_POS (0u) +#define ADI_STBR2_VA_0_7_MASK (0xFFu) +/* STBR3 */ +#define ADI_STBR3_VA_8_15_POS (0u) +#define ADI_STBR3_VA_8_15_MASK (0xFFu) +/* STBR4 */ +#define ADI_STBR4_VRES_0_7_POS (0u) +#define ADI_STBR4_VRES_0_7_MASK (0xFFu) +/* STBR5 */ +#define ADI_STBR5_VRES_8_15_POS (0u) +#define ADI_STBR5_VRES_8_15_MASK (0xFFu) + +/* Status Register C */ +/* STCR0 */ +#define ADI_STCR0_CS1FLT_POS (0u) +#define ADI_STCR0_CS1FLT_MASK (0x01u) +#define ADI_STCR0_CS2FLT_POS (1u) +#define ADI_STCR0_CS2FLT_MASK (0x02u) +#define ADI_STCR0_CS3FLT_POS (2u) +#define ADI_STCR0_CS3FLT_MASK (0x04u) +#define ADI_STCR0_CS4FLT_POS (3u) +#define ADI_STCR0_CS4FLT_MASK (0x08u) +#define ADI_STCR0_CS5FLT_POS (4u) +#define ADI_STCR0_CS5FLT_MASK (0x10u) +#define ADI_STCR0_CS6FLT_POS (5u) +#define ADI_STCR0_CS6FLT_MASK (0x20u) +#define ADI_STCR0_CS7FLT_POS (6u) +#define ADI_STCR0_CS7FLT_MASK (0x40u) +#define ADI_STCR0_CS8FLT_POS (7u) +#define ADI_STCR0_CS8FLT_MASK (0x80u) +/* STCR1 */ +#define ADI_STCR1_CS9FLT_POS (0u) +#define ADI_STCR1_CS9FLT_MASK (0x01u) +#define ADI_STCR1_CS10FLT_POS (1u) +#define ADI_STCR1_CS10FLT_MASK (0x02u) +#define ADI_STCR1_CS11FLT_POS (2u) +#define ADI_STCR1_CS11FLT_MASK (0x04u) +#define ADI_STCR1_CS12FLT_POS (3u) +#define ADI_STCR1_CS12FLT_MASK (0x08u) +#define ADI_STCR1_CS13FLT_POS (4u) +#define ADI_STCR1_CS13FLT_MASK (0x10u) +#define ADI_STCR1_CS14FLT_POS (5u) +#define ADI_STCR1_CS14FLT_MASK (0x20u) +#define ADI_STCR1_CS15FLT_POS (6u) +#define ADI_STCR1_CS15FLT_MASK (0x40u) +#define ADI_STCR1_CS16FLT_POS (7u) +#define ADI_STCR1_CS16FLT_MASK (0x80u) +/* STCR2 */ +#define ADI_STCR2_CT_6_10_POS (0u) +#define ADI_STCR2_CT_6_10_MASK (0x1Fu) +/* STCR3 */ +#define ADI_STCR3_CTS_0_1_POS (0u) +#define ADI_STCR3_CTS_0_1_MASK (0x03u) +#define ADI_STCR3_CT_0_5_POS (2u) +#define ADI_STCR3_CT_0_5_MASK (0xFCu) +/* STCR4 */ +#define ADI_STCR4_SMED_POS (0u) +#define ADI_STCR4_SMED_MASK (0x01u) +#define ADI_STCR4_SED_POS (1u) +#define ADI_STCR4_SED_MASK (0x02u) +#define ADI_STCR4_CMED_POS (2u) +#define ADI_STCR4_CMED_MASK (0x04u) +#define ADI_STCR4_CED_POS (3u) +#define ADI_STCR4_CED_MASK (0x08u) +#define ADI_STCR4_VD_UV_POS (4u) +#define ADI_STCR4_VD_UV_MASK (0x10u) +#define ADI_STCR4_VD_OV_POS (5u) +#define ADI_STCR4_VD_OV_MASK (0x20u) +#define ADI_STCR4_VA_UV_POS (6u) +#define ADI_STCR4_VA_UV_MASK (0x40u) +#define ADI_STCR4_VA_OV_POS (7u) +#define ADI_STCR4_VA_OV_MASK (0x80u) +/* STCR5 */ +#define ADI_STCR5_OSCCHK_POS (0u) +#define ADI_STCR5_OSCCHK_MASK (0x01u) +#define ADI_STCR5_TMODCHK_POS (1u) +#define ADI_STCR5_TMODCHK_MASK (0x02u) +#define ADI_STCR5_THSD_POS (2u) +#define ADI_STCR5_THSD_MASK (0x04u) +#define ADI_STCR5_SLEEP_POS (3u) +#define ADI_STCR5_SLEEP_MASK (0x08u) +#define ADI_STCR5_SPIFLT_POS (4u) +#define ADI_STCR5_SPIFLT_MASK (0x10u) +#define ADI_STCR5_COMP_POS (5u) +#define ADI_STCR5_COMP_MASK (0x20u) +#define ADI_STCR5_VDE_POS (6u) +#define ADI_STCR5_VDE_MASK (0x40u) +#define ADI_STCR5_VDEL_POS (7u) +#define ADI_STCR5_VDEL_MASK (0x80u) + +/* Status Register D */ +/* STDR0 */ +#define ADI_STDR0_C1UV_POS (0u) +#define ADI_STDR0_C1UV_MASK (0x01u) +#define ADI_STDR0_C1OV_POS (1u) +#define ADI_STDR0_C1OV_MASK (0x02u) +#define ADI_STDR0_C2UV_POS (2u) +#define ADI_STDR0_C2UV_MASK (0x04u) +#define ADI_STDR0_C2OV_POS (3u) +#define ADI_STDR0_C2OV_MASK (0x08u) +#define ADI_STDR0_C3UV_POS (4u) +#define ADI_STDR0_C3UV_MASK (0x10u) +#define ADI_STDR0_C3OV_POS (5u) +#define ADI_STDR0_C3OV_MASK (0x20u) +#define ADI_STDR0_C4UV_POS (6u) +#define ADI_STDR0_C4UV_MASK (0x40u) +#define ADI_STDR0_C4OV_POS (7u) +#define ADI_STDR0_C4OV_MASK (0x80u) +/* STDR1 */ +#define ADI_STDR1_C5UV_POS (0u) +#define ADI_STDR1_C5UV_MASK (0x01u) +#define ADI_STDR1_C50OV_POS (1u) +#define ADI_STDR1_C50OV_MASK (0x02u) +#define ADI_STDR1_C6UV_POS (2u) +#define ADI_STDR1_C6UV_MASK (0x04u) +#define ADI_STDR1_C6OV_POS (3u) +#define ADI_STDR1_C6OV_MASK (0x08u) +#define ADI_STDR1_C7UV_POS (4u) +#define ADI_STDR1_C7UV_MASK (0x10u) +#define ADI_STDR1_C7OV_POS (5u) +#define ADI_STDR1_C7OV_MASK (0x20u) +#define ADI_STDR1_C8UV_POS (6u) +#define ADI_STDR1_C8UV_MASK (0x40u) +#define ADI_STDR1_C8OV_POS (7u) +#define ADI_STDR1_C8OV_MASK (0x80u) +/* STDR2 */ +#define ADI_STDR2_C9UV_POS (0u) +#define ADI_STDR2_C9UV_MASK (0x01u) +#define ADI_STDR2_C9OV_POS (1u) +#define ADI_STDR2_C9OV_MASK (0x02u) +#define ADI_STDR2_C10UV_POS (2u) +#define ADI_STDR2_C10UV_MASK (0x04u) +#define ADI_STDR2_C10OV_POS (3u) +#define ADI_STDR2_C10OV_MASK (0x08u) +#define ADI_STDR2_C11UV_POS (4u) +#define ADI_STDR2_C11UV_MASK (0x10u) +#define ADI_STDR2_C11OV_POS (5u) +#define ADI_STDR2_C11OV_MASK (0x20u) +#define ADI_STDR2_C12UV_POS (6u) +#define ADI_STDR2_C12UV_MASK (0x40u) +#define ADI_STDR2_C12OV_POS (7u) +#define ADI_STDR2_C12OV_MASK (0x80u) +/* STDR3 */ +#define ADI_STDR3_C13UV_POS (0u) +#define ADI_STDR3_C13UV_MASK (0x01u) +#define ADI_STDR3_C13OV_POS (1u) +#define ADI_STDR3_C13OV_MASK (0x02u) +#define ADI_STDR3_C14UV_POS (2u) +#define ADI_STDR3_C14UV_MASK (0x04u) +#define ADI_STDR3_C14OV_POS (3u) +#define ADI_STDR3_C14OV_MASK (0x08u) +#define ADI_STDR3_C15UV_POS (4u) +#define ADI_STDR3_C15UV_MASK (0x10u) +#define ADI_STDR3_C15OV_POS (5u) +#define ADI_STDR3_C15OV_MASK (0x20u) +#define ADI_STDR3_C16UV_POS (6u) +#define ADI_STDR3_C16UV_MASK (0x40u) +#define ADI_STDR3_C16OV_POS (7u) +#define ADI_STDR3_C16OV_MASK (0x80u) +/* STDR5 */ +#define ADI_STDR5_OC_CNTR_0_7_POS (0u) +#define ADI_STDR5_OC_CNTR_0_7_MASK (0xFFu) + +/* Status Register E */ +/* STER4 */ +#define ADI_STER4_GPI_1_8_POS (0u) +#define ADI_STER4_GPI_1_8_MASK (0xFFu) +/* STER5 */ +#define ADI_STER5_GPI_9_10_POS (0u) +#define ADI_STER5_GPI_9_10_MASK (0x03u) +#define ADI_STER5_REV_0_3_POS (4u) +#define ADI_STER5_REV_0_3_MASK (0xF0u) + +/*========== Extern Constant and Variable Declarations ======================*/ + +/** Used to choose which configuration register must be addressed */ +typedef enum { + ADI_CFG_REGISTER_SET_A, + ADI_CFG_REGISTER_SET_B, + ADI_CFG_REGISTER_SET_E_MAX, +} ADI_CFG_REGISTER_SET_e; + +/* If needed, add definition of database entries here */ + +/** This struct contains pointer to used data buffers */ +typedef struct { + uint16_t *txBuffer; + uint16_t *rxBuffer; + DATA_BLOCK_CELL_VOLTAGE_s *cellVoltage; + DATA_BLOCK_CELL_VOLTAGE_s *cellVoltageAverage; + DATA_BLOCK_CELL_VOLTAGE_s *cellVoltageFiltered; + DATA_BLOCK_CELL_VOLTAGE_s *cellVoltageRedundant; + DATA_BLOCK_CELL_TEMPERATURE_s *cellTemperature; + DATA_BLOCK_BALANCING_CONTROL_s *balancingControl; + DATA_BLOCK_ALL_GPIO_VOLTAGES_s *allGpioVoltages; + DATA_BLOCK_ALL_GPIO_VOLTAGES_s *allGpioVoltagesRedundant; + DATA_BLOCK_CELL_VOLTAGE_s *cellVoltageOpenWireEven; + DATA_BLOCK_CELL_VOLTAGE_s *cellVoltageOpenWireOdd; + DATA_BLOCK_CELL_VOLTAGE_s *cellVoltageAverageOpenWire; + DATA_BLOCK_CELL_VOLTAGE_s *cellVoltageRedundantOpenWire; + DATA_BLOCK_ALL_GPIO_VOLTAGES_s *allGpioVoltageOpenWire; + DATA_BLOCK_OPEN_WIRE_s *openWire; + uint8_t commandCounter[BS_NR_OF_STRINGS][ADI_N_ADI]; + ADI_ERROR_TABLE_s *errorTable; +} ADI_DATA_s; + +/** + * This structure contains all the variables relevant for the ades183x state machine. + * The user can get the current state of the ades183x state machine with this variable + */ +typedef struct { + bool measurementStarted; /*!< flag indicates that the driver has received the request to start measurements */ + bool firstMeasurementMade; /*!< flag indicates if first measurement cycle was completed for all strings */ + bool firstDiagnosticMade; /*!< flag indicates if all diagnostics made at least one time for all strings */ + uint8_t spiNumberInterfaces; /*!< number of SPI channels that have to be measured */ + uint8_t currentString; /*!< string currently being addressed */ + uint8_t redundantAuxiliaryChannel + [BS_NR_OF_STRINGS]; /*!< auxiliary channel for which a redundant measurement must be made */ + uint64_t serialId[BS_NR_OF_STRINGS][ADI_N_ADI]; /*!< serial ID of the IC */ + uint8_t revision[BS_NR_OF_STRINGS][ADI_N_ADI]; /*!< revision of the IC */ + ADI_DATA_s data; /*!< contains pointers to the local data buffer */ +} ADI_STATE_s; + +/*========== Extern Function Prototypes =====================================*/ + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +#endif + +#endif /* FOXBMS__ADI_ADES183X_DEFS_H_ */ diff --git a/src/app/driver/afe/maxim/common/mxm_afe_dma.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_diagnostic.h similarity index 70% rename from src/app/driver/afe/maxim/common/mxm_afe_dma.h rename to src/app/driver/afe/adi/common/ades183x/adi_ades183x_diagnostic.h index 1966cedc..dd8dc0e8 100644 --- a/src/app/driver/afe/maxim/common/mxm_afe_dma.h +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_diagnostic.h @@ -40,25 +40,29 @@ */ /** - * @file mxm_afe_dma.h + * @file adi_ades183x_diagnostic.h * @author foxBMS Team - * @date 2020-06-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2022-12-06 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS - * @prefix AFE + * @prefix ADI * - * @brief Headers for the driver for the DMA module for the Maxim driver. + * @brief Headers for the diagnostic driver for the ADI analog front-end. * */ -#ifndef FOXBMS__MXM_AFE_DMA_H_ -#define FOXBMS__MXM_AFE_DMA_H_ +#ifndef FOXBMS__ADI_ADES183X_DIAGNOSTIC_H_ +#define FOXBMS__ADI_ADES183X_DIAGNOSTIC_H_ /*========== Includes =======================================================*/ /* clang-format off */ -#include "afe_dma.h" +#include "adi_ades183x_cfg.h" /* clang-format on */ + +#include "adi_ades183x_defs.h" + +#include #include /*========== Macros and Definitions =========================================*/ @@ -67,8 +71,23 @@ /*========== Extern Function Prototypes =====================================*/ +/** + * @brief Make diagnostics with the built-in AFE functions. + * @param adiState state of the adi driver + */ +extern void ADI_Diagnostic(ADI_STATE_s *adiState); + +/** + * @brief Evaluate diagnostic for cell voltage measurement + * @param adiState state of the adi driver + * @param moduleNumber module number the diagnostics shall be checked for + */ +extern bool ADI_EvaluateDiagnosticCellVoltages(ADI_STATE_s *adiState, uint16_t moduleNumber); + /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST +extern bool TEST_ADI_IsFirstDiagnosticCycleFinished(ADI_STATE_s *adiState); +extern void TEST_ADI_SetFirstDiagnosticCycleFinished(ADI_STATE_s *adiState); #endif -#endif /* FOXBMS__MXM_AFE_DMA_H_ */ +#endif /* FOXBMS__ADI_ADES183X_DIAGNOSTIC_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_diagnostic_w.c b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_diagnostic_w.c new file mode 100644 index 00000000..374f0085 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_diagnostic_w.c @@ -0,0 +1,93 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_diagnostic_w.c + * @author foxBMS Team + * @date 2023-10-09 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Dummy diagnostics driver for the ADI analog front end. + * + */ + +/*========== Includes =======================================================*/ +#include "adi_ades183x_defs.h" +#include "adi_ades183x_diagnostic.h" +#include "fassert.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +extern void ADI_Diagnostic(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); +} + +extern bool ADI_EvaluateDiagnosticCellVoltages(ADI_STATE_s *adiState, uint16_t moduleNumber) { + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(moduleNumber < BS_NR_OF_MODULES_PER_STRING); + bool retVal = false; + if ((adiState->data.errorTable->crcIsOk[adiState->currentString][moduleNumber] == true) && + (adiState->data.errorTable->voltageRegisterContentIsNotStuck[adiState->currentString][moduleNumber] == true)) { + retVal = true; + } + return retVal; +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST + +#endif diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_gpio_voltages.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_gpio_voltages.h new file mode 100644 index 00000000..1d7c4073 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_gpio_voltages.h @@ -0,0 +1,93 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_gpio_voltages.h + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Header file of some software + * + */ + +#ifndef FOXBMS__ADI_ADES183X_GPIO_VOLTAGES_H_ +#define FOXBMS__ADI_ADES183X_GPIO_VOLTAGES_H_ + +/*========== Includes =======================================================*/ + +#include "adi_ades183x_defs.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Extern Constant and Variable Declarations ======================*/ + +/*========== Extern Function Prototypes =====================================*/ + +/** + * @brief Stores GPIO voltages. + * @details This function, reads the raw values from the registers, and + * calls ADI_SaveRxToGpioVoltageBuffer() which convert them into + * voltages and stores them. + * @param adiState state of the ADI driver + * @param registerType type of auxiliary register to read + * @param storeLocation location where read data has to be stored + */ +extern void ADI_GetGpioVoltages( + ADI_STATE_s *adiState, + ADI_AUXILIARY_REGISTER_TYPE_e registerType, + ADI_AUXILIARY_STORE_LOCATION_e storeLocation); + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_ADI_SaveRxToGpioVoltageBuffer( + ADI_STATE_s *adiState, + uint8_t *data, + uint8_t registerSet, + ADI_AUXILIARY_STORE_LOCATION_e storeLocation); +#endif + +#endif /* FOXBMS__ADI_ADES183X_GPIO_VOLTAGES_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_helpers.c b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_helpers.c new file mode 100644 index 00000000..b0e1ffc6 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_helpers.c @@ -0,0 +1,691 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_helpers.c + * @author foxBMS Team + * @date 2022-12-06 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Helper functionalities specific to the driver for the ADI ades183x + * + */ + +/*========== Includes =======================================================*/ +/* clang-format off */ +#include "adi_ades183x.h" +/* clang-format on */ + +#include "adi_ades183x_helpers.h" + +#include "adi_ades183x_buffers.h" +#include "adi_ades183x_commands.h" +#include "adi_ades183x_pec.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/** + * @brief Increment command counter of AFE driver. + * @param adiState state of the driver + */ +static void ADI_IncrementCommandCounter(ADI_STATE_s *adiState); + +/** + * @brief Writes data in the configuration stored in AFE driver, + * for a specific AFE. + * @details The driver stores the AFE configuration to write to the AFEs. + * This function sets the data for a specific register for a specific + * AFE in the daisy chain. The parameter registerSet selects one + * configuration register (A or B). Offset corresponds to one of the + * bytes in the selected register. + * @param module module number + * @param registerSet configuration register to address + * @param registerOffset position of byte to address in configuration register + * @param data data to write to byte in register + * @param position position where to store the data in byte + * @param mask mask corresponding to data to store + * @param adiState state of the driver + */ +static void ADI_StoredConfigurationFillRegisterData( + uint8_t module, + ADI_CFG_REGISTER_SET_e registerSet, + uint8_t registerOffset, + uint8_t data, + uint8_t position, + uint8_t mask, + ADI_STATE_s *adiState); + +/*========== Static Function Implementations ================================*/ +static void ADI_StoredConfigurationFillRegisterData( + uint8_t module, + ADI_CFG_REGISTER_SET_e registerSet, + uint8_t registerOffset, + uint8_t data, + uint8_t position, + uint8_t mask, + ADI_STATE_s *adiState) { + /* AXIVION Routine Generic-MissingParameterAssert: module: parameter accepts whole range */ + /* AXIVION Routine Generic-MissingParameterAssert: data: parameter accepts whole range */ + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(registerSet <= ADI_CFG_REGISTER_SET_B); + /* Only 8 bit in a register part */ + FAS_ASSERT(position <= ADI_MAX_BIT_POSITION_IN_BYTE); + /* All 0s mask would mean do nothing */ + FAS_ASSERT(mask > 0u); + FAS_ASSERT(registerOffset <= ADI_REGISTER_OFFSET5); + + if (registerSet == ADI_CFG_REGISTER_SET_A) { + ADI_WriteDataBits( + &adi_configurationRegisterAgroup[adiState->currentString][(module * ADI_WRCFGA_LEN) + registerOffset], + data, + position, + mask); + } else if (registerSet == ADI_CFG_REGISTER_SET_B) { + ADI_WriteDataBits( + &adi_configurationRegisterBgroup[adiState->currentString][(module * ADI_WRCFGB_LEN) + registerOffset], + data, + position, + mask); + } else { /* invalid register set */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + } +} + +static void ADI_IncrementCommandCounter(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /** + * SM_SPI_CNT: SPI Frame Counter + * Increment driver stored value of command counter if command causes increase. + */ + for (uint16_t i = 0u; i < ADI_N_ADI; i++) { + if (adiState->data.commandCounter[adiState->currentString][i] < ADI_COMMAND_COUNTER_MAX_VALUE) { + adiState->data.commandCounter[adiState->currentString][i]++; + } else { + adiState->data.commandCounter[adiState->currentString][i] = ADI_COMMAND_COUNTER_RESTART_VALUE; + } + } +} + +/*========== Extern Function Implementations ================================*/ +extern STD_RETURN_TYPE_e ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_e registerSet, ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(registerSet <= ADI_CFG_REGISTER_SET_B); + + STD_RETURN_TYPE_e returnValue = STD_OK; + bool configurationAIsOk = true; + bool configurationBIsOk = true; + + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Test configuration register A */ + for (uint8_t byte = 0; byte < ADI_WRCFGA_LEN; byte++) { + if (adi_configurationRegisterAgroup[adiState->currentString][byte + (m * ADI_WRCFGA_LEN)] != + adi_readConfigurationRegisterAgroup[adiState->currentString][byte + (m * ADI_WRCFGA_LEN)]) { + configurationAIsOk = false; + returnValue = STD_NOT_OK; + break; + } + } + if (configurationAIsOk == false) { + adiState->data.errorTable->configurationAIsOk[adiState->currentString][m] = false; + } else { + adiState->data.errorTable->configurationAIsOk[adiState->currentString][m] = true; + } + configurationAIsOk = true; + /* Test configuration register B */ + for (uint8_t byte = 0; byte < ADI_WRCFGA_LEN; byte++) { + if (adi_configurationRegisterBgroup[adiState->currentString][byte + (m * ADI_WRCFGB_LEN)] != + adi_readConfigurationRegisterBgroup[adiState->currentString][byte + (m * ADI_WRCFGB_LEN)]) { + configurationBIsOk = false; + returnValue = STD_NOT_OK; + break; + } + } + if (configurationBIsOk == false) { + adiState->data.errorTable->configurationBIsOk[adiState->currentString][m] = false; + } else { + adiState->data.errorTable->configurationBIsOk[adiState->currentString][m] = true; + } + configurationBIsOk = true; + } + return returnValue; +} + +extern void ADI_WriteCommandConfigurationBits( + uint16_t *configuredCommand, + uint8_t position, + uint8_t length, + uint16_t configuration) { + FAS_ASSERT(configuredCommand != NULL_PTR); + FAS_ASSERT(length > 0u); + FAS_ASSERT(length <= ADI_COMMAND_CODE_LENGTH); + FAS_ASSERT(position <= (ADI_COMMAND_CODE_LENGTH - 1u)); + FAS_ASSERT(configuration <= (~(ADI_DATA_MASK_SEED << length))); + + uint16_t command = (((uint16_t)configuredCommand[ADI_COMMAND_FIRST_BYTE_POSITION]) << ADI_BYTE_SHIFT) | + configuredCommand[ADI_COMMAND_SECOND_BYTE_POSITION]; + uint16_t mask = (~(ADI_COMMAND_MASK_SEED << length)) << position; + /* Set bits to modify to 0 */ + command &= ~mask; + /* Now set bits, works if 0 or not */ + command |= (configuration << position) & mask; + configuredCommand[ADI_COMMAND_FIRST_BYTE_POSITION] = (command >> ADI_BYTE_SHIFT) & ADI_ONE_BYTE_MASK; + configuredCommand[ADI_COMMAND_SECOND_BYTE_POSITION] = command & ADI_ONE_BYTE_MASK; +} + +extern STD_RETURN_TYPE_e ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_e registerSet, ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(registerSet <= ADI_CFG_REGISTER_SET_B); + STD_RETURN_TYPE_e returnValueA = STD_OK; + STD_RETURN_TYPE_e returnValueB = STD_OK; + STD_RETURN_TYPE_e returnValue = STD_OK; + + if (registerSet == ADI_CFG_REGISTER_SET_A) { + ADI_WriteRegister( + adi_cmdWrcfga, + adi_configurationRegisterAgroup[adiState->currentString], + ADI_PEC_NO_FAULT_INJECTION, + adiState); + ADI_CopyCommandBits(adi_cmdRdcfga, adi_command); + ADI_ReadRegister(adi_command, adi_readConfigurationRegisterAgroup[adiState->currentString], adiState); + returnValueA = ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_A, adiState); + } else if (registerSet == ADI_CFG_REGISTER_SET_B) { + ADI_WriteRegister( + adi_cmdWrcfgb, + adi_configurationRegisterBgroup[adiState->currentString], + ADI_PEC_NO_FAULT_INJECTION, + adiState); + ADI_CopyCommandBits(adi_cmdRdcfgb, adi_command); + ADI_ReadRegister(adi_command, adi_readConfigurationRegisterBgroup[adiState->currentString], adiState); + returnValueB = ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_B, adiState); + } else { /* invalid register set */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + } + if ((returnValueA == STD_NOT_OK) || (returnValueB == STD_NOT_OK)) { + returnValue = STD_NOT_OK; + } + return returnValue; +} + +extern void ADI_CopyCommandBits(const uint16_t *sourceCommand, uint16_t *destinationCommand) { + FAS_ASSERT(sourceCommand != NULL_PTR); + FAS_ASSERT(destinationCommand != NULL_PTR); + for (uint8_t i = 0u; i < ADI_COMMAND_DEFINITION_LENGTH; i++) { + destinationCommand[i] = sourceCommand[i]; + } +} + +extern void ADI_ReadDataBits(uint8_t receivedData, uint8_t *pDataToRead, uint8_t position, uint8_t mask) { + /* AXIVION Routine Generic-MissingParameterAssert: receivedData: parameter accepts whole range */ + FAS_ASSERT(pDataToRead != NULL_PTR); + /* Only 8 bit in a register part */ + FAS_ASSERT(position <= ADI_MAX_BIT_POSITION_IN_BYTE); + /* All 0s mask would mean do nothing */ + FAS_ASSERT(mask > 0u); + + *pDataToRead = (receivedData & mask) >> position; +} + +/* RequirementId: D7.1 V0R4 FUN-0.0.01.01 */ +/* RequirementId: D7.1 V0R4 SIF-4.10.01.01 */ +/* RequirementId: D7.1 V0R4 SIF-4.10.02.01 */ +/* RequirementId: D7.1 V0R4 SIF-4.10.11.02 */ +/* RequirementId: D7.1 V0R4 SIF-4.10.12.01 */ +extern void ADI_ReadRegister(uint16_t *registerToRead, uint8_t *data, ADI_STATE_s *adiState) { + FAS_ASSERT(registerToRead != NULL_PTR); + FAS_ASSERT(data != NULL_PTR); + FAS_ASSERT(adiState != NULL_PTR); + + uint8_t PEC_Check[ADI_SIZE_OF_DATA_FOR_PEC_COMPUTATION_WITH_COUNTER] = {0}; + uint16_t PEC_result = 0u; + uint8_t PEC_RX[ADI_PEC_SIZE_IN_BYTES] = {0}; + uint8_t afeCommandCounter = 0u; + uint16_t registerLengthInBytes = registerToRead[ADI_COMMAND_DATA_LENGTH_POSITION]; + uint16_t byte = 0u; /* variable to parse data bytes */ + + /* One frame = data + 2 bytes PEC */ + /* + 2u: the two additional bytes corresponding to the PEC */ + uint16_t spiFrameLength = registerLengthInBytes + ADI_PEC_SIZE_IN_BYTES; + uint16_t dataLength = registerLengthInBytes; + + for (uint16_t i = 0; i < ADI_N_BYTES_FOR_DATA_TRANSMISSION; i++) { + adiState->data.txBuffer[i] = 0x0; + } + + /** + * SM_SPI_PEC: SPI Packet Error Code + * Calculate PEC for command. + */ + /* Compute PEC of the two command bytes */ + PEC_Check[ADI_COMMAND_FIRST_BYTE_POSITION] = (uint8_t)registerToRead[ADI_COMMAND_FIRST_BYTE_POSITION]; + PEC_Check[ADI_COMMAND_SECOND_BYTE_POSITION] = (uint8_t)registerToRead[ADI_COMMAND_SECOND_BYTE_POSITION]; + PEC_result = ADI_Pec15(ADI_COMMAND_SIZE_IN_BYTES, PEC_Check); + + adiState->data.txBuffer[ADI_COMMAND_FIRST_BYTE_POSITION] = registerToRead[ADI_COMMAND_FIRST_BYTE_POSITION]; + adiState->data.txBuffer[ADI_COMMAND_SECOND_BYTE_POSITION] = registerToRead[ADI_COMMAND_SECOND_BYTE_POSITION]; + adiState->data.txBuffer[ADI_COMMAND_PEC_FIRST_BYTE_POSITION] = + (uint8_t)((PEC_result >> ADI_BYTE_SHIFT) & ADI_ONE_BYTE_MASK); + adiState->data.txBuffer[ADI_COMMAND_PEC_SECOND_BYTE_POSITION] = (uint8_t)(PEC_result & ADI_ONE_BYTE_MASK); + + /* 4u: two bytes command + two bytes command PEC */ + /* Register length + 2u: The two additional bytes correspond to the PEC */ + uint16_t frameLength = ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + + ((registerLengthInBytes + ADI_PEC_SIZE_IN_BYTES) * ADI_N_ADI); + ADI_SpiTransmitReceiveData(adiState, adiState->data.txBuffer, adiState->data.rxBuffer, (uint32_t)frameLength); + + for (uint16_t i = 0; i < ADI_N_ADI; i++) { + /* Put received messages in data buffer, used outside function to access data */ + for (byte = 0u; byte < registerLengthInBytes; byte++) { + data[byte + (i * dataLength)] = + (uint8_t)(adiState->data.rxBuffer + [(ADI_FIRST_DATA_BYTE_POSITION_IN_TRANSMISSION_FRAME + byte) + (i * spiFrameLength)]); + } + /* PEC_Check is a local variable holding read data and used to compute the PEC */ + for (byte = 0u; byte < registerLengthInBytes; byte++) { + PEC_Check[byte] = + (uint8_t)(adiState->data.rxBuffer + [(ADI_FIRST_DATA_BYTE_POSITION_IN_TRANSMISSION_FRAME + byte) + (i * spiFrameLength)]); + } + /* Data PEC is also computed on command counter, so one byte with command counter is added */ + PEC_Check[byte] = + (uint8_t)(adiState->data.rxBuffer + [(ADI_FIRST_DATA_BYTE_POSITION_IN_TRANSMISSION_FRAME + byte) + (i * spiFrameLength)]) & + ADI_COMMAND_COUNTER_MASK; + + PEC_result = + ADI_Pec10((uint8_t)(registerToRead[ADI_COMMAND_DATA_LENGTH_POSITION] & ADI_ONE_BYTE_MASK), PEC_Check, true); + PEC_RX[ADI_DATA_PEC_FIRST_BYTE_POSITION] = (uint8_t)((PEC_result >> ADI_BYTE_SHIFT) & ADI_ONE_BYTE_MASK); + PEC_RX[ADI_DATA_PEC_SECOND_BYTE_POSITION] = (uint8_t)(PEC_result & ADI_ONE_BYTE_MASK); + + /* Position of the PEC (two bytes) in the first read frame */ + /* 4u: two bytes command + two bytes command PEC, followed by number of bytes in register */ + uint16_t crcByte0Position = registerLengthInBytes + ADI_COMMAND_AND_PEC_SIZE_IN_BYTES; + uint16_t crcByte1Position = registerLengthInBytes + ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 1u; + + /** + * SM_SPI_PEC: SPI Packet Error Code + * PEC check on read value. + */ + /* if calculated PEC not equal to received PEC */ + if ((PEC_RX[ADI_DATA_PEC_FIRST_BYTE_POSITION] != + (adiState->data.rxBuffer[crcByte0Position + (i * spiFrameLength)] & + ADI_PEC10_MSB_EXCLUDE_COMMAND_COUNTER)) || + (PEC_RX[ADI_DATA_PEC_SECOND_BYTE_POSITION] != + (adiState->data.rxBuffer[crcByte1Position + (i * spiFrameLength)] & ADI_ONE_BYTE_MASK))) { +/* update error table of the corresponding ades183x only if PEC check is activated */ +#if (ADI_DISCARD_PEC == false) + adiState->data.errorTable->crcIsOk[adiState->currentString][i] = false; +#else + adiState->data.errorTable->crcIsOk[adiState->currentString][i] = true; +#endif + } else { + /* update error table of the corresponding ades183x */ + adiState->data.errorTable->crcIsOk[adiState->currentString][i] = true; + } + + /* CRC is placed after the data bytes */ + uint16_t crcFirstBytePosition = ADI_FIRST_DATA_BYTE_POSITION_IN_TRANSMISSION_FRAME + registerLengthInBytes; + /** + * SM_SPI_CNT: SPI Frame Counter + * Compare driver stored value of command counter with values sent by the AFEs. + */ + /* Retrieve command counter value sent by the AFE, included in first CRC byte of answer frame */ + uint16_t commandCounterData = adiState->data.rxBuffer[crcFirstBytePosition + (i * spiFrameLength)] & + ADI_COMMAND_COUNTER_MASK; + afeCommandCounter = (uint8_t)((commandCounterData >> ADI_COMMAND_COUNTER_POSITION) & ADI_ONE_BYTE_MASK); + + if (afeCommandCounter != adiState->data.commandCounter[adiState->currentString][i]) { + /** + * command counter flag stays set as soon as an error was detected + * it can only be reset within the reset function + */ + adiState->data.errorTable->commandCounterIsOk[adiState->currentString][i] = false; + } + } +} + +/* RequirementId: D7.1 V0R4 FUN-0.0.01.04 */ +extern void ADI_SpiTransmitReceiveData( + ADI_STATE_s *adiState, + uint16_t *pTxBuff, + uint16_t *pRxBuff, + uint32_t frameLength) { + /* AXIVION Routine Generic-MissingParameterAssert: frameLength: parameter accepts whole range */ + /* AXIVION Routine Generic-MissingParameterAssert: pRxBuff: parameter accepts whole range */ + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(pTxBuff != NULL_PTR); + + STD_RETURN_TYPE_e retValDummy = STD_OK; + STD_RETURN_TYPE_e retVal = STD_OK; + if (frameLength == 0u) { + /* Length = 0: only transmit dummy byte */ + /* START SPI function to adapt for different environment */ + /* No DMA, blocking */ + retVal = SPI_TransmitDummyByte(&spi_adiInterface[adiState->currentString], 0u); + /* END SPI function to adapt for different environment */ + } else { + if (pRxBuff == NULL_PTR) { + /* Transmit only (receive discarded) */ + /* START SPI function to adapt for different environment */ + /* No DMA, blocking */ + retValDummy = + SPI_TransmitDummyByte(&spi_adiInterface[adiState->currentString], ADI_SPI_WAKEUP_WAIT_TIME_US); + retVal = SPI_TransmitData(&spi_adiInterface[adiState->currentString], pTxBuff, frameLength); + /* END SPI function to adapt for different environment */ + } else { + /* Transmit and receive */ + /* START SPI function to adapt for different environment */ + /* Uses DMA and notifications */ + retValDummy = + SPI_TransmitDummyByte(&spi_adiInterface[adiState->currentString], ADI_SPI_WAKEUP_WAIT_TIME_US); + retVal = + SPI_TransmitReceiveDataDma(&spi_adiInterface[adiState->currentString], pTxBuff, pRxBuff, frameLength); + /* Now wait for notification in DMA Rx finished interrupt */ + uint32_t timeout = ADI_TRANSMISSION_TIMEOUT; + FAS_ASSERT(timeout > 0u); + uint32_t ulNotifiedValue = 0u; + /* Suspend task and wait for notification, clear notification value on entry and exit */ + (void)OS_WaitForNotification(&ulNotifiedValue, timeout); + if (ulNotifiedValue != ADI_DMA_SPI_FINISHED_NOTIFICATION_VALUE) { + /* if ulNotifiedValue not written by xTaskNotify() in DMA interrupt: transmission timeout */ + retVal = STD_NOT_OK; + } + /* END SPI function to adapt for different environment */ + } + } + + if ((retVal == STD_NOT_OK) || (retValDummy == STD_NOT_OK)) { + adiState->data.errorTable->spiIsOk[adiState->currentString] = false; + } else if ((retVal == STD_OK) && (retValDummy == STD_OK)) { + adiState->data.errorTable->spiIsOk[adiState->currentString] = true; + } else { + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + } +} + +extern void ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_e registerSet, + uint8_t registerOffset, + uint8_t data, + uint8_t position, + uint8_t mask, + ADI_STATE_s *adiState) { + /* AXIVION Routine Generic-MissingParameterAssert: data: parameter accepts whole range */ + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(registerSet <= ADI_CFG_REGISTER_SET_B); + /* Only 8 bit in a register part */ + FAS_ASSERT(position <= ADI_MAX_BIT_POSITION_IN_BYTE); + /* All 0s mask would mean do nothing */ + FAS_ASSERT(mask > 0u); + FAS_ASSERT(registerOffset <= ADI_REGISTER_OFFSET5); + + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + ADI_StoredConfigurationFillRegisterData(m, registerSet, registerOffset, data, position, mask, adiState); + } +} + +/* RequirementId: D7.1 V0R4 FUN-0.0.01.03 */ +/* RequirementId: D7.1 V0R4 SIF-4.10.01.01 */ +/* RequirementId: D7.1 V0R4 SIF-4.10.11.01 */ +extern void ADI_TransmitCommand(uint16_t *command, ADI_STATE_s *adiState) { + FAS_ASSERT(command != NULL_PTR); + FAS_ASSERT(adiState != NULL_PTR); + + uint8_t PEC_Check[ADI_MAX_REGISTER_SIZE_IN_BYTES] = {0}; + uint16_t PEC_result = 0u; + + /** + * SM_SPI_PEC: SPI Packet Error Code + * Calculate PEC for command. + */ + PEC_Check[ADI_COMMAND_FIRST_BYTE_POSITION] = (uint8_t)command[ADI_COMMAND_BYTE0_POSITION]; + PEC_Check[ADI_COMMAND_SECOND_BYTE_POSITION] = (uint8_t)command[ADI_COMMAND_BYTE1_POSITION]; + PEC_result = ADI_Pec15(ADI_COMMAND_SIZE_IN_BYTES, PEC_Check); + + adiState->data.txBuffer[ADI_COMMAND_FIRST_BYTE_POSITION] = command[ADI_COMMAND_BYTE0_POSITION]; + adiState->data.txBuffer[ADI_COMMAND_SECOND_BYTE_POSITION] = command[ADI_COMMAND_BYTE1_POSITION]; + adiState->data.txBuffer[ADI_COMMAND_PEC_FIRST_BYTE_POSITION] = + (uint8_t)((PEC_result >> ADI_BYTE_SHIFT) & ADI_ONE_BYTE_MASK); + adiState->data.txBuffer[ADI_COMMAND_PEC_SECOND_BYTE_POSITION] = (uint8_t)(PEC_result & ADI_ONE_BYTE_MASK); + + ADI_SpiTransmitReceiveData(adiState, adiState->data.txBuffer, NULL_PTR, ADI_COMMAND_AND_PEC_SIZE_IN_BYTES); + + /** + * SM_SPI_CNT: SPI Frame Counter + * Increment driver stored value of command counter if command causes increase. + */ + /** If command increments AFE command counter, increment driver command counter */ + if (command[ADI_COMMAND_INC_POSITION] == 1u) { + ADI_IncrementCommandCounter(adiState); + } +} + +extern void ADI_WriteRegisterGlobal( + const uint16_t *registerToWrite, + uint8_t *data, + ADI_PEC_FAULT_INJECTION_e pecFaultInjection, + ADI_STATE_s *adiState) { + FAS_ASSERT(registerToWrite != NULL_PTR); + FAS_ASSERT(data != NULL_PTR); + FAS_ASSERT(adiState != NULL_PTR); + + for (uint16_t i = 0u; i < ADI_N_ADI; i++) { + for (uint8_t byte = 0; byte < registerToWrite[ADI_COMMAND_DATA_LENGTH_POSITION]; byte++) { + adi_dataTransmit[byte + (i * registerToWrite[ADI_COMMAND_DATA_LENGTH_POSITION])] = data[byte]; + } + } + ADI_WriteRegister(registerToWrite, adi_dataTransmit, pecFaultInjection, adiState); +} + +/* RequirementId: D7.1 V0R4 SIF-4.20.01.03 */ +extern void ADI_StoredConfigurationWriteToAfeGlobal(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + STD_RETURN_TYPE_e returnValue = STD_OK; + + returnValue = ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_A, adiState); + if (returnValue == STD_NOT_OK) { + /* If problem when writing configuration, retry once */ + (void)ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_A, adiState); + } + returnValue = ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_B, adiState); + if (returnValue == STD_NOT_OK) { + /* If problem when writing configuration, retry once */ + (void)ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_B, adiState); + } +} + +extern void ADI_ClearCommandCounter(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /** + * SM_SPI_CNT: SPI Frame Counter + * Reset driver stored value of command counter by sending RSTCC command. + */ + /* Clear command counter */ + ADI_CopyCommandBits(adi_cmdRstcc, adi_command); + ADI_TransmitCommand(adi_command, adiState); + for (uint16_t i = 0u; i < ADI_N_ADI; i++) { + adiState->data.errorTable->commandCounterIsOk[adiState->currentString][i] = true; + adiState->data.commandCounter[adiState->currentString][i] = ADI_COMMAND_COUNTER_RESET_VALUE; + } +} + +extern void ADI_Wait(uint32_t waitTime) { + FAS_ASSERT(waitTime > 0u); + + uint32_t currentTime = OS_GetTickCount(); + /* Block task without possibility to wake up */ + /* +1: to wait at least waitTime*/ + OS_DelayTaskUntil(¤tTime, waitTime + 1u); +} + +extern void ADI_WriteDataBits(uint8_t *pSentData, uint8_t dataToWrite, uint8_t position, uint8_t mask) { + FAS_ASSERT(pSentData != NULL_PTR); + /* AXIVION Routine Generic-MissingParameterAssert: dataToWrite: parameter accepts whole range */ + /* Only 8 bit in a register part */ + FAS_ASSERT(position <= ADI_MAX_BIT_POSITION_IN_BYTE); + /* All 0s mask would mean do nothing */ + FAS_ASSERT(mask > 0u); + + uint8_t tempData = (uint8_t)((((uint16_t)dataToWrite) << position) & ADI_DATA_MASK_SEED); + *pSentData &= ~mask; + *pSentData |= tempData & mask; +} + +/* RequirementId: D7.1 V0R4 FUN-0.0.01.02 */ +/* RequirementId: D7.1 V0R4 SIF-4.10.01.01 */ +/* RequirementId: D7.1 V0R4 SIF-4.10.11.01 */ +extern void ADI_WriteRegister( + const uint16_t *registerToWrite, + uint8_t *data, + ADI_PEC_FAULT_INJECTION_e pecFaultInjection, + ADI_STATE_s *adiState) { + FAS_ASSERT(registerToWrite != NULL_PTR); + FAS_ASSERT(data != NULL_PTR); + FAS_ASSERT(adiState != NULL_PTR); + + uint16_t PEC_result = 0; + uint8_t PEC_Check[ADI_SIZE_OF_DATA_FOR_PEC_COMPUTATION] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint16_t registerLengthInBytes = registerToWrite[ADI_COMMAND_DATA_LENGTH_POSITION]; + uint16_t spiFrameLength = registerLengthInBytes + 2u; + uint16_t dataLength = registerLengthInBytes; + + /** + * SM_SPI_PEC: SPI Packet Error Code + * Calculate PEC for command. + */ + /* Compute PEC of the two command bytes */ + PEC_Check[ADI_COMMAND_FIRST_BYTE_POSITION] = (uint8_t)registerToWrite[ADI_COMMAND_FIRST_BYTE_POSITION]; + PEC_Check[ADI_COMMAND_SECOND_BYTE_POSITION] = (uint8_t)registerToWrite[ADI_COMMAND_SECOND_BYTE_POSITION]; + PEC_result = ADI_Pec15(ADI_COMMAND_SIZE_IN_BYTES, PEC_Check); + + adiState->data.txBuffer[ADI_COMMAND_FIRST_BYTE_POSITION] = registerToWrite[ADI_COMMAND_FIRST_BYTE_POSITION]; + adiState->data.txBuffer[ADI_COMMAND_SECOND_BYTE_POSITION] = registerToWrite[ADI_COMMAND_SECOND_BYTE_POSITION]; + if (pecFaultInjection == ADI_COMMAND_PEC_FAULT_INJECTION) { + adiState->data.txBuffer[ADI_COMMAND_PEC_FIRST_BYTE_POSITION] = (PEC_result >> ADI_BYTE_SHIFT) & + ADI_ONE_BYTE_MASK; + adiState->data.txBuffer[ADI_COMMAND_PEC_SECOND_BYTE_POSITION] = (PEC_result & ADI_ONE_BYTE_MASK) + 1u; + } else { + adiState->data.txBuffer[ADI_COMMAND_PEC_FIRST_BYTE_POSITION] = (PEC_result >> ADI_BYTE_SHIFT) & + ADI_ONE_BYTE_MASK; + adiState->data.txBuffer[ADI_COMMAND_PEC_SECOND_BYTE_POSITION] = PEC_result & ADI_ONE_BYTE_MASK; + } + + for (uint16_t i = 0u; i < ADI_N_ADI; i++) { + /* data[] contains the data to write to the daisy-chain, it is used outside of the function */ + for (uint16_t byte = 0; byte < registerLengthInBytes; byte++) { + adiState->data + .txBuffer[(ADI_FIRST_DATA_BYTE_POSITION_IN_TRANSMISSION_FRAME + byte) + (i * spiFrameLength)] = + data[byte + (i * dataLength)]; + } + /** + * SM_SPI_PEC: SPI Packet Error Code + * Calculate PEC for values to be sent to the daisy-chain. + */ + /* Calculate PEC of all data (1 PEC value for 6 bytes) */ + /* PEC_Check is a local variable holding data to write and used to compute the PEC */ + for (uint16_t byte = 0; byte < registerLengthInBytes; byte++) { + uint16_t bufferData = + adiState->data + .txBuffer[(ADI_FIRST_DATA_BYTE_POSITION_IN_TRANSMISSION_FRAME + byte) + (i * spiFrameLength)]; + PEC_Check[byte] = (uint8_t)((bufferData)&ADI_ONE_BYTE_MASK); + } + + PEC_result = ADI_Pec10((uint8_t)(registerLengthInBytes & ADI_ONE_BYTE_MASK), PEC_Check, false); + + /* CRC is placed after the data bytes */ + uint16_t crcFirstBytePosition = ADI_FIRST_DATA_BYTE_POSITION_IN_TRANSMISSION_FRAME + registerLengthInBytes; + if (pecFaultInjection == ADI_DATA_PEC_FAULT_INJECTION) { + adiState->data.txBuffer[crcFirstBytePosition + (i * spiFrameLength)] = + (PEC_result >> ADI_BYTE_SHIFT) & ADI_PEC10_FULL_EXCLUDE_COMMAND_COUNTER; + adiState->data.txBuffer[crcFirstBytePosition + 1u + (i * spiFrameLength)] = + (PEC_result & ADI_ONE_BYTE_MASK) + 1u; + } else { + adiState->data.txBuffer[crcFirstBytePosition + (i * spiFrameLength)] = + (PEC_result >> ADI_BYTE_SHIFT) & ADI_PEC10_FULL_EXCLUDE_COMMAND_COUNTER; + adiState->data.txBuffer[crcFirstBytePosition + 1u + (i * spiFrameLength)] = PEC_result & ADI_ONE_BYTE_MASK; + } + } + + uint16_t frameLength = ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + + ((registerLengthInBytes + ADI_PEC_SIZE_IN_BYTES) * ADI_N_ADI); + ADI_SpiTransmitReceiveData(adiState, adiState->data.txBuffer, adiState->data.rxBuffer, (uint32_t)frameLength); + + /** + * SM_SPI_CNT: SPI Frame Counter + * Increment driver stored value of command counter if command causes increase. + */ + /* If command increments AFE command counter, increment driver command counter */ + /* Do not increment if a PEC error was injected */ + if ((registerToWrite[ADI_COMMAND_INC_POSITION] == 1u) && (pecFaultInjection == ADI_PEC_NO_FAULT_INJECTION)) { + ADI_IncrementCommandCounter(adiState); + } +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_ADI_StoredConfigurationFillRegisterData( + uint8_t module, + ADI_CFG_REGISTER_SET_e registerSet, + uint8_t registerOffset, + uint8_t data, + uint8_t position, + uint8_t mask, + ADI_STATE_s *adiState) { + ADI_StoredConfigurationFillRegisterData(module, registerSet, registerOffset, data, position, mask, adiState); +} +extern void TEST_ADI_IncrementCommandCounter(ADI_STATE_s *adiState) { + ADI_IncrementCommandCounter(adiState); +} + +#endif diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_helpers.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_helpers.h new file mode 100644 index 00000000..289ccaf7 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_helpers.h @@ -0,0 +1,279 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_helpers.h + * @author foxBMS Team + * @date 2022-12-06 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Headers for the diagnostic driver for the ADI analog front-end. + * + */ + +#ifndef FOXBMS__ADI_ADES183X_HELPERS_H_ +#define FOXBMS__ADI_ADES183X_HELPERS_H_ + +/*========== Includes =======================================================*/ +/* clang-format off */ +#include "adi_ades183x_cfg.h" +/* clang-format on */ + +#include "adi_ades183x_defs.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Extern Constant and Variable Declarations ======================*/ + +/*========== Extern Function Prototypes =====================================*/ +/** + * @brief send command to the ades183x daisy-chain (e.g., start voltage + * measurement). + * @param command command to be sent + * @param adiState state of the driver + */ +extern void ADI_TransmitCommand(uint16_t *command, ADI_STATE_s *adiState); + +/** + * @brief copy command bits in variables. + * @details The commands are defined as const. As some of them have + * configuration bits, they are first copied in a non-const variable. + * They can then be configured with + * ADI_WriteCommandConfigurationBits(). + * @param sourceCommand command definition from command list + * @param destinationCommand copied command bits from command definition + */ +extern void ADI_CopyCommandBits(const uint16_t *sourceCommand, uint16_t *destinationCommand); + +/** + * @brief write configuration bits in commands (e.g., channel in ADAX command). + * @param configuredCommand command in which bits are configured + * @param position start bit of configuration field to write + * @param length length of configuration field to write + * @param configuration configuration to write to the configuration field + */ +extern void ADI_WriteCommandConfigurationBits( + uint16_t *configuredCommand, + uint8_t position, + uint8_t length, + uint16_t configuration); + +/** + * @brief Helper function to read specific bits from received data. + * @param receivedData data received from the AFEs + * @param pDataToRead specific bits read from received data + * @param position position where to read the bits in received data + * @param mask mask corresponding to bits to read + */ +extern void ADI_ReadDataBits(uint8_t receivedData, uint8_t *pDataToRead, uint8_t position, uint8_t mask); + +/** + * @brief send command to the ades183x daisy-chain to read a register. + * @details This is the core function to receive data from the ades183x + * daisy-chain. + * A 2 byte command is sent with the corresponding PEC. + * Example: Read configuration register (RDCFG). + * The data send is: + * 2 bytes (COMMAND) 2 bytes (PEC) + * The data received is: + * 6 bytes (IC1) 2 bytes (PEC) + 6 bytes (IC2) 2 bytes (PEC) + * + 6 bytes (IC3) 2 bytes (PEC) + * + ... + * + 6 bytes (IC{ADI_N_ADI}) 2 bytes (PEC) + * The function does not check the PECs. This has to be done + * elsewhere. + * @param registerToRead register to be read + * @param data read data + * @param adiState state of the driver + */ +extern void ADI_ReadRegister(uint16_t *registerToRead, uint8_t *data, ADI_STATE_s *adiState); + +/** + * @brief Sends data in the configuration stored in driver to all AFEs in the + * daisy chain, for all configuration registers. + * @param adiState state of the driver + */ +extern void ADI_StoredConfigurationWriteToAfeGlobal(ADI_STATE_s *adiState); + +/** + * @brief Compares the configuration stored in the AFE driver with + * the configuration read from the AFEs. + * @details If the stored and read configuration match, the corresponding flag + * is set to true in the error table, otherwise it is set to false. + * @param registerSet configuration register to check + * @param adiState state of the driver + * @return STD_OK if check was OK, STD_NOT_OK otherwise + */ +extern STD_RETURN_TYPE_e ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_e registerSet, ADI_STATE_s *adiState); + +/** + * @brief Sends data in the configuration stored in driver to all AFEs in the + * daisy chain, for a specific configuration register. + * @param registerSet configuration register to write + * @param adiState state of the driver + * @return STD_OK if check made after writing was OK, STD_NOT_OK otherwise + */ +extern STD_RETURN_TYPE_e ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_e registerSet, ADI_STATE_s *adiState); + +/** + * @brief Write the same 6 bytes to all devices in the daisy-chain. + * @param registerToWrite register to write + * @param data data to write in register + * @param pecFaultInjection used for diagnostics to inject faults in PEC + * @param adiState state of the driver + */ +extern void ADI_WriteRegisterGlobal( + const uint16_t *registerToWrite, + uint8_t *data, + ADI_PEC_FAULT_INJECTION_e pecFaultInjection, + ADI_STATE_s *adiState); + +/** + * @brief Send RSTCC to AFEs in daisy-chain and clear command counter of AFE driver. + * @param adiState state of the driver + */ +extern void ADI_ClearCommandCounter(ADI_STATE_s *adiState); + +/** + * @brief Transmits and receives data on SPI. + * @param adiState state of the ADI driver + * @param pTxBuff pointer to data that is transmitted by the SPI interface + * @param pRxBuff pointer to data that is received by the SPI interface + * @param frameLength number of bytes to be transmitted by the SPI interface + */ +extern void ADI_SpiTransmitReceiveData( + ADI_STATE_s *adiState, + uint16_t *pTxBuff, + uint16_t *pRxBuff, + uint32_t frameLength); + +/** + * @brief Writes data in the configuration stored in AFE driver, + * for all AFEs in the daisy-chain. + * @details Does the same as ADI_StoredConfigurationFillRegisterData(), but + * for all AFEs in the daisy chain. + * @param registerSet configuration register to address + * @param registerOffset position of byte to address in configuration register + * @param data data to write to byte in register + * @param position position where to store the data in byte + * @param mask mask corresponding to data to store + * @param adiState state of the driver + */ +extern void ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_e registerSet, + uint8_t registerOffset, + uint8_t data, + uint8_t position, + uint8_t mask, + ADI_STATE_s *adiState); + +/** + * @brief wait for a certain number of milliseconds + * @details This function is used to wait for a definite amount of time. + * In foxBMS, block task running ades183x. + * The task cannot be woken up before the time has elapsed. + * @param waitTime time in ms during which task will be blocked + */ +extern void ADI_Wait(uint32_t waitTime); + +/** + * @brief Helper function to write specific bits in data to be sent. + * @param pSentData data to send to the AFEs + * @param dataToWrite specific bits to write in data to be sent + * @param position position where to write the bits in data to send + * @param mask mask corresponding to bits to write + */ +extern void ADI_WriteDataBits(uint8_t *pSentData, uint8_t dataToWrite, uint8_t position, uint8_t mask); + +/** + * @brief sends command to the ades183x daisy-chain to write data. + * @details This is the core function to transmit data to the ades183x + * daisy-chain. + * The data sent is: + * COMMAND + 6 bytes (IC1) + 6 bytes (IC2) + * + 6 bytes (IC3) + * + ... + * + 6 bytes (IC{ADI_N_ADI}) + * A 2 byte command is sent with the corresponding PEC. + * Example: write configuration register (WRCFG). + * The command has to be set and then the function calculates the PEC + * automatically. + * The function calculates the needed PEC to send the data to the + * daisy-chain. The sent data has the format: + * 2 byte-COMMAND (2 bytes PEC) + 6 bytes (IC1) (2 bytes PEC) + * + 6 bytes (IC2) (2 bytes PEC) + * + 6 bytes (IC3) (2 bytes PEC) + * + ... + * + 6 bytes (IC{ADI_N_ADI}) (2 bytes PEC) + * The pecFaultInjection parameters is used to inject faults in the + * command PEC or in the data PEC. It is used for diagnostics. + * The default value is ADI_PEC_NO_FAULT_INJECTION, in this case the + * correct PECs are transmitted. + * @param registerToWrite register to write + * @param data data to write in register + * @param adiState state of the driver + * @param pecFaultInjection used for diagnostics to inject faults in PEC + */ +extern void ADI_WriteRegister( + const uint16_t *registerToWrite, + uint8_t *data, + ADI_PEC_FAULT_INJECTION_e pecFaultInjection, + ADI_STATE_s *adiState); + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_ADI_StoredConfigurationFillRegisterData( + uint8_t module, + ADI_CFG_REGISTER_SET_e registerSet, + uint8_t registerOffset, + uint8_t data, + uint8_t position, + uint8_t mask, + ADI_STATE_s *adiState); +extern void TEST_ADI_IncrementCommandCounter(ADI_STATE_s *adiState); +#endif + +#endif /* FOXBMS__ADI_ADES183X_HELPERS_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_initialization.c b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_initialization.c new file mode 100644 index 00000000..b0250143 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_initialization.c @@ -0,0 +1,604 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_initialization.c + * @author foxBMS Team + * @date 2019-08-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix ADI + * + * @brief Implementation of some software + * + */ + +/*========== Includes =======================================================*/ + +#include "adi_ades183x_initialization.h" + +#include "adi_ades183x_buffers.h" +#include "adi_ades183x_commands.h" +#include "adi_ades183x_defs.h" +#include "adi_ades183x_helpers.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ +/* Wait at least one micro second for the AFE to wakeup */ +#define ADI_AFE_WAKEUP_TIME ((ADI_DAISY_CHAIN_WAKE_UP_TIME_us / ADI_COEFFICIENT_US_TO_MS) + 1u) +#define ADI_ISO_SPI_WAKEUP_TIME ((ADI_DAISY_CHAIN_READY_TIME_us / ADI_COEFFICIENT_US_TO_MS) + 1u) + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/** + * @brief TODO. + * @details TODO + * @param adiState state of the driver + */ +static void ADI_ClearAllFlagsInStatusRegisterGroupC(ADI_STATE_s *adiState); + +/** + * @brief Disable balancing. + * @details TODO + * @param adiState state of the driver + */ +static void ADI_DisableBalancingOnStartup(ADI_STATE_s *adiState); + +/** + * @brief TODO. + * @details TODO + * @param adiState state of the driver + */ +static void ADI_GetSerialIdsOfAllIcsInString(ADI_STATE_s *adiState); + +/** + * @brief TODO. + * @details TODO + * @param adiState state of the driver + */ +static void ADI_GetRevisionOfAllIcsInString(ADI_STATE_s *adiState); + +/** + * @brief Initialize the driver configuration. + * @details TODO + * @param adiState state of the driver + */ +static void ADI_InitializeConfiguration(ADI_STATE_s *adiState); + +/** + * @brief Resets the error table. + * @details This function should be called during initialization or before + * starting a new measurement cycle + * @param adiState state of the driver + */ +static void ADI_ResetErrorTable(ADI_STATE_s *adiState); + +/** + * @brief Reset TODO. + * @details TODO + * @param adiState state of the driver + */ +static void ADI_ResetIirFilterOnStartup(ADI_STATE_s *adiState); + +/** + * @brief Start cell voltage measurement. + * @details This function should be called during initialization or before + * starting a new measurement cycle + * @param adiState state of the driver + */ +static void ADI_StartContinuousCellVoltageMeasurements(ADI_STATE_s *adiState); + +/** + * @brief Wake up the AFE. + * @details TODO + * @param adiState state of the driver + */ +static void ADI_WakeUpDaisyChain(ADI_STATE_s *adiState); + +/*========== Static Function Implementations ================================*/ + +static void ADI_ClearAllFlagsInStatusRegisterGroupC(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + adi_clearFlagData[ADI_REGISTER_OFFSET0] = 0u; + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS1FLT_POS, ADI_STCR0_CS1FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS2FLT_POS, ADI_STCR0_CS2FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS3FLT_POS, ADI_STCR0_CS3FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS4FLT_POS, ADI_STCR0_CS4FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS5FLT_POS, ADI_STCR0_CS5FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS6FLT_POS, ADI_STCR0_CS6FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS7FLT_POS, ADI_STCR0_CS7FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET0], 1u, ADI_STCR0_CS8FLT_POS, ADI_STCR0_CS8FLT_MASK); + adi_clearFlagData[ADI_REGISTER_OFFSET1] = 0u; + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS9FLT_POS, ADI_STCR1_CS9FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS10FLT_POS, ADI_STCR1_CS10FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS11FLT_POS, ADI_STCR1_CS11FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS12FLT_POS, ADI_STCR1_CS12FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS13FLT_POS, ADI_STCR1_CS13FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS14FLT_POS, ADI_STCR1_CS14FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS15FLT_POS, ADI_STCR1_CS15FLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET1], 1u, ADI_STCR1_CS16FLT_POS, ADI_STCR1_CS16FLT_MASK); + adi_clearFlagData[ADI_REGISTER_OFFSET4] = 0u; + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET4], 1u, ADI_STCR4_SMED_POS, ADI_STCR4_SMED_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET4], 1u, ADI_STCR4_SED_POS, ADI_STCR4_SED_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET4], 1u, ADI_STCR4_CMED_POS, ADI_STCR4_CMED_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET4], 1u, ADI_STCR4_CED_POS, ADI_STCR4_CED_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET4], 1u, ADI_STCR4_VD_UV_POS, ADI_STCR4_VD_UV_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET4], 1u, ADI_STCR4_VD_OV_POS, ADI_STCR4_VD_OV_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET4], 1u, ADI_STCR4_VA_UV_POS, ADI_STCR4_VA_UV_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET4], 1u, ADI_STCR4_VA_OV_POS, ADI_STCR4_VA_OV_MASK); + adi_clearFlagData[ADI_REGISTER_OFFSET5] = 0u; + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET5], 1u, ADI_STCR5_OSCCHK_POS, ADI_STCR5_OSCCHK_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET5], 1u, ADI_STCR5_TMODCHK_POS, ADI_STCR5_TMODCHK_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET5], 1u, ADI_STCR5_THSD_POS, ADI_STCR5_THSD_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET5], 1u, ADI_STCR5_SLEEP_POS, ADI_STCR5_SLEEP_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET5], 1u, ADI_STCR5_SPIFLT_POS, ADI_STCR5_SPIFLT_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET5], 1u, ADI_STCR5_COMP_POS, ADI_STCR5_COMP_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET5], 1u, ADI_STCR5_VDE_POS, ADI_STCR5_VDE_MASK); + ADI_WriteDataBits(&adi_clearFlagData[ADI_REGISTER_OFFSET5], 1u, ADI_STCR5_VDEL_POS, ADI_STCR5_VDEL_MASK); + ADI_WriteRegisterGlobal(adi_cmdClrflag, adi_clearFlagData, ADI_PEC_NO_FAULT_INJECTION, adiState); +} + +static void ADI_DisableBalancingOnStartup(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /* balancing: Set all PWM values to 0 for all AFEs in the daisy-chain */ + adi_writeGlobal[ADI_REGISTER_OFFSET0] = 0u; + adi_writeGlobal[ADI_REGISTER_OFFSET1] = 0u; + adi_writeGlobal[ADI_REGISTER_OFFSET2] = 0u; + adi_writeGlobal[ADI_REGISTER_OFFSET3] = 0u; + adi_writeGlobal[ADI_REGISTER_OFFSET4] = 0u; + adi_writeGlobal[ADI_REGISTER_OFFSET5] = 0u; + ADI_WriteRegisterGlobal(adi_cmdWrpwma, adi_writeGlobal, ADI_PEC_NO_FAULT_INJECTION, adiState); + ADI_WriteRegisterGlobal(adi_cmdWrpwmb, adi_writeGlobal, ADI_PEC_NO_FAULT_INJECTION, adiState); +} + +static void ADI_GetSerialIdsOfAllIcsInString(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + ADI_CopyCommandBits(adi_cmdRdsid, adi_command); + ADI_ReadRegister(adi_command, adi_dataReceive, adiState); + for (uint16_t m = 0; m < ADI_N_ADI; m++) { + adiState->serialId[adiState->currentString][m] = 0u; + for (uint8_t byte = 0u; byte < ADI_RDSID_LEN; byte++) { + adiState->serialId[adiState->currentString][m] |= ((uint64_t)adi_dataReceive[(m * ADI_RDSID_LEN) + byte]) + << (ADI_BYTE_SHIFT * byte); + } + } +} + +static void ADI_GetRevisionOfAllIcsInString(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + ADI_CopyCommandBits(adi_cmdRdstate, adi_command); + ADI_ReadRegister(adi_command, adi_dataReceive, adiState); + for (uint16_t m = 0; m < ADI_N_ADI; m++) { + ADI_ReadDataBits( + adi_dataReceive[(m * ADI_RDSTATE_LEN) + ADI_REGISTER_OFFSET5], + &(adiState->revision[adiState->currentString][m]), + ADI_STER5_REV_0_3_POS, + ADI_STER5_REV_0_3_MASK); + } +} + +static void ADI_InitializeConfiguration(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /* Configuration register A */ + /* CFGRA0 */ + /** + * SM_VCELL_RED: Cell Voltage Measurement Redundancy + * CTH[2:0]=0b010 -> S-ADC comparison threshold set to 9 mV + */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET0, + ADI_DEFAULT_CTH_COMPARISON_THRESHOLD, + ADI_CFGRA0_CTH_0_2_POS, + ADI_CFGRA0_CTH_0_2_MASK, + adiState); + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET0, + ADI_DEFAULT_REFON_SETUP, + ADI_CFGRA0_REFON_POS, + ADI_CFGRA0_REFON_MASK, + adiState); + /* CFGRA1 */ + /* Do not assert any fault flags. Field will be used in diagnostic functions */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET1, + ADI_DEFAULT_FLAG_D_SETUP, + ADI_CFGRA1_FLAG_D_0_7_POS, + ADI_CFGRA1_FLAG_D_0_7_MASK, + adiState); + /* CFGRA2 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET2, + ADI_DEFAULT_OWA_SETUP, + ADI_CFGRA2_OWA_0_2_POS, + ADI_CFGRA2_OWA_0_2_MASK, + adiState); + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET2, + ADI_DEFAULT_OWRNG_SETUP, + ADI_CFGRA2_OWRNG_POS, + ADI_CFGRA2_OWRNG_MASK, + adiState); + /* Disable soak time on AUX ADCs */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET2, + ADI_DEFAULT_SOAKON_SETUP, + ADI_CFGRA2_SOAKON_POS, + ADI_CFGRA2_SOAKON_MASK, + adiState); + /* CFGRA3 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET3, + ADI_DEFAULT_GPO_1_8_SETUP, + ADI_CFGRA3_GPO_1_8_POS, + ADI_CFGRA3_GPO_1_8_MASK, + adiState); + /* CFGRA4 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET4, + ADI_DEFAULT_GPO_9_10_SETUP, + ADI_CFGRA4_GPO_9_10_POS, + ADI_CFGRA4_GPO_9_10_MASK, + adiState); + /* CFGRA5 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET5, + ADI_DEFAULT_IIR_SETUP, + ADI_CFGRA5_FC_0_2_POS, + ADI_CFGRA5_FC_0_2_MASK, + adiState); + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET5, + ADI_DEFAULT_COMM_BK_SETUP, + ADI_CFGRA5_COMM_BK_POS, + ADI_CFGRA5_COMM_BK_MASK, + adiState); + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET5, + ADI_DEFAULT_MUTE_ST_SETUP, + ADI_CFGRA5_MUTE_ST_POS, + ADI_CFGRA5_MUTE_ST_MASK, + adiState); + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET5, + ADI_DEFAULT_SNAP_ST_SETUP, + ADI_CFGRA5_SNAP_ST_POS, + ADI_CFGRA5_SNAP_ST_MASK, + adiState); + + /* Configuration register B */ + /* CFGRB0 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, + ADI_REGISTER_OFFSET0, + ADI_DEFAULT_VUV_0_7_SETUP, + ADI_CFGRB0_VUV_0_7_POS, + ADI_CFGRB0_VUV_0_7_MASK, + adiState); + /* CFGRB1 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, + ADI_REGISTER_OFFSET1, + ADI_DEFAULT_VUV_8_11_SETUP, + ADI_CFGRB1_VUV_8_11_POS, + ADI_CFGRB1_VUV_8_11_MASK, + adiState); + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, + ADI_REGISTER_OFFSET1, + ADI_DEFAULT_VOV_0_3_SETUP, + ADI_CFGRB1_VOV_0_3_POS, + ADI_CFGRB1_VOV_0_3_MASK, + adiState); + /* CFGRB2 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, + ADI_REGISTER_OFFSET2, + ADI_DEFAULT_VOV_4_11_SETUP, + ADI_CFGRB2_VOV_4_11_POS, + ADI_CFGRB2_VOV_4_11_MASK, + adiState); + /* CFGRB3 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, + ADI_REGISTER_OFFSET3, + ADI_DEFAULT_DCT0_0_5_SETUP, + ADI_CFGRB3_DCT0_0_5_POS, + ADI_CFGRB3_DCT0_0_5_MASK, + adiState); + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, + ADI_REGISTER_OFFSET3, + ADI_DEFAULT_DTRNG_SETUP, + ADI_CFGRB3_DTRNG_POS, + ADI_CFGRB3_DTRNG_MASK, + adiState); + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, + ADI_REGISTER_OFFSET3, + ADI_DEFAULT_DTMEN_SETUP, + ADI_CFGRB3_DTMEN_POS, + ADI_CFGRB3_DTMEN_MASK, + adiState); + /* CFGRB4 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, + ADI_REGISTER_OFFSET4, + ADI_DEFAULT_DCC_1_8_SETUP, + ADI_CFGRB4_DCC_1_8_POS, + ADI_CFGRB4_DCC_1_8_MASK, + adiState); + /* CFGRB5 */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, + ADI_REGISTER_OFFSET5, + ADI_DEFAULT_DCC_9_16_SETUP, + ADI_CFGRB5_DCC_9_16_POS, + ADI_CFGRB5_DCC_9_16_MASK, + adiState); +} + +static void ADI_ResetErrorTable(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) { + adiState->data.errorTable->spiIsOk[stringNumber] = true; + for (uint16_t m = 0; m < ADI_N_ADI; m++) { + adiState->data.errorTable->crcIsOk[stringNumber][m] = true; + adiState->data.errorTable->commandCounterIsOk[stringNumber][m] = true; + adiState->data.errorTable->configurationAIsOk[stringNumber][m] = true; + adiState->data.errorTable->configurationBIsOk[stringNumber][m] = true; + adiState->data.errorTable->voltageRegisterContentIsNotStuck[stringNumber][m] = true; + adiState->data.errorTable->auxiliaryRegisterContentIsNotStuck[stringNumber][m] = true; + adiState->data.errorTable->adcComparisonIsOk[stringNumber][m] = true; + adiState->data.errorTable->compFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->spiFltFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->filteredVoltageRangeIsOk[stringNumber][m] = true; + adiState->data.errorTable->evenWireIsOk[stringNumber][m] = true; + adiState->data.errorTable->oddWireIsOk[stringNumber][m] = true; + adiState->data.errorTable->evenWireHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->oddWireHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->adcCompFlagsHaveNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->auxComparisonIsOk[stringNumber][m] = true; + adiState->data.errorTable->auxVoltageRangeIsOk[stringNumber][m] = true; + adiState->data.errorTable->analogSupplyOvervoltageFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->analogSupplyUndervoltageFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->digitalSupplyOvervoltageFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->digitalSupplyUndervoltageFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->vdeFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->oscchkFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->analogSupplyOvervoltageFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->analogSupplyUndervoltageFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->digitalSupplyOvervoltageFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->digitalSupplyUndervoltageFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->vdeFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->vdelFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->analogSupplyRangeIsOk[stringNumber][m] = true; + adiState->data.errorTable->digitalSupplyRangeIsOk[stringNumber][m] = true; + adiState->data.errorTable->vresRangeIsOk[stringNumber][m] = true; + adiState->data.errorTable->dieTemperatureIsOk[stringNumber][m] = true; + adiState->data.errorTable->oscchkFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->ocCounterFasterFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->ocCounterSlowerFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->thsdFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->tmodchkFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->tmodchkFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->cmedFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->smedFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->sleepFlagIsCleared[stringNumber][m] = true; + adiState->data.errorTable->cmedFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->smedFlagHasNoLatentFault[stringNumber][m] = true; + adiState->data.errorTable->initResetAuxValuesAreOk[stringNumber][m] = true; + adiState->data.errorTable->initClearedAuxValuesAreOk[stringNumber][m] = true; + } + } +} + +static void ADI_ResetIirFilterOnStartup(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /* IIR filter: Change FILT configuration for all AFEs */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, + ADI_REGISTER_OFFSET5, + ADI_IIR_FILTER_PARAMETER_2, + ADI_CFGRA5_FC_0_2_POS, + ADI_CFGRA5_FC_0_2_MASK, + adiState); + ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_A, adiState); +} + +static void ADI_StartContinuousCellVoltageMeasurements(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /* Mute balancing before starting cell voltage measurements */ + ADI_CopyCommandBits(adi_cmdMute, adi_command); + ADI_TransmitCommand(adi_command, adiState); + + /** + * SM_VCELL_RED: Cell Voltage Measurement Redundancy + * Set RD bit to enable redundant cell voltage measurements + */ + ADI_CopyCommandBits(adi_cmdAdcv, adi_command); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RD_POS, ADI_ADCV_RD_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_CONT_POS, ADI_ADCV_CONT_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_DCP_POS, ADI_ADCV_DCP_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RSTF_POS, ADI_ADCV_RSTF_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_OW01_POS, ADI_ADCV_OW01_LEN, 0u); + ADI_TransmitCommand(adi_command, adiState); + ADI_Wait(ADI_IIR_SETTLING_TIME_ms); +} + +static void ADI_WakeUpDaisyChain(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + /* Send dummy bytes to wake up the daisy chain */ + uint16_t txData = 0u; + /* Send dummy byte and wait at least T_wake for each device to wake up */ + ADI_SpiTransmitReceiveData(adiState, &txData, NULL_PTR, 0u); + ADI_Wait(ADI_AFE_WAKEUP_TIME); + + /* Send dummy byte and wait at least T_ready for each isoSPI to get active */ + ADI_SpiTransmitReceiveData(adiState, &txData, NULL_PTR, 0u); + ADI_Wait(ADI_ISO_SPI_WAKEUP_TIME); +} + +/*========== Extern Function Implementations ================================*/ +/* RequirementId: D7.1 V0R4 FUN-4.10.01.01 */ +/* RequirementId: D7.1 V0R4 FUN-4.10.01.02 */ +/* RequirementId: D7.1 V0R4 FUN-4.10.02.01 */ +/* RequirementId: D7.1 V0R4 FUN-6.10.02.01 */ +extern void ADI_InitializeMeasurement(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + adiState->spiNumberInterfaces = BS_NR_OF_STRINGS; + adiState->currentString = 0u; + + ADI_ResetErrorTable(adiState); + + while (adiState->currentString < adiState->spiNumberInterfaces) { + adiState->redundantAuxiliaryChannel[adiState->currentString] = ADI_START_AUX_CHANNEL; + + /* Wake up daisy-chain */ + ADI_WakeUpDaisyChain(adiState); + /* Issue soft reset to be sure that all AFEs are in the reset state */ + ADI_CopyCommandBits(adi_cmdSrst, adi_command); + ADI_TransmitCommand(adi_command, adiState); + ADI_Wait(ADI_TSOFTRESET_ms); + /* Wake up daisy-chain */ + ADI_WakeUpDaisyChain(adiState); + ADI_ClearCommandCounter(adiState); /* reset command counter */ + + /* Set default configuration in AFE Driver storage */ + ADI_InitializeConfiguration(adiState); + /* REFON bit in configuration register A must be set before checking reset/cleared values */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, ADI_REGISTER_OFFSET0, 1u, ADI_CFGRA0_REFON_POS, ADI_CFGRA0_REFON_MASK, adiState); + /* Write default configuration from AFE Driver storage to daisy-chain, for all registers */ + ADI_StoredConfigurationWriteToAfeGlobal(adiState); + + ADI_Wait(ADI_TREFUP_ms); + + ADI_DisableBalancingOnStartup(adiState); + + ADI_ResetIirFilterOnStartup(adiState); + + /* Clear all flags in Status Register Group C */ + ADI_ClearAllFlagsInStatusRegisterGroupC(adiState); + + /* TODO: why and what happens here?! */ + ADI_CopyCommandBits(adi_cmdRdstatc, adi_command); + ADI_ReadRegister(adi_command, adi_dataReceive, adiState); + for (uint16_t m = 0u; m < ADI_N_ADI; m++) { + /* Get STR5 */ + uint8_t statusData = adi_dataReceive[(m * ADI_RDSTATC_LEN) + ADI_REGISTER_OFFSET5]; + /* Check COMP flag */ + uint8_t flagComp = 0u; + ADI_ReadDataBits(statusData, &flagComp, ADI_STCR5_COMP_POS, ADI_STCR5_COMP_MASK); + if (flagComp != 1u) { + adiState->data.errorTable->compFlagIsCleared[adiState->currentString][m] = false; + } + } + + /* Start continuous cell voltage measurements */ + ADI_StartContinuousCellVoltageMeasurements(adiState); + /* Read serial IDs of all ICs in string */ + ADI_GetSerialIdsOfAllIcsInString(adiState); + /* Read revisions of all ICs in string */ + ADI_GetRevisionOfAllIcsInString(adiState); + ++adiState->currentString; + } + adiState->currentString = 0u; +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_ADI_ClearAllFlagsInStatusRegisterGroupC(ADI_STATE_s *adiState) { + ADI_ClearAllFlagsInStatusRegisterGroupC(adiState); +} +extern void TEST_ADI_DisableBalancingOnStartup(ADI_STATE_s *adiState) { + ADI_DisableBalancingOnStartup(adiState); +} +extern void TEST_ADI_GetRevisionOfAllIcsInString(ADI_STATE_s *adiState) { + ADI_GetRevisionOfAllIcsInString(adiState); +} +extern void TEST_ADI_GetSerialIdsOfAllIcsInString(ADI_STATE_s *adiState) { + ADI_GetSerialIdsOfAllIcsInString(adiState); +} +extern void TEST_ADI_InitializeConfiguration(ADI_STATE_s *adiState) { + ADI_InitializeConfiguration(adiState); +} +extern void TEST_ADI_ResetErrorTable(ADI_STATE_s *adiState) { + ADI_ResetErrorTable(adiState); +} +extern void TEST_ADI_StartContinuousCellVoltageMeasurements(ADI_STATE_s *adiState) { + ADI_StartContinuousCellVoltageMeasurements(adiState); +} +extern void TEST_ADI_WakeUpDaisyChain(ADI_STATE_s *adiState) { + ADI_WakeUpDaisyChain(adiState); +} +extern void TEST_ADI_ResetIirFilterOnStartup(ADI_STATE_s *adiState) { + ADI_ResetIirFilterOnStartup(adiState); +} +#endif diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_initialization.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_initialization.h new file mode 100644 index 00000000..713c9669 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_initialization.h @@ -0,0 +1,89 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_initialization.h + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Header file of some software + * + */ + +#ifndef FOXBMS__ADI_ADES183X_INITIALIZATION_H_ +#define FOXBMS__ADI_ADES183X_INITIALIZATION_H_ + +/*========== Includes =======================================================*/ +#include "adi_ades183x_defs.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Extern Constant and Variable Declarations ======================*/ + +/*========== Extern Function Prototypes =====================================*/ + +/** + * @brief Implements the initialization for the ades183x driver. + * @details This function contains the sequence of events + * @param adiState state of the driver + */ +extern void ADI_InitializeMeasurement(ADI_STATE_s *adiState); + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_ADI_ClearAllFlagsInStatusRegisterGroupC(ADI_STATE_s *adiState); +extern void TEST_ADI_DisableBalancingOnStartup(ADI_STATE_s *adiState); +extern void TEST_ADI_GetRevisionOfAllIcsInString(ADI_STATE_s *adiState); +extern void TEST_ADI_GetSerialIdsOfAllIcsInString(ADI_STATE_s *adiState); +extern void TEST_ADI_InitializeConfiguration(ADI_STATE_s *adiState); +extern void TEST_ADI_ResetErrorTable(ADI_STATE_s *adiState); +extern void TEST_ADI_StartContinuousCellVoltageMeasurements(ADI_STATE_s *adiState); +extern void TEST_ADI_WakeUpDaisyChain(ADI_STATE_s *adiState); +extern void TEST_ADI_ResetIirFilterOnStartup(ADI_STATE_s *adiState); +#endif + +#endif /* FOXBMS__ADI_ADES183X_INITIALIZATION_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_temperatures.c b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_temperatures.c new file mode 100644 index 00000000..08b5780d --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_temperatures.c @@ -0,0 +1,123 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_temperatures.c + * @author foxBMS Team + * @date 2019-08-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix ADI + * + * @brief Implementation of some software + * + */ + +/*========== Includes =======================================================*/ + +#include "adi_ades183x_temperatures.h" + +#include "adi_ades183x_cfg.h" + +#include "fassert.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ +/** + * @brief Converts index of read GPIO voltages for temperatures. + * @details This function translates the indexes of read GPIO voltages so that + * if some inputs are unused, they do not appear in the final cell + * temperature table. + * @param registerGpioIndex index of the read voltage ion the ades183x + * register + * @return index where the voltage must be stored if it is used + */ +static uint16_t ADI_GetStoredTemperatureIndex(uint16_t registerGpioIndex); + +/*========== Static Function Implementations ================================*/ +static uint16_t ADI_GetStoredTemperatureIndex(uint16_t registerGpioIndex) { + FAS_ASSERT(registerGpioIndex < BS_NR_OF_GPIOS_PER_MODULE); + + uint16_t storedTemperatureIndex = 0u; + for (uint8_t c = 0; c < registerGpioIndex; c++) { + if (adi_temperatureInputsUsed[c] == 1u) { + storedTemperatureIndex++; + } + } + + return storedTemperatureIndex; +} + +/*========== Extern Function Implementations ================================*/ +/* RequirementId: D7.1 V0R4 FUN-2.10.01.01 */ +extern void ADI_GetTemperatures(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint16_t registerGpioIndex = 0u; registerGpioIndex < BS_NR_OF_GPIOS_PER_MODULE; registerGpioIndex++) { + if (adi_temperatureInputsUsed[registerGpioIndex] == 1u) { + uint16_t storedTemperatureIndex = ADI_GetStoredTemperatureIndex(registerGpioIndex); + int16_t temperature = ADI_ConvertGpioVoltageToTemperature( + adiState->data.allGpioVoltages->gpioVoltages_mV[adiState->currentString] + [(m * BS_NR_OF_GPIOS_PER_MODULE) + + registerGpioIndex]); /* unit: decidegree C */ + adiState->data.cellTemperature + ->cellTemperature_ddegC[adiState->currentString][m][storedTemperatureIndex] = temperature; + } + } + } +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +extern uint16_t TEST_ADI_GetStoredTemperatureIndex(uint16_t registerGpioIndex) { + return ADI_GetStoredTemperatureIndex(registerGpioIndex); +} + +#endif diff --git a/src/app/driver/afe/nxp/mc33775a/config/nxp_afe_dma_cfg.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_temperatures.h similarity index 77% rename from src/app/driver/afe/nxp/mc33775a/config/nxp_afe_dma_cfg.h rename to src/app/driver/afe/adi/common/ades183x/adi_ades183x_temperatures.h index 362be0ff..573e27e4 100644 --- a/src/app/driver/afe/nxp/mc33775a/config/nxp_afe_dma_cfg.h +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_temperatures.h @@ -40,28 +40,23 @@ */ /** - * @file nxp_afe_dma_cfg.h + * @file adi_ades183x_temperatures.h * @author foxBMS Team - * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS - * @prefix DMA - * - * @brief Headers for the configuration for the DMA module + * @prefix ADI * + * @brief Header file of some software * */ -#ifndef FOXBMS__NXP_AFE_DMA_CFG_H_ -#define FOXBMS__NXP_AFE_DMA_CFG_H_ +#ifndef FOXBMS__ADI_ADES183X_TEMPERATURES_H_ +#define FOXBMS__ADI_ADES183X_TEMPERATURES_H_ /*========== Includes =======================================================*/ - -#include "battery_system_cfg.h" -#include "dma_cfg.h" - -#include "HL_sys_dma.h" +#include "adi_ades183x_defs.h" #include @@ -71,8 +66,17 @@ /*========== Extern Function Prototypes =====================================*/ +/** + * @brief Store temperatures converted from GPIO voltages. + * @details This function takes the GPIO voltages, converts them to + * temperatures and stores the temperatures. + * @param adiState state of the ADI driver + */ +extern void ADI_GetTemperatures(ADI_STATE_s *adiState); + /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST +extern uint16_t TEST_ADI_GetStoredTemperatureIndex(uint16_t registerGpioIndex); #endif -#endif /* FOXBMS__NXP_AFE_DMA_CFG_H_ */ +#endif /* FOXBMS__ADI_ADES183X_TEMPERATURES_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_voltages.c b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_voltages.c new file mode 100644 index 00000000..9dfa3e75 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_voltages.c @@ -0,0 +1,472 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_voltages.c + * @author foxBMS Team + * @date 2019-08-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup SOME_GROUP + * @prefix ADI + * + * @brief Implementation of some software + * + */ + +/*========== Includes =======================================================*/ +#include "adi_ades183x_voltages.h" + +#include "adi_ades183x_cfg.h" + +#include "adi_ades183x_buffers.h" +#include "adi_ades183x_commands.h" +#include "adi_ades183x_commands_voltages.h" +#include "adi_ades183x_diagnostic.h" +#include "adi_ades183x_helpers.h" +#include "fassert.h" + +#include +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/** + * @brief Copies the related command bytes to read the average voltage + * registers + * @param commandBytesToReadVoltageRegisters command bytes to be copied + */ +static void ADI_CopyCommandBytesAverageCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters); + +/** + * @brief Copies the related command bytes to read the voltage registers + * @param commandBytesToReadVoltageRegisters command bytes to be copied + */ +static void ADI_CopyCommandBytesCellVoltageRegister(ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters); + +/** + * @brief Copies the related command bytes to read the filtered voltage + * registers + * @param commandBytesToReadVoltageRegisters command bytes to be copied + */ +static void ADI_CopyCommandBytesFilteredCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters); + +/** + * @brief Copies the related command bytes to read the redundant voltage + * registers + * @param commandBytesToReadVoltageRegisters command bytes to be copied + */ +static void ADI_CopyCommandBytesRedundantCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters); + +/** + * @brief Copies the related command bytes to read the average voltage + * registers + * @param adiState state of the ADI driver + * @param commandBytesToReadVoltageRegisters command bytes to be copied + * @param storeLocation location where read data has to + * be stored + */ +static void ADI_ReadAndStoreVoltages( + ADI_STATE_s *adiState, + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation); + +/** + * @brief Saves the cell voltage values read from the daisy-chain. + * @details There are 6 register to read _(A, B, C, D, E, F) to get all cell + * voltages. + * This function is called to store the result from the transmission + * buffer to the appropriate location in the driver. + * @param adiState state of the ADI driver + * @param data receive buffer + * @param registerSet voltage register that was read (voltage register A, + * B, C, D, E or F) + * @param storeLocation location where read data has to be stored + */ +static void ADI_SaveRxToCellVoltageBuffer( + ADI_STATE_s *adiState, + uint8_t *data, + uint8_t registerSet, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation); + +/*========== Static Function Implementations ================================*/ + +static void ADI_CopyCommandBytesCellVoltageRegister(ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters) { + FAS_ASSERT(commandBytesToReadVoltageRegisters != NULL_PTR); + ADI_CopyCommandBits(adi_cmdRdcva, commandBytesToReadVoltageRegisters->registerA); + ADI_CopyCommandBits(adi_cmdRdcvb, commandBytesToReadVoltageRegisters->registerB); + ADI_CopyCommandBits(adi_cmdRdcvc, commandBytesToReadVoltageRegisters->registerC); + ADI_CopyCommandBits(adi_cmdRdcvd, commandBytesToReadVoltageRegisters->registerD); + ADI_CopyCommandBits(adi_cmdRdcve, commandBytesToReadVoltageRegisters->registerE); + ADI_CopyCommandBits(adi_cmdRdcvf, commandBytesToReadVoltageRegisters->registerF); +} + +static void ADI_CopyCommandBytesAverageCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters) { + FAS_ASSERT(commandBytesToReadVoltageRegisters != NULL_PTR); + ADI_CopyCommandBits(adi_cmdRdaca, commandBytesToReadVoltageRegisters->registerA); + ADI_CopyCommandBits(adi_cmdRdacb, commandBytesToReadVoltageRegisters->registerB); + ADI_CopyCommandBits(adi_cmdRdacc, commandBytesToReadVoltageRegisters->registerC); + ADI_CopyCommandBits(adi_cmdRdacd, commandBytesToReadVoltageRegisters->registerD); + ADI_CopyCommandBits(adi_cmdRdace, commandBytesToReadVoltageRegisters->registerE); + ADI_CopyCommandBits(adi_cmdRdacf, commandBytesToReadVoltageRegisters->registerF); +} + +static void ADI_CopyCommandBytesFilteredCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters) { + FAS_ASSERT(commandBytesToReadVoltageRegisters != NULL_PTR); + ADI_CopyCommandBits(adi_cmdRdfca, commandBytesToReadVoltageRegisters->registerA); + ADI_CopyCommandBits(adi_cmdRdfcb, commandBytesToReadVoltageRegisters->registerB); + ADI_CopyCommandBits(adi_cmdRdfcc, commandBytesToReadVoltageRegisters->registerC); + ADI_CopyCommandBits(adi_cmdRdfcd, commandBytesToReadVoltageRegisters->registerD); + ADI_CopyCommandBits(adi_cmdRdfce, commandBytesToReadVoltageRegisters->registerE); + ADI_CopyCommandBits(adi_cmdRdfcf, commandBytesToReadVoltageRegisters->registerF); +} + +static void ADI_CopyCommandBytesRedundantCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters) { + FAS_ASSERT(commandBytesToReadVoltageRegisters != NULL_PTR); + ADI_CopyCommandBits(adi_cmdRdsva, commandBytesToReadVoltageRegisters->registerA); + ADI_CopyCommandBits(adi_cmdRdsvb, commandBytesToReadVoltageRegisters->registerB); + ADI_CopyCommandBits(adi_cmdRdsvc, commandBytesToReadVoltageRegisters->registerC); + ADI_CopyCommandBits(adi_cmdRdsvd, commandBytesToReadVoltageRegisters->registerD); + ADI_CopyCommandBits(adi_cmdRdsve, commandBytesToReadVoltageRegisters->registerE); + ADI_CopyCommandBits(adi_cmdRdsvf, commandBytesToReadVoltageRegisters->registerF); +} + +static void ADI_ReadAndStoreVoltages( + ADI_STATE_s *adiState, + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation) { + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(commandBytesToReadVoltageRegisters != NULL_PTR); + FAS_ASSERT(storeLocation < ADI_VOLTAGE_STORE_LOCATION_E_MAX); + + ADI_ReadRegister(commandBytesToReadVoltageRegisters->registerA, adi_dataReceive, adiState); + ADI_SaveRxToCellVoltageBuffer(adiState, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, storeLocation); + + ADI_ReadRegister(commandBytesToReadVoltageRegisters->registerB, adi_dataReceive, adiState); + ADI_SaveRxToCellVoltageBuffer(adiState, adi_dataReceive, ADI_RESULT_REGISTER_SET_B, storeLocation); + + ADI_ReadRegister(commandBytesToReadVoltageRegisters->registerC, adi_dataReceive, adiState); + ADI_SaveRxToCellVoltageBuffer(adiState, adi_dataReceive, ADI_RESULT_REGISTER_SET_C, storeLocation); + + ADI_ReadRegister(commandBytesToReadVoltageRegisters->registerD, adi_dataReceive, adiState); + ADI_SaveRxToCellVoltageBuffer(adiState, adi_dataReceive, ADI_RESULT_REGISTER_SET_D, storeLocation); + + ADI_ReadRegister(commandBytesToReadVoltageRegisters->registerE, adi_dataReceive, adiState); + ADI_SaveRxToCellVoltageBuffer(adiState, adi_dataReceive, ADI_RESULT_REGISTER_SET_E, storeLocation); + + ADI_ReadRegister(commandBytesToReadVoltageRegisters->registerF, adi_dataReceive, adiState); + ADI_SaveRxToCellVoltageBuffer(adiState, adi_dataReceive, ADI_RESULT_REGISTER_SET_F, storeLocation); +} + +/* RequirementId: D7.1 V0R4 FUN-1.10.01.03 */ +static void ADI_SaveRxToCellVoltageBuffer( + ADI_STATE_s *adiState, + uint8_t *data, + uint8_t registerSet, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation) { + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT(data != NULL_PTR); + FAS_ASSERT( + (registerSet == ADI_RESULT_REGISTER_SET_A) || (registerSet == ADI_RESULT_REGISTER_SET_B) || + (registerSet == ADI_RESULT_REGISTER_SET_C) || (registerSet == ADI_RESULT_REGISTER_SET_D) || + (registerSet == ADI_RESULT_REGISTER_SET_E) || (registerSet == ADI_RESULT_REGISTER_SET_F)); + FAS_ASSERT(storeLocation < ADI_VOLTAGE_STORE_LOCATION_E_MAX); + + uint16_t cellOffset = 0u; + uint16_t registerVoltageIndex = 0u; + uint16_t storedVoltageIndex = 0u; + uint16_t rawValue = 0u; + int16_t signedValue = 0; + float_t floatVoltage = 0.0f; + int16_t voltage = 0; + uint16_t bufferLSB = 0u; + uint16_t bufferMSB = 0u; + DATA_BLOCK_CELL_VOLTAGE_s *pVoltageTable = NULL_PTR; + static uint16_t numberValidMeasurements = 0; + + if ((storeLocation == ADI_CELL_VOLTAGE) && (registerSet == ADI_RESULT_REGISTER_SET_A)) { + numberValidMeasurements = 0u; + } + + switch (storeLocation) { + case ADI_CELL_VOLTAGE: + pVoltageTable = adiState->data.cellVoltage; + break; + case ADI_AVERAGE_CELL_VOLTAGE: + pVoltageTable = adiState->data.cellVoltageAverage; + break; + case ADI_FILTERED_CELL_VOLTAGE: + pVoltageTable = adiState->data.cellVoltageFiltered; + break; + case ADI_REDUNDANT_CELL_VOLTAGE: + pVoltageTable = adiState->data.cellVoltageRedundant; + break; + case ADI_CELL_VOLTAGE_OPEN_WIRE_EVEN: + pVoltageTable = adiState->data.cellVoltageOpenWireEven; + break; + case ADI_CELL_VOLTAGE_OPEN_WIRE_ODD: + pVoltageTable = adiState->data.cellVoltageOpenWireOdd; + break; + case ADI_CELL_VOLTAGE_AVERAGE_OPEN_WIRE: + pVoltageTable = adiState->data.cellVoltageAverageOpenWire; + break; + case ADI_CELL_VOLTAGE_REDUNDANT_OPEN_WIRE: + pVoltageTable = adiState->data.cellVoltageRedundantOpenWire; + break; + default: /* LCOV_EXCL_LINE */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } + + switch (registerSet) { + case ADI_RESULT_REGISTER_SET_A: /* Voltage register group A: 3 voltages */ + cellOffset = ADI_VOLTAGE_00_02_OFFSET; + break; + case ADI_RESULT_REGISTER_SET_B: /* Voltage register group B: 3 voltages */ + cellOffset = ADI_VOLTAGE_03_05_OFFSET; + break; + case ADI_RESULT_REGISTER_SET_C: /* Voltage register group C: 3 voltages */ + cellOffset = ADI_VOLTAGE_06_08_OFFSET; + break; + case ADI_RESULT_REGISTER_SET_D: /* Voltage register group D: 3 voltages */ + cellOffset = ADI_VOLTAGE_09_11_OFFSET; + break; + case ADI_RESULT_REGISTER_SET_E: /* Voltage register group E: 3 voltages */ + cellOffset = ADI_VOLTAGE_12_14_OFFSET; + break; + case ADI_RESULT_REGISTER_SET_F: /* Voltage register group F: */ + cellOffset = ADI_VOLTAGE_15_18_OFFSET; + break; + default: /* LCOV_EXCL_LINE */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } + + for (uint16_t m = 0u; m < ADI_N_ADI; m++) { + /* Parse all voltages contained in one register */ + for (uint16_t c = 0u; c < ADI_MAX_NUMBER_OF_VOLTAGES_IN_REGISTER; c++) { + registerVoltageIndex = c + cellOffset; + if (registerVoltageIndex < ADI_MAX_SUPPORTED_CELLS) { + /* Check if cell voltage input is used */ + if (adi_voltageInputsUsed[registerVoltageIndex] == 1u) { + /* If input used, translate number to store voltage at the appropriate location */ + storedVoltageIndex = ADI_GetStoredVoltageIndex(registerVoltageIndex); + if (storedVoltageIndex < BS_NR_OF_CELL_BLOCKS_PER_MODULE) { + bufferMSB = (uint16_t)(data + [(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES) + 1u]); + bufferLSB = (uint16_t)(data + [(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)]); + rawValue = bufferLSB | (bufferMSB << ADI_BYTE_SHIFT); + signedValue = (int16_t)rawValue; + floatVoltage = + ((float_t)signedValue * ADI_VOLTAGE_CONVERSION_FACTOR * ADI_VOLTAGE_CONVERSION_UNIT) + + ADI_VOLTAGE_CONVERSION_OFFSET; + voltage = (int16_t)floatVoltage; /* Unit mV */ + + pVoltageTable->cellVoltage_mV[adiState->currentString][m][storedVoltageIndex] = voltage; + /* RequirementId: D7.1 V0R4 SIF-4.40.01.01 */ + /* Check that register does not contain cleared value */ + if (rawValue != ADI_REGISTER_CLEARED_VALUE) { + adiState->data.errorTable->voltageRegisterContentIsNotStuck[adiState->currentString][m] = + true; + } else { + adiState->data.errorTable->voltageRegisterContentIsNotStuck[adiState->currentString][m] = + false; + } + + if (storeLocation == ADI_CELL_VOLTAGE) { + if (ADI_EvaluateDiagnosticCellVoltages(adiState, m) == false) { + adiState->data.cellVoltage->invalidCellVoltage[adiState->currentString][m] |= + (0x01u << storedVoltageIndex); + } else { + adiState->data.cellVoltage->invalidCellVoltage[adiState->currentString][m] &= + (~0x01u << storedVoltageIndex); + numberValidMeasurements++; + } + } + } + } + } + } + } + if ((storeLocation == ADI_CELL_VOLTAGE) && (registerSet == ADI_RESULT_REGISTER_SET_F)) { + adiState->data.cellVoltage->nrValidCellVoltages[adiState->currentString] = numberValidMeasurements; + } +} + +/*========== Extern Function Implementations ================================*/ +/* RequirementId: D7.1 V0R4 FUN-1.10.01.01 */ +extern void ADI_GetVoltages( + ADI_STATE_s *adiState, + ADI_VOLTAGE_REGISTER_TYPE_e registerType, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation) { + FAS_ASSERT(adiState != NULL_PTR); + FAS_ASSERT( + (registerType == ADI_CELL_VOLTAGE_REGISTER) || (registerType == ADI_AVERAGE_CELL_VOLTAGE_REGISTER) || + (registerType == ADI_FILTERED_CELL_VOLTAGE_REGISTER) || (registerType == ADI_REDUNDANT_CELL_VOLTAGE_REGISTER)); + FAS_ASSERT(storeLocation < ADI_VOLTAGE_STORE_LOCATION_E_MAX); + + ADI_COMMAND_READ_REGISTERS_s commandBytesToReadVoltageRegisters = { + .registerA = {0}, + .registerB = {0}, + .registerC = {0}, + .registerD = {0}, + .registerE = {0}, + .registerF = {0}, + }; + + switch (registerType) { + case ADI_CELL_VOLTAGE_REGISTER: + ADI_CopyCommandBytesCellVoltageRegister(&commandBytesToReadVoltageRegisters); + break; + case ADI_AVERAGE_CELL_VOLTAGE_REGISTER: + ADI_CopyCommandBytesAverageCellVoltageRegisters(&commandBytesToReadVoltageRegisters); + break; + case ADI_FILTERED_CELL_VOLTAGE_REGISTER: + ADI_CopyCommandBytesFilteredCellVoltageRegisters(&commandBytesToReadVoltageRegisters); + break; + case ADI_REDUNDANT_CELL_VOLTAGE_REGISTER: + ADI_CopyCommandBytesRedundantCellVoltageRegisters(&commandBytesToReadVoltageRegisters); + break; + default: /* LCOV_EXCL_LINE */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } + ADI_ReadAndStoreVoltages(adiState, &commandBytesToReadVoltageRegisters, storeLocation); +} + +extern uint16_t ADI_GetStoredVoltageIndex(uint16_t registerVoltageIndex) { + FAS_ASSERT(registerVoltageIndex < ADI_MAX_SUPPORTED_CELLS); + + uint16_t storedVoltageIndex = 0u; + for (uint8_t c = 0; c < registerVoltageIndex; c++) { + if (adi_voltageInputsUsed[c] == 1u) { + storedVoltageIndex++; + } + } + return storedVoltageIndex; +} + +extern void ADI_RestartContinuousCellVoltageMeasurements(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + ADI_CopyCommandBits(adi_cmdAdcv, adi_command); + /** + * SM_VCELL_RED: Cell Voltage Measurement Redundancy + * Set RD bit to enable redundant cell voltage measurements + */ + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RD_POS, ADI_ADCV_RD_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_CONT_POS, ADI_ADCV_CONT_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_DCP_POS, ADI_ADCV_DCP_LEN, 0u); + /* Restart measurement: do not reset IIR filter to keep current filtered values */ + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RSTF_POS, ADI_ADCV_RSTF_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_OW01_POS, ADI_ADCV_OW01_LEN, 0u); + ADI_TransmitCommand(adi_command, adiState); + ADI_Wait(ADI_MEASUREMENT_RESTART_WAIT_TIME_ms); +} + +extern void ADI_StopContinuousCellVoltageMeasurements(ADI_STATE_s *adiState) { + FAS_ASSERT(adiState != NULL_PTR); + + ADI_CopyCommandBits(adi_cmdAdcv, adi_command); + /* Start one single-shot measurement without redundancy, after the measurements are stopped */ + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RD_POS, ADI_ADCV_RD_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_CONT_POS, ADI_ADCV_CONT_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_DCP_POS, ADI_ADCV_DCP_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RSTF_POS, ADI_ADCV_RSTF_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_OW01_POS, ADI_ADCV_OW01_LEN, 0u); + ADI_TransmitCommand(adi_command, adiState); + ADI_Wait(ADI_MEASUREMENT_STOP_WAIT_TIME_ms); +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST + +extern void TEST_ADI_CopyCommandBytesCellVoltageRegister( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters) { + ADI_CopyCommandBytesCellVoltageRegister(commandBytesToReadVoltageRegisters); +} + +extern void TEST_ADI_CopyCommandBytesAverageCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters) { + ADI_CopyCommandBytesAverageCellVoltageRegisters(commandBytesToReadVoltageRegisters); +} + +extern void TEST_ADI_CopyCommandBytesFilteredCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters) { + ADI_CopyCommandBytesFilteredCellVoltageRegisters(commandBytesToReadVoltageRegisters); +} + +extern void TEST_ADI_CopyCommandBytesRedundantCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters) { + ADI_CopyCommandBytesRedundantCellVoltageRegisters(commandBytesToReadVoltageRegisters); +} + +extern void TEST_ADI_ReadAndStoreVoltages( + ADI_STATE_s *adiState, + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation) { + ADI_ReadAndStoreVoltages(adiState, commandBytesToReadVoltageRegisters, storeLocation); +} + +extern void TEST_ADI_SaveRxToCellVoltageBuffer( + ADI_STATE_s *adiState, + uint8_t *data, + uint8_t registerSet, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation) { + ADI_SaveRxToCellVoltageBuffer(adiState, data, registerSet, storeLocation); +} +#endif diff --git a/src/app/driver/afe/adi/common/ades183x/adi_ades183x_voltages.h b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_voltages.h new file mode 100644 index 00000000..239dfe32 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/adi_ades183x_voltages.h @@ -0,0 +1,139 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_voltages.h + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Header file of some software + * + */ + +#ifndef FOXBMS__ADI_ADES183X_VOLTAGES_H_ +#define FOXBMS__ADI_ADES183X_VOLTAGES_H_ + +/*========== Includes =======================================================*/ + +#include "adi_ades183x_defs.h" + +#include + +/*========== Macros and Definitions =========================================*/ +/** Struct to group the commands to read the registers A to F */ +typedef struct { + uint16_t registerA[ADI_COMMAND_DEFINITION_LENGTH]; + uint16_t registerB[ADI_COMMAND_DEFINITION_LENGTH]; + uint16_t registerC[ADI_COMMAND_DEFINITION_LENGTH]; + uint16_t registerD[ADI_COMMAND_DEFINITION_LENGTH]; + uint16_t registerE[ADI_COMMAND_DEFINITION_LENGTH]; + uint16_t registerF[ADI_COMMAND_DEFINITION_LENGTH]; +} ADI_COMMAND_READ_REGISTERS_s; + +/*========== Extern Constant and Variable Declarations ======================*/ + +/*========== Extern Function Prototypes =====================================*/ + +/** + * @brief Converts index of read voltages. + * @details This function translates the indexes of read voltages so that + * if some inputs are unused, they do not appear in the final + * cell voltage table + * @param registerVoltageIndex index of the read voltage ion the ades183x + * register + * @return index where the voltage must be stored if it is used + */ +extern uint16_t ADI_GetStoredVoltageIndex(uint16_t registerVoltageIndex); + +/** + * @brief Reads and stores cell voltages. + * @details This function, reads the raw values from the registers, and + * calls ADI_SaveRxToCellVoltageBuffer() which convert them into + * voltages and stores them. + * @param adiState state of the ADI driver + * @param registerType type of voltage register to read + * @param storeLocation location where read data has to be stored + */ +extern void ADI_GetVoltages( + ADI_STATE_s *adiState, + ADI_VOLTAGE_REGISTER_TYPE_e registerType, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation); + +/** + * @brief Stop cell voltage measurement. + * @details This function should be called before activation of balancing + * @param adiState state of the driver + */ +extern void ADI_StopContinuousCellVoltageMeasurements(ADI_STATE_s *adiState); + +/** + * @brief Restart cell voltage measurement. + * @details This function should be called after deactivation of balancing + * @param adiState state of the driver + */ +extern void ADI_RestartContinuousCellVoltageMeasurements(ADI_STATE_s *adiState); + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_ADI_CopyCommandBytesCellVoltageRegister( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters); +extern void TEST_ADI_CopyCommandBytesAverageCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters); +extern void TEST_ADI_CopyCommandBytesFilteredCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters); +extern void TEST_ADI_CopyCommandBytesRedundantCellVoltageRegisters( + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters); +extern void TEST_ADI_ReadAndStoreVoltages( + ADI_STATE_s *adiState, + ADI_COMMAND_READ_REGISTERS_s *commandBytesToReadVoltageRegisters, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation); +extern void TEST_ADI_SaveRxToCellVoltageBuffer( + ADI_STATE_s *adiState, + uint8_t *data, + uint8_t registerSet, + ADI_VOLTAGE_STORE_LOCATION_e storeLocation); +#endif + +#endif /* FOXBMS__ADI_ADES183X_VOLTAGES_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe.c b/src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe.c new file mode 100644 index 00000000..d27f6ac6 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe.c @@ -0,0 +1,144 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_afe.c + * @author foxBMS Team + * @date 2020-05-08 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix AFE + * + * @brief AFE driver implementation for ADI ICs + */ + +/*========== Includes =======================================================*/ +/* clang-format off */ +#include "afe.h" +/* clang-format on */ + +#include "adi_ades183x.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +extern STD_RETURN_TYPE_e AFE_TriggerIc(void) { + ADI_MeasurementCycle(&adi_stateBase); + return STD_OK; +} + +extern STD_RETURN_TYPE_e AFE_Initialize(void) { + ADI_ActivateInterfaceBoard(); + return STD_OK; +} + +extern STD_RETURN_TYPE_e AFE_RequestEepromRead(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + STD_RETURN_TYPE_e retval = STD_OK; + + return retval; +} + +extern STD_RETURN_TYPE_e AFE_RequestEepromWrite(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + STD_RETURN_TYPE_e retval = STD_OK; + + return retval; +} + +extern STD_RETURN_TYPE_e AFE_RequestTemperatureRead(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + STD_RETURN_TYPE_e retval = STD_OK; + + return retval; +} + +extern STD_RETURN_TYPE_e AFE_RequestBalancingFeedbackRead(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + STD_RETURN_TYPE_e retval = STD_NOT_OK; + + return retval; +} + +extern STD_RETURN_TYPE_e AFE_RequestOpenWireCheck(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + STD_RETURN_TYPE_e retval = STD_OK; + + return retval; +} + +extern STD_RETURN_TYPE_e AFE_StartMeasurement(void) { + return ADI_MakeRequest(AFE_START_REQUEST); +} + +extern bool AFE_IsFirstMeasurementCycleFinished(void) { + return ADI_IsFirstMeasurementCycleFinished(&adi_stateBase); +} + +extern STD_RETURN_TYPE_e AFE_RequestIoRead(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + STD_RETURN_TYPE_e retval = STD_NOT_OK; + + return retval; +} + +extern STD_RETURN_TYPE_e AFE_RequestIoWrite(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + STD_RETURN_TYPE_e retval = STD_NOT_OK; + + return retval; +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe_dma.c b/src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe_dma.c new file mode 100644 index 00000000..1347db4d --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe_dma.c @@ -0,0 +1,84 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_afe_dma.c + * @author foxBMS Team + * @date 2020-05-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix AFE + * + * @brief Driver for the DMA module for the ADI driver. + * + */ + +/*========== Includes =======================================================*/ +#include "dma_cfg.h" + +#include "adi_ades183x.h" +#include "adi_ades183x_defs.h" +#include "afe_dma.h" +#include "ftask.h" +#include "spi.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +/* Function called on DMA complete interrupts (TX and RX). */ +void AFE_DmaCallback(uint8_t spiIndex) { + FAS_ASSERT(spiIndex == ADI_SPI_INDEX); + (void)OS_NotifyFromIsr(ftsk_taskHandleAfe, ADI_DMA_SPI_FINISHED_NOTIFICATION_VALUE); +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ diff --git a/src/app/driver/afe/debug/default/config/debug_default_cfg.c b/src/app/driver/afe/adi/common/ades183x/config/adi_ades183x_cfg.c similarity index 85% rename from src/app/driver/afe/debug/default/config/debug_default_cfg.c rename to src/app/driver/afe/adi/common/ades183x/config/adi_ades183x_cfg.c index 2c2b780a..7872bde6 100644 --- a/src/app/driver/afe/debug/default/config/debug_default_cfg.c +++ b/src/app/driver/afe/adi/common/ades183x/config/adi_ades183x_cfg.c @@ -40,20 +40,22 @@ */ /** - * @file debug_default_cfg.c + * @file adi_ades183x_cfg.c * @author foxBMS Team - * @date 2020-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2020-12-09 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION - * @prefix FAKE + * @prefix ADI * - * @brief Configuration for the fake AFE + * @brief Configuration for the ADI analog front-end * */ /*========== Includes =======================================================*/ -#include "debug_default_cfg.h" +#include "adi_ades183x_cfg.h" + +#include "tsi.h" #include @@ -69,6 +71,9 @@ /*========== Extern Function Implementations ================================*/ +int16_t ADI_ConvertGpioVoltageToTemperature(int16_t voltage_mV) { + /* AXIVION Routine Generic-MissingParameterAssert: voltage_mV: parameter accepts whole range */ + return TSI_GetTemperature((uint16_t)voltage_mV); +} + /*========== Externalized Static Function Implementations (Unit Test) =======*/ -#ifdef UNITY_UNIT_TEST -#endif diff --git a/src/app/driver/afe/debug/default/config/debug_default_cfg.h b/src/app/driver/afe/adi/common/ades183x/config/adi_ades183x_cfg.h similarity index 63% rename from src/app/driver/afe/debug/default/config/debug_default_cfg.h rename to src/app/driver/afe/adi/common/ades183x/config/adi_ades183x_cfg.h index 57363098..89ae9654 100644 --- a/src/app/driver/afe/debug/default/config/debug_default_cfg.h +++ b/src/app/driver/afe/adi/common/ades183x/config/adi_ades183x_cfg.h @@ -40,35 +40,68 @@ */ /** - * @file debug_default_cfg.h + * @file adi_ades183x_cfg.h * @author foxBMS Team - * @date 2020-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2020-12-09 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION - * @prefix FAKE + * @prefix ADI * - * @brief Header for the configuration for the fake AFE + * @brief Header for the configuration for the ADI analog front-end. * */ -#ifndef FOXBMS__DEBUG_DEFAULT_CFG_H_ -#define FOXBMS__DEBUG_DEFAULT_CFG_H_ +#ifndef FOXBMS__ADI_ADES183X_CFG_H_ +#define FOXBMS__ADI_ADES183X_CFG_H_ /*========== Includes =======================================================*/ - #include "battery_system_cfg.h" +#include "adi_ades183x_defs.h" + +#include #include /*========== Macros and Definitions =========================================*/ +/** Controls if PEC should be discarded (true) or not (false) */ +#define ADI_DISCARD_PEC (false) +#if !((ADI_DISCARD_PEC == false) || (ADI_DISCARD_PEC == true)) +#error "ADI_DISCARD_PEC can only have the value true of false" +#endif + +/** Index of the SPI used by the ADI driver */ +#define ADI_SPI_INDEX (SPI_SPI1_INDEX) + /*========== Extern Constant and Variable Declarations ======================*/ +/** + * Lookup table to indicate which voltage inputs are used + */ +extern const uint8_t adi_voltageInputsUsed[ADI_MAX_SUPPORTED_CELLS]; +/** + * Lookup table to indicate which GPIO inputs are used for temperature measurement + */ +extern const uint8_t adi_temperatureInputsUsed[BS_NR_OF_GPIOS_PER_MODULE]; + /*========== Extern Function Prototypes =====================================*/ +/** + * @brief converts a raw GPIO voltage to a temperature value in deciCelsius. + * + * The temperatures are read from NTC elements via voltage dividers. + * This function implements the look-up table between voltage and temperature, + * taking into account the NTC characteristics and the voltage divider. + * + * @param voltage_mV voltage read from the GPIO in mV + * + * @return temperature temperature value in deci °C + */ +extern int16_t ADI_ConvertGpioVoltageToTemperature(int16_t voltage_mV); + /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST #endif -#endif /* FOXBMS__DEBUG_DEFAULT_CFG_H_ */ +#endif /* FOXBMS__ADI_ADES183X_CFG_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/pec/adi_ades183x_pec.c b/src/app/driver/afe/adi/common/ades183x/pec/adi_ades183x_pec.c new file mode 100644 index 00000000..187580f9 --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/pec/adi_ades183x_pec.c @@ -0,0 +1,178 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_pec.c + * @author foxBMS Team + * @date 2019-12-12 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief PEC computations + * @details The CRC polynomials used are defined in the data sheets of the ICs. + * + */ + +/*========== Includes =======================================================*/ +#include "adi_ades183x_pec.h" + +#include "adi_ades183x.h" +#include "fassert.h" +#include "fstd_types.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +extern uint16_t ADI_Pec15(uint8_t length, uint8_t *data) { + FAS_ASSERT(length > 0u); + FAS_ASSERT(data != NULL_PTR); + + /* Pre-computed CRC15 Table for polynomial 0xC599 */ + static const uint16_t adi_crc15Table[ADI_PEC_PRECOMPUTED_TABLE_SIZE] = { + 0x0000u, 0x4599u, 0x4EABu, 0x0B32u, 0x58CFu, 0x1D56u, 0x1664u, 0x53FDu, 0x7407u, 0x319Eu, 0x3AACu, 0x7F35u, + 0x2CC8u, 0x6951u, 0x6263u, 0x27FAu, 0x2D97u, 0x680Eu, 0x633Cu, 0x26A5u, 0x7558u, 0x30C1u, 0x3BF3u, 0x7E6Au, + 0x5990u, 0x1C09u, 0x173Bu, 0x52A2u, 0x015Fu, 0x44C6u, 0x4FF4u, 0x0A6Du, 0x5B2Eu, 0x1EB7u, 0x1585u, 0x501Cu, + 0x03E1u, 0x4678u, 0x4D4Au, 0x08D3u, 0x2F29u, 0x6AB0u, 0x6182u, 0x241Bu, 0x77E6u, 0x327Fu, 0x394Du, 0x7CD4u, + 0x76B9u, 0x3320u, 0x3812u, 0x7D8Bu, 0x2E76u, 0x6BEFu, 0x60DDu, 0x2544u, 0x02BEu, 0x4727u, 0x4C15u, 0x098Cu, + 0x5A71u, 0x1FE8u, 0x14DAu, 0x5143u, 0x73C5u, 0x365Cu, 0x3D6Eu, 0x78F7u, 0x2B0Au, 0x6E93u, 0x65A1u, 0x2038u, + 0x07C2u, 0x425Bu, 0x4969u, 0x0CF0u, 0x5F0Du, 0x1A94u, 0x11A6u, 0x543Fu, 0x5E52u, 0x1BCBu, 0x10F9u, 0x5560u, + 0x069Du, 0x4304u, 0x4836u, 0x0DAFu, 0x2A55u, 0x6FCCu, 0x64FEu, 0x2167u, 0x729Au, 0x3703u, 0x3C31u, 0x79A8u, + 0x28EBu, 0x6D72u, 0x6640u, 0x23D9u, 0x7024u, 0x35BDu, 0x3E8Fu, 0x7B16u, 0x5CECu, 0x1975u, 0x1247u, 0x57DEu, + 0x0423u, 0x41BAu, 0x4A88u, 0x0F11u, 0x057Cu, 0x40E5u, 0x4BD7u, 0x0E4Eu, 0x5DB3u, 0x182Au, 0x1318u, 0x5681u, + 0x717Bu, 0x34E2u, 0x3FD0u, 0x7A49u, 0x29B4u, 0x6C2Du, 0x671Fu, 0x2286u, 0x2213u, 0x678Au, 0x6CB8u, 0x2921u, + 0x7ADCu, 0x3F45u, 0x3477u, 0x71EEu, 0x5614u, 0x138Du, 0x18BFu, 0x5D26u, 0x0EDBu, 0x4B42u, 0x4070u, 0x05E9u, + 0x0F84u, 0x4A1Du, 0x412Fu, 0x04B6u, 0x574Bu, 0x12D2u, 0x19E0u, 0x5C79u, 0x7B83u, 0x3E1Au, 0x3528u, 0x70B1u, + 0x234Cu, 0x66D5u, 0x6DE7u, 0x287Eu, 0x793Du, 0x3CA4u, 0x3796u, 0x720Fu, 0x21F2u, 0x646Bu, 0x6F59u, 0x2AC0u, + 0x0D3Au, 0x48A3u, 0x4391u, 0x0608u, 0x55F5u, 0x106Cu, 0x1B5Eu, 0x5EC7u, 0x54AAu, 0x1133u, 0x1A01u, 0x5F98u, + 0x0C65u, 0x49FCu, 0x42CEu, 0x0757u, 0x20ADu, 0x6534u, 0x6E06u, 0x2B9Fu, 0x7862u, 0x3DFBu, 0x36C9u, 0x7350u, + 0x51D6u, 0x144Fu, 0x1F7Du, 0x5AE4u, 0x0919u, 0x4C80u, 0x47B2u, 0x022Bu, 0x25D1u, 0x6048u, 0x6B7Au, 0x2EE3u, + 0x7D1Eu, 0x3887u, 0x33B5u, 0x762Cu, 0x7C41u, 0x39D8u, 0x32EAu, 0x7773u, 0x248Eu, 0x6117u, 0x6A25u, 0x2FBCu, + 0x0846u, 0x4DDFu, 0x46EDu, 0x0374u, 0x5089u, 0x1510u, 0x1E22u, 0x5BBBu, 0x0AF8u, 0x4F61u, 0x4453u, 0x01CAu, + 0x5237u, 0x17AEu, 0x1C9Cu, 0x5905u, 0x7EFFu, 0x3B66u, 0x3054u, 0x75CDu, 0x2630u, 0x63A9u, 0x689Bu, 0x2D02u, + 0x276Fu, 0x62F6u, 0x69C4u, 0x2C5Du, 0x7FA0u, 0x3A39u, 0x310Bu, 0x7492u, 0x5368u, 0x16F1u, 0x1DC3u, 0x585Au, + 0x0BA7u, 0x4E3Eu, 0x450Cu, 0x0095u, + }; + + uint16_t pec = ADI_PEC15_SEED; + + for (uint8_t byte = 0u; byte < length; byte++) { + uint8_t position = + (uint8_t)(((pec >> (ADI_PEC15_POLYNOMIAL_SIZE - ADI_PEC_BYTE_SIZE)) ^ data[byte]) & ADI_PEC_ONE_BYTE_MASK); + pec = ((uint16_t)(pec << ADI_PEC_BYTE_SIZE)) ^ (uint16_t)(adi_crc15Table[position]); + } + + /* Shift one bit to the left because in AFE, PEC is stored in 16 bit register with one trailing 0 */ + return ((pec & ADI_PEC15_MASK) << 1u); +} + +uint16_t ADI_Pec10(uint8_t length, uint8_t *data, bool receive) { + FAS_ASSERT(length > 0u); + FAS_ASSERT(data != NULL_PTR); + /* AXIVION Routine Generic-MissingParameterAssert: receive: 'receive' is guaranteed to be be bool (true/false) + by the compiler */ + + /* Pre-computed CRC10 Table for polynomial 0x48F */ + static const uint16_t adi_crc10Table[ADI_PEC_PRECOMPUTED_TABLE_SIZE] = { + 0x000u, 0x08Fu, 0x11Eu, 0x191u, 0x23Cu, 0x2B3u, 0x322u, 0x3ADu, 0x0F7u, 0x078u, 0x1E9u, 0x166u, 0x2CBu, 0x244u, + 0x3D5u, 0x35Au, 0x1EEu, 0x161u, 0x0F0u, 0x07Fu, 0x3D2u, 0x35Du, 0x2CCu, 0x243u, 0x119u, 0x196u, 0x007u, 0x088u, + 0x325u, 0x3AAu, 0x23Bu, 0x2B4u, 0x3DCu, 0x353u, 0x2C2u, 0x24Du, 0x1E0u, 0x16Fu, 0x0FEu, 0x071u, 0x32Bu, 0x3A4u, + 0x235u, 0x2BAu, 0x117u, 0x198u, 0x009u, 0x086u, 0x232u, 0x2BDu, 0x32Cu, 0x3A3u, 0x00Eu, 0x081u, 0x110u, 0x19Fu, + 0x2C5u, 0x24Au, 0x3DBu, 0x354u, 0x0F9u, 0x076u, 0x1E7u, 0x168u, 0x337u, 0x3B8u, 0x229u, 0x2A6u, 0x10Bu, 0x184u, + 0x015u, 0x09Au, 0x3C0u, 0x34Fu, 0x2DEu, 0x251u, 0x1FCu, 0x173u, 0x0E2u, 0x06Du, 0x2D9u, 0x256u, 0x3C7u, 0x348u, + 0x0E5u, 0x06Au, 0x1FBu, 0x174u, 0x22Eu, 0x2A1u, 0x330u, 0x3BFu, 0x012u, 0x09Du, 0x10Cu, 0x183u, 0x0EBu, 0x064u, + 0x1F5u, 0x17Au, 0x2D7u, 0x258u, 0x3C9u, 0x346u, 0x01Cu, 0x093u, 0x102u, 0x18Du, 0x220u, 0x2AFu, 0x33Eu, 0x3B1u, + 0x105u, 0x18Au, 0x01Bu, 0x094u, 0x339u, 0x3B6u, 0x227u, 0x2A8u, 0x1F2u, 0x17Du, 0x0ECu, 0x063u, 0x3CEu, 0x341u, + 0x2D0u, 0x25Fu, 0x2E1u, 0x26Eu, 0x3FFu, 0x370u, 0x0DDu, 0x052u, 0x1C3u, 0x14Cu, 0x216u, 0x299u, 0x308u, 0x387u, + 0x02Au, 0x0A5u, 0x134u, 0x1BBu, 0x30Fu, 0x380u, 0x211u, 0x29Eu, 0x133u, 0x1BCu, 0x02Du, 0x0A2u, 0x3F8u, 0x377u, + 0x2E6u, 0x269u, 0x1C4u, 0x14Bu, 0x0DAu, 0x055u, 0x13Du, 0x1B2u, 0x023u, 0x0ACu, 0x301u, 0x38Eu, 0x21Fu, 0x290u, + 0x1CAu, 0x145u, 0x0D4u, 0x05Bu, 0x3F6u, 0x379u, 0x2E8u, 0x267u, 0x0D3u, 0x05Cu, 0x1CDu, 0x142u, 0x2EFu, 0x260u, + 0x3F1u, 0x37Eu, 0x024u, 0x0ABu, 0x13Au, 0x1B5u, 0x218u, 0x297u, 0x306u, 0x389u, 0x1D6u, 0x159u, 0x0C8u, 0x047u, + 0x3EAu, 0x365u, 0x2F4u, 0x27Bu, 0x121u, 0x1AEu, 0x03Fu, 0x0B0u, 0x31Du, 0x392u, 0x203u, 0x28Cu, 0x038u, 0x0B7u, + 0x126u, 0x1A9u, 0x204u, 0x28Bu, 0x31Au, 0x395u, 0x0CFu, 0x040u, 0x1D1u, 0x15Eu, 0x2F3u, 0x27Cu, 0x3EDu, 0x362u, + 0x20Au, 0x285u, 0x314u, 0x39Bu, 0x036u, 0x0B9u, 0x128u, 0x1A7u, 0x2FDu, 0x272u, 0x3E3u, 0x36Cu, 0x0C1u, 0x04Eu, + 0x1DFu, 0x150u, 0x3E4u, 0x36Bu, 0x2FAu, 0x275u, 0x1D8u, 0x157u, 0x0C6u, 0x049u, 0x313u, 0x39Cu, 0x20Du, 0x282u, + 0x12Fu, 0x1A0u, 0x031u, 0x0BEu, + }; + + uint16_t pec = ADI_PEC10_SEED; + + /* Compute CRC for the six bytes of data */ + for (uint8_t byte = 0u; byte < length; byte++) { + uint8_t position = + (uint8_t)(((pec >> (ADI_PEC10_POLYNOMIAL_SIZE - ADI_PEC_BYTE_SIZE)) ^ data[byte]) & ADI_PEC_ONE_BYTE_MASK); + pec = ((uint16_t)(pec << ADI_PEC_BYTE_SIZE)) ^ (uint16_t)(adi_crc10Table[position]); + } + + /* Add the 6 bits of command counter to CRC computation */ + + /* In sent data, command counter bits are set to 0 */ + uint8_t commandCounter = 0u; + if (receive == true) { + /* In receive data, compute CRC with the 6 received command counter bits */ + commandCounter = data[length] & ADI_PEC10_COMMAND_COUNTER_MASK; + } + pec ^= (uint16_t)(commandCounter << (ADI_PEC10_POLYNOMIAL_SIZE - ADI_PEC_BYTE_SIZE)); + for (uint8_t i = 0u; i < ADI_PEC10_COMMAND_COUNTER_SIZE_IN_BITS; i++) { + if ((pec & ADI_PEC10_MSB_MASK) != 0u) /* test for MSB = bit 10 */ + { + pec = (uint16_t)((pec << 1u) ^ ADI_PEC10_POLYNOMIAL); + } else { + pec <<= 1u; + } + } + return (pec & ADI_PEC10_MASK); +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ diff --git a/src/app/driver/afe/adi/common/ades183x/pec/adi_ades183x_pec.h b/src/app/driver/afe/adi/common/ades183x/pec/adi_ades183x_pec.h new file mode 100644 index 00000000..23b5c07d --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/pec/adi_ades183x_pec.h @@ -0,0 +1,111 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades183x_pec.h + * @author foxBMS Team + * @date 2019-12-12 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix ADI + * + * @brief Headers for the PEC computations. + * @details The CRC polynomials used are defined in the data sheets of the ICs. + * + */ + +#ifndef FOXBMS__ADI_ADES183X_PEC_H_ +#define FOXBMS__ADI_ADES183X_PEC_H_ + +/*========== Includes =======================================================*/ + +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/** Defines for the PEC computation */ +/**@{*/ +#define ADI_PEC_BYTE_SIZE (8u) +#define ADI_PEC_ONE_BYTE_MASK (0xFFu) +#define ADI_PEC_PRECOMPUTED_TABLE_SIZE (256u) + +#define ADI_PEC15_POLYNOMIAL_SIZE (15u) +#define ADI_PEC15_SEED (0x10u) +#define ADI_PEC15_MASK (0x7FFFu) + +#define ADI_PEC10_POLYNOMIAL (0x48Fu) +#define ADI_PEC10_POLYNOMIAL_SIZE (10u) +#define ADI_PEC10_SEED (0x10u) +#define ADI_PEC10_MASK (0x3FFu) +#define ADI_PEC10_MSB_MASK (0x200u) +#define ADI_PEC10_COMMAND_COUNTER_SIZE_IN_BITS (6u) +#define ADI_PEC10_COMMAND_COUNTER_MASK (0xFCu) +/**@}*/ + +/*========== Extern Constant and Variable Declarations ======================*/ + +/*========== Extern Function Prototypes =====================================*/ + +/** + * @brief calculates the PEC15 + * @param length Number of bytes that will be used to calculate a PEC + * @param data Array of data that will be used to calculate a PEC + * @return PEC15, shifted one bit to the left + */ +extern uint16_t ADI_Pec15(uint8_t length, uint8_t *data); + +/** + * @brief calculates the PEC10 + *K + * @param length Number of bytes that will be used to calculate a PEC + * @param data Array of data that will be used to calculate a PEC + * @param receive true if data was received, false if data is to be sent + * @return PEC10 + */ +extern uint16_t ADI_Pec10(uint8_t length, uint8_t *data, bool receive); + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +#endif + +#endif /* FOXBMS__ADI_ADES183X_PEC_H_ */ diff --git a/src/app/driver/afe/adi/common/ades183x/wscript b/src/app/driver/afe/adi/common/ades183x/wscript new file mode 100644 index 00000000..ed95ef6e --- /dev/null +++ b/src/app/driver/afe/adi/common/ades183x/wscript @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Builds the AFE measurement library for the ADI ADES183x device""" + +import os + + +def build(bld): + """builds the AFE driver library for ADI ADES183x""" + source = [ + "adi_ades183x.c", + "adi_ades183x_buffers.c", + "adi_ades183x_commands_voltages.c", + "adi_ades183x_commands.c", + "adi_ades183x_helpers.c", + "adi_ades183x_initialization.c", + "adi_ades183x_temperatures.c", + "adi_ades183x_voltages.c", + os.path.join("api", "adi_ades183x_afe.c"), + os.path.join("api", "adi_ades183x_afe_dma.c"), + os.path.join("config", "adi_ades183x_cfg.c"), + os.path.join("pec", "adi_ades183x_pec.c"), + ] + # only build the diagnostics objects when these are available + diagnostics = "adi_ades183x_diagnostic.c" + if bld.path.find_node(diagnostics): + source.append(diagnostics) + bld.recurse("diag") + else: + source.append("adi_ades183x_diagnostic_w.c") + + includes = [ + os.path.join("..", "..", "..", "..", "config"), + os.path.join("..", "..", "..", "..", "mcu"), + os.path.join("..", "..", "..", "..", "pex"), + os.path.join("..", "..", "..", "..", "rtc"), + os.path.join("..", "..", "..", "..", "spi"), + os.path.join("..", "..", "..", "..", "ts"), + os.path.join("..", "..", "..", "..", "ts", "api"), + os.path.join("..", "..", "..", "..", "..", "application", "config"), + os.path.join("..", "..", "..", "..", "..", "engine", "config"), + os.path.join("..", "..", "..", "..", "..", "engine", "database"), + os.path.join("..", "..", "..", "..", "..", "engine", "diag"), + os.path.join("..", "..", "..", "..", "..", "main", "include"), + os.path.join("..", "..", "..", "..", "..", "task", "config"), + os.path.join("..", "..", "..", "..", "..", "task", "ftask"), + os.path.join("..", "..", "..", "..", "..", "task", "os"), + ] + includes.extend(bld.env.INCLUDES_AFE) + includes.extend(bld.env.INCLUDES_RTOS) + cflags = bld.env.CFLAGS_FOXBMS + target = f"{bld.env.APPNAME.lower()}-afe-driver-adi-ades183x-common" + bld.objects( + source=source, + includes=includes, + cflags=cflags, + target=target, + ) diff --git a/src/app/driver/afe/adi/wscript b/src/app/driver/afe/adi/wscript new file mode 100644 index 00000000..0c053f2d --- /dev/null +++ b/src/app/driver/afe/adi/wscript @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Helper Build Script: ./src/app/driver/afe/adi + +Helper script to recursively build the variant of the ADI AFE""" + + +def build(bld): + """selects the driver library to be build""" + bld.recurse(bld.env.afe_ic) diff --git a/src/app/driver/afe/api/afe.h b/src/app/driver/afe/api/afe.h index 4dfd4bbd..334981ea 100644 --- a/src/app/driver/afe/api/afe.h +++ b/src/app/driver/afe/api/afe.h @@ -43,8 +43,8 @@ * @file afe.h * @author foxBMS Team * @date 2020-05-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix AFE * @@ -106,8 +106,7 @@ typedef struct { extern STD_RETURN_TYPE_e AFE_TriggerIc(void); /** initializer, this function is called in order to initialize the AFE */ extern STD_RETURN_TYPE_e AFE_Initialize(void); -/** this function should tell the AFE that it should start measuring */ -extern STD_RETURN_TYPE_e AFE_StartMeasurement(void); + /** this function returns whether the first measurement cycle has finished */ extern bool AFE_IsFirstMeasurementCycleFinished(void); diff --git a/src/app/driver/afe/api/afe_dma.h b/src/app/driver/afe/api/afe_dma.h index 1c7ea86b..f757b186 100644 --- a/src/app/driver/afe/api/afe_dma.h +++ b/src/app/driver/afe/api/afe_dma.h @@ -43,8 +43,8 @@ * @file afe_dma.h * @author foxBMS Team * @date 2020-06-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix AFE * diff --git a/src/app/driver/afe/api/afe_plausibility.c b/src/app/driver/afe/api/afe_plausibility.c index 95c9bb4b..37a2fa47 100644 --- a/src/app/driver/afe/api/afe_plausibility.c +++ b/src/app/driver/afe/api/afe_plausibility.c @@ -43,8 +43,8 @@ * @file afe_plausibility.c * @author foxBMS Team * @date 2019-01-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup MODULES * @prefix AFE * @@ -86,7 +86,7 @@ extern STD_RETURN_TYPE_e AFE_PlausibilityCheckVoltageMeasurementRange( return retval; } -extern STD_RETURN_TYPE_e AFE_PlausibilityCheckTempMinMax(const int16_t celltemperature_ddegC) { +extern STD_RETURN_TYPE_e AFE_PlausibilityCheckTempMinMax(const int16_t cellTemperature_ddegC) { STD_RETURN_TYPE_e retval = STD_OK; const int16_t plausibleMaximumTemperature_ddegC = TSI_GetMaximumPlausibleTemperature(); @@ -95,8 +95,8 @@ extern STD_RETURN_TYPE_e AFE_PlausibilityCheckTempMinMax(const int16_t celltempe /* General plausibility check: Maximum temperature may not be smaller than minimum */ FAS_ASSERT(plausibleMaximumTemperature_ddegC >= plausibleMinimumTemperature_ddegC); - if ((celltemperature_ddegC > plausibleMaximumTemperature_ddegC) || - (celltemperature_ddegC < plausibleMinimumTemperature_ddegC)) { + if ((cellTemperature_ddegC > plausibleMaximumTemperature_ddegC) || + (cellTemperature_ddegC < plausibleMinimumTemperature_ddegC)) { /* Cell voltage measurement value out of measurement range */ retval = STD_NOT_OK; } diff --git a/src/app/driver/afe/api/afe_plausibility.h b/src/app/driver/afe/api/afe_plausibility.h index a4d68d32..846d83e2 100644 --- a/src/app/driver/afe/api/afe_plausibility.h +++ b/src/app/driver/afe/api/afe_plausibility.h @@ -43,8 +43,8 @@ * @file afe_plausibility.h * @author foxBMS Team * @date 2019-01-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup MODULES * @prefix AFE * @@ -101,9 +101,9 @@ extern STD_RETURN_TYPE_e AFE_PlausibilityCheckVoltageMeasurementRange( /** * @brief Cell temperature plausibility check * - * @param celltemperature_ddegC cell temperature that is checked in deci °C + * @param cellTemperature_ddegC cell temperature that is checked in deci °C */ -extern STD_RETURN_TYPE_e AFE_PlausibilityCheckTempMinMax(const int16_t celltemperature_ddegC); +extern STD_RETURN_TYPE_e AFE_PlausibilityCheckTempMinMax(const int16_t cellTemperature_ddegC); /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST diff --git a/src/app/driver/afe/debug/default/api/debug_default_afe.c b/src/app/driver/afe/debug/default/api/debug_default_afe.c index 05dbd48c..37bec927 100644 --- a/src/app/driver/afe/debug/default/api/debug_default_afe.c +++ b/src/app/driver/afe/debug/default/api/debug_default_afe.c @@ -43,8 +43,8 @@ * @file debug_default_afe.c * @author foxBMS Team * @date 2020-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix FAKE * @@ -53,8 +53,7 @@ /*========== Includes =======================================================*/ -#include "debug_default_afe.h" - +#include "afe.h" #include "debug_default.h" #include diff --git a/src/app/driver/afe/debug/default/api/debug_default_afe_dma.c b/src/app/driver/afe/debug/default/api/debug_default_afe_dma.c index 5e0c9d80..3fb93b48 100644 --- a/src/app/driver/afe/debug/default/api/debug_default_afe_dma.c +++ b/src/app/driver/afe/debug/default/api/debug_default_afe_dma.c @@ -43,8 +43,8 @@ * @file debug_default_afe_dma.c * @author foxBMS Team * @date 2020-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix FAKE * @@ -53,7 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "debug_default_afe_dma.h" +#include "afe_dma.h" #include diff --git a/src/app/driver/afe/debug/default/debug_default.c b/src/app/driver/afe/debug/default/debug_default.c index 16435dea..8fcab6bf 100644 --- a/src/app/driver/afe/debug/default/debug_default.c +++ b/src/app/driver/afe/debug/default/debug_default.c @@ -43,8 +43,8 @@ * @file debug_default.c * @author foxBMS Team * @date 2020-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix FAKE * @@ -245,8 +245,8 @@ static void FAKE_SetState( if ((pFakeState->currentState == nextState) && (pFakeState->currentSubstate == nextSubstate)) { /* Next state and next substate equal to current state and substate: nothing to do */ - pFakeState->nextState = FAKE_FSM_STATE_DUMMY; /* no state transistion required -> reset */ - pFakeState->nextSubstate = FAKE_FSM_SUBSTATE_DUMMY; /* no substate transistion required -> reset */ + pFakeState->nextState = FAKE_FSM_STATE_DUMMY; /* no state transition required -> reset */ + pFakeState->nextSubstate = FAKE_FSM_SUBSTATE_DUMMY; /* no substate transition required -> reset */ earlyExit = true; } @@ -257,8 +257,8 @@ static void FAKE_SetState( pFakeState->currentState = nextState; pFakeState->previousSubstate = pFakeState->currentSubstate; pFakeState->currentSubstate = FAKE_FSM_SUBSTATE_ENTRY; /* Use entry state after a top level state change */ - pFakeState->nextState = FAKE_FSM_STATE_DUMMY; /* no state transistion required -> reset */ - pFakeState->nextSubstate = FAKE_FSM_SUBSTATE_DUMMY; /* no substate transistion required -> reset */ + pFakeState->nextState = FAKE_FSM_STATE_DUMMY; /* no state transition required -> reset */ + pFakeState->nextSubstate = FAKE_FSM_SUBSTATE_DUMMY; /* no substate transition required -> reset */ } else if (pFakeState->currentSubstate != nextSubstate) { /* Only the next substate is different, switch to it */ FAKE_SetSubstate(pFakeState, nextSubstate, idleTime); @@ -280,36 +280,38 @@ static void FAKE_SetFirstMeasurementCycleFinished(FAKE_STATE_s *pFakeState) { FAS_ASSERT(pFakeState != NULL_PTR); OS_EnterTaskCritical(); - uint16_t i = 0; - for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { pFakeState->data.cellVoltage->stringVoltage_mV[s] = FAKE_CELL_VOLTAGE_mV * BS_NR_OF_CELL_BLOCKS_PER_STRING; - for (i = 0; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - pFakeState->data.cellVoltage->cellVoltage_mV[s][i] = FAKE_CELL_VOLTAGE_mV; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + pFakeState->data.cellVoltage->cellVoltage_mV[s][m][cb] = FAKE_CELL_VOLTAGE_mV; + } } pFakeState->data.cellVoltage->state = 0; pFakeState->data.cellTemperature->state = 0; - for (i = 0; i < BS_NR_OF_TEMP_SENSORS_PER_STRING; i++) { - pFakeState->data.cellTemperature->cellTemperature_ddegC[s][i] = FAKE_CELL_TEMPERATURE_ddegC; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { + pFakeState->data.cellTemperature->cellTemperature_ddegC[s][m][ts] = FAKE_CELL_TEMPERATURE_ddegC; + } } pFakeState->data.balancingFeedback->state = 0; - for (i = 0; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - pFakeState->data.balancingControl->balancingState[s][i] = 0; + for (uint16_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_STRING; cb++) { + pFakeState->data.balancingControl->balancingState[s][cb] = 0u; } pFakeState->data.balancingControl->nrBalancedCells[s] = 0u; - for (i = 0; i < BS_NR_OF_MODULES_PER_STRING; i++) { - pFakeState->data.balancingFeedback->value[s][i] = 0; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + pFakeState->data.balancingFeedback->value[s][m] = 0u; } pFakeState->data.slaveControl->state = 0; - for (i = 0; i < BS_NR_OF_MODULES_PER_STRING; i++) { - pFakeState->data.slaveControl->ioValueIn[i] = 0; - pFakeState->data.slaveControl->ioValueOut[i] = 0; - pFakeState->data.slaveControl->externalTemperatureSensor[i] = 0; - pFakeState->data.slaveControl->eepromValueRead[i] = 0; - pFakeState->data.slaveControl->eepromValueWrite[i] = 0; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + pFakeState->data.slaveControl->ioValueIn[m] = 0; + pFakeState->data.slaveControl->ioValueOut[m] = 0; + pFakeState->data.slaveControl->externalTemperatureSensor[m] = 0; + pFakeState->data.slaveControl->eepromValueRead[m] = 0; + pFakeState->data.slaveControl->eepromValueWrite[m] = 0; } pFakeState->data.slaveControl->eepromReadAddressLastUsed = 0xFFFFFFFF; pFakeState->data.slaveControl->eepromReadAddressToUse = 0xFFFFFFFF; @@ -317,12 +319,12 @@ static void FAKE_SetFirstMeasurementCycleFinished(FAKE_STATE_s *pFakeState) { pFakeState->data.slaveControl->eepromWriteAddressToUse = 0xFFFFFFFF; pFakeState->data.allGpioVoltages->state = 0; - for (i = 0; i < (BS_NR_OF_MODULES_PER_STRING * BS_NR_OF_GPIOS_PER_MODULE); i++) { - pFakeState->data.allGpioVoltages->gpioVoltages_mV[s][i] = 0; + for (uint16_t gpio = 0u; gpio < (BS_NR_OF_MODULES_PER_STRING * BS_NR_OF_GPIOS_PER_MODULE); gpio++) { + pFakeState->data.allGpioVoltages->gpioVoltages_mV[s][gpio] = 0; } - for (i = 0; i < (BS_NR_OF_MODULES_PER_STRING * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1)); i++) { - pFakeState->data.openWire->openWire[s][i] = 0; + for (uint16_t ow = 0u; ow < (BS_NR_OF_MODULES_PER_STRING * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)); ow++) { + pFakeState->data.openWire->openWire[s][ow] = 0u; } pFakeState->data.openWire->state = 0; } @@ -339,34 +341,37 @@ static void FAKE_SetFirstMeasurementCycleFinished(FAKE_STATE_s *pFakeState) { static STD_RETURN_TYPE_e FAKE_SaveFakeVoltageMeasurementData(FAKE_STATE_s *pFakeState) { FAS_ASSERT(pFakeState != NULL_PTR); - STD_RETURN_TYPE_e successfullSave = STD_OK; + STD_RETURN_TYPE_e successfulSave = STD_OK; for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { pFakeState->data.cellVoltage->nrValidCellVoltages[s] = 0u; - for (uint16_t i = 0u; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - pFakeState->data.cellVoltage->cellVoltage_mV[s][i] = FAKE_CELL_VOLTAGE_mV; - pFakeState->data.cellVoltage->nrValidCellVoltages[s] += 1u; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint16_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + pFakeState->data.cellVoltage->cellVoltage_mV[s][m][cb] = FAKE_CELL_VOLTAGE_mV; + pFakeState->data.cellVoltage->nrValidCellVoltages[s] += 1u; + } } } - DATA_WRITE_DATA(pFakeState->data.cellVoltage); - return successfullSave; + return successfulSave; } static STD_RETURN_TYPE_e FAKE_SaveFakeTemperatureMeasurementData(FAKE_STATE_s *pFakeState) { FAS_ASSERT(pFakeState != NULL_PTR); - STD_RETURN_TYPE_e successfullSave = STD_OK; + STD_RETURN_TYPE_e successfulSave = STD_OK; for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { - for (uint16_t i = 0u; i < BS_NR_OF_TEMP_SENSORS_PER_STRING; i++) { - pFakeState->data.cellTemperature->cellTemperature_ddegC[s][i] = FAKE_CELL_TEMPERATURE_ddegC; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { + pFakeState->data.cellTemperature->cellTemperature_ddegC[s][m][ts] = FAKE_CELL_TEMPERATURE_ddegC; + } } } DATA_WRITE_DATA(pFakeState->data.cellTemperature); - return successfullSave; + return successfulSave; } static FAKE_FSM_STATES_e FAKE_ProcessInitializationState(FAKE_STATE_s *pFakeState) { diff --git a/src/app/driver/afe/debug/default/debug_default.h b/src/app/driver/afe/debug/default/debug_default.h index a5285171..b53f5300 100644 --- a/src/app/driver/afe/debug/default/debug_default.h +++ b/src/app/driver/afe/debug/default/debug_default.h @@ -43,8 +43,8 @@ * @file debug_default.h * @author foxBMS Team * @date 2020-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix FAKE * @@ -72,7 +72,7 @@ typedef enum { FAKE_FSM_STATE_HAS_NEVER_RUN, /*!< never run state - always the second state */ FAKE_FSM_STATE_UNINITIALIZED, /*!< uninitialized state */ FAKE_FSM_STATE_INITIALIZATION, /*!< initializing the state machine */ - FAKE_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ + FAKE_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ FAKE_FSM_STATE_ERROR, /*!< state for error processing */ } FAKE_FSM_STATES_e; diff --git a/src/app/driver/afe/debug/default/debug_default.json b/src/app/driver/afe/debug/default/debug_default.json index d061b962..d563cd5b 100644 --- a/src/app/driver/afe/debug/default/debug_default.json +++ b/src/app/driver/afe/debug/default/debug_default.json @@ -2,7 +2,6 @@ "include": [ "../../api", ".", - "api", - "config" + "api" ] } diff --git a/src/app/driver/afe/debug/default/wscript b/src/app/driver/afe/debug/default/wscript index f46273fe..05f29a0a 100644 --- a/src/app/driver/afe/debug/default/wscript +++ b/src/app/driver/afe/debug/default/wscript @@ -50,14 +50,9 @@ def build(bld): source = [ os.path.join("api", "debug_default_afe.c"), os.path.join("api", "debug_default_afe_dma.c"), - os.path.join("config", "debug_default_cfg.c"), os.path.join("debug_default.c"), ] includes = [ - os.path.join("..", "..", "api"), - os.path.join("."), - os.path.join("api"), - os.path.join("config"), os.path.join("..", "..", "..", "config"), os.path.join("..", "..", "..", "io"), os.path.join("..", "..", "..", "spi"), @@ -71,6 +66,7 @@ def build(bld): os.path.join("..", "..", "..", "..", "engine", "diag"), os.path.join("..", "..", "..", "..", "task", "os"), ] + includes.extend(bld.env.INCLUDES_AFE) includes.extend(bld.env.INCLUDES_RTOS) cflags = bld.env.CFLAGS_FOXBMS target = f"{bld.env.APPNAME.lower()}-afe-driver" diff --git a/src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.c b/src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.c index 446a60cd..55d007ba 100644 --- a/src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.c +++ b/src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.c @@ -43,8 +43,8 @@ * @file ltc_6806_cfg.c * @author foxBMS Team * @date 2015-02-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix LTC * diff --git a/src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.h b/src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.h index 4f215c1c..065fc0bf 100644 --- a/src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.h +++ b/src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.h @@ -43,8 +43,8 @@ * @file ltc_6806_cfg.h * @author foxBMS Team * @date 2015-02-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix LTC * @@ -178,7 +178,7 @@ /** Time to measure all fuel cells in normal mode 10280 µs */ #define LTC_FUELCELL_NORMAL_ALL_CELLS_MS (11) -/** LTC statemachine short time definition in ms */ +/** LTC state machine short time definition in ms */ #define LTC_STATEMACH_SHORTTIME (1) /** @@ -236,9 +236,9 @@ */ #define LTC_STATEMACH_MEAS_SINGLE_FILTERED_TCYCLE (35) -/** LTC statemachine sequence error timing in ms */ +/** LTC state machine sequence error timing in ms */ #define LTC_STATEMACH_SEQERRTTIME (5) -/** LTC statemachine CRC-transmission error timing in ms */ +/** LTC state machine CRC-transmission error timing in ms */ #define LTC_STATEMACH_PECERRTIME (1) /** diff --git a/src/app/driver/afe/ltc/6806/ltc_6806.c b/src/app/driver/afe/ltc/6806/ltc_6806.c index 45dc07da..8acfd335 100644 --- a/src/app/driver/afe/ltc/6806/ltc_6806.c +++ b/src/app/driver/afe/ltc/6806/ltc_6806.c @@ -43,8 +43,8 @@ * @file ltc_6806.c * @author foxBMS Team * @date 2019-09-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix LTC * @@ -299,33 +299,36 @@ static LTC_RETURN_TYPE_e LTC_CheckStateRequest(LTC_STATE_s *ltc_state, LTC_REQUE * */ static void LTC_InitializeDatabase(LTC_STATE_s *ltc_state) { - uint16_t i = 0; - for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { - ltc_state->ltcData.cellVoltage->state = 0; - for (i = 0; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - ltc_state->ltcData.cellVoltage->cellVoltage_mV[s][i] = 0; - ltc_state->ltcData.openWireDetection->openWirePup[s][i] = 0; - ltc_state->ltcData.openWireDetection->openWirePdown[s][i] = 0; - ltc_state->ltcData.openWireDetection->openWireDelta[s][i] = 0; + ltc_state->ltcData.cellVoltage->state = 0u; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + ltc_state->ltcData.cellVoltage->cellVoltage_mV[s][m][cb] = 0; + } + } + for (uint16_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_STRING; cb++) { + ltc_state->ltcData.openWireDetection->openWirePup[s][cb] = 0; + ltc_state->ltcData.openWireDetection->openWirePdown[s][cb] = 0; + ltc_state->ltcData.openWireDetection->openWireDelta[s][cb] = 0; } ltc_state->ltcData.cellTemperature->state = 0; - for (i = 0; i < BS_NR_OF_TEMP_SENSORS_PER_STRING; i++) { - ltc_state->ltcData.cellTemperature->cellTemperature_ddegC[s][i] = 0; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { + ltc_state->ltcData.cellTemperature->cellTemperature_ddegC[s][m][ts] = 0; + } } - ltc_state->ltcData.allGpioVoltages->state = 0; - for (i = 0; i < (BS_NR_OF_MODULES_PER_STRING * BS_NR_OF_GPIOS_PER_MODULE); i++) { - ltc_state->ltcData.allGpioVoltages->gpioVoltages_mV[s][i] = 0; + ltc_state->ltcData.allGpioVoltages->state = 0u; + for (uint16_t gpio = 0u; gpio < (BS_NR_OF_MODULES_PER_STRING * BS_NR_OF_GPIOS_PER_MODULE); gpio++) { + ltc_state->ltcData.allGpioVoltages->gpioVoltages_mV[s][gpio] = 0; } - for (i = 0; i < (BS_NR_OF_MODULES_PER_STRING * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1)); i++) { - ltc_state->ltcData.openWire->openWire[s][i] = 0; + for (uint16_t ow = 0u; ow < (BS_NR_OF_MODULES_PER_STRING * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1)); ow++) { + ltc_state->ltcData.openWire->openWire[s][ow] = 0u; } - ltc_state->ltcData.openWire->state = 0; + ltc_state->ltcData.openWire->state = 0u; } - DATA_WRITE_DATA(ltc_state->ltcData.cellVoltage, ltc_state->ltcData.cellTemperature, ltc_state->ltcData.openWire); } @@ -356,9 +359,9 @@ static void LTC_StateTransition(LTC_STATE_s *ltc_state, LTC_STATEMACH_e state, u /** * @brief condition-based state transition depending on retVal * - * If retVal is #STD_OK, after timer_ms_ok is elapsed the LTC statemachine will + * If retVal is #STD_OK, after timer_ms_ok is elapsed the LTC state machine will * transition into state_ok and substate_ok, otherwise after timer_ms_nok the - * statemachine will transition to state_nok and substate_nok. Depending on + * state machine will transition to state_nok and substate_nok. Depending on * value of retVal the corresponding diagnosis entry will be called. * * @param ltc_state state of the ltc state machine @@ -410,7 +413,7 @@ extern void LTC_SaveVoltages(LTC_STATE_s *ltc_state, uint8_t stringNumber) { int32_t stringVoltage_mV = 0; uint16_t numberValidMeasurements = 0; for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { /* ------- 1. Check open-wires ----------------- * Is cell N input not open wire && * Is cell N+1 input not open wire && @@ -418,30 +421,28 @@ extern void LTC_SaveVoltages(LTC_STATE_s *ltc_state, uint8_t stringNumber) { * If so, everything okay, else set cell voltage measurement to invalid. */ if ((ltc_state->ltcData.openWire - ->openWire[stringNumber][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)) + c] == 0u) && + ->openWire[stringNumber][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)) + cb] == 0u) && (ltc_state->ltcData.openWire - ->openWire[stringNumber][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)) + c + 1u] == 0u) && - ((ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] & (0x01u << c)) == 0u)) { + ->openWire[stringNumber][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)) + cb + 1u] == 0u) && + ((ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] & (0x01u << cb)) == 0u)) { /* Cell voltage is valid -> perform minimum/maximum plausibility check */ /* ------- 2. Perform minimum/maximum measurement range check ---------- */ if (STD_OK == AFE_PlausibilityCheckVoltageMeasurementRange( - ltc_state->ltcData.cellVoltage - ->cellVoltage_mV[stringNumber][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c], + ltc_state->ltcData.cellVoltage->cellVoltage_mV[stringNumber][m][cb], ltc_plausibleCellVoltages6806)) { /* Cell voltage is valid -> calculate string voltage */ /* -------- 3. Calculate string values ------------- */ - stringVoltage_mV += ltc_state->ltcData.cellVoltage - ->cellVoltage_mV[stringNumber][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; + stringVoltage_mV += ltc_state->ltcData.cellVoltage->cellVoltage_mV[stringNumber][m][cb]; numberValidMeasurements++; } else { /* Invalidate cell voltage measurement */ - ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01u << c); + ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01uLL << cb); cellVoltageMeasurementValid = STD_NOT_OK; } } else { /* Set cell voltage measurement value invalid, if not already invalid because of PEC Error */ - ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01u << c); + ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01uLL << cb); cellVoltageMeasurementValid = STD_NOT_OK; } } @@ -460,23 +461,21 @@ extern void LTC_SaveTemperatures(LTC_STATE_s *ltc_state, uint8_t stringNumber) { STD_RETURN_TYPE_e cellTemperatureMeasurementValid = STD_OK; uint16_t numberValidMeasurements = 0; for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { /* ------- 1. Check valid flag ----------------- * Is cell temperature valid because of previous PEC error * If so, everything okay, else set cell temperature measurement to invalid. */ - if ((ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] & (0x01u << c)) == 0u) { + if ((ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] & (0x01u << ts)) == 0u) { /* Cell temperature is valid -> perform minimum/maximum plausibility check */ /* ------- 2. Perform minimum/maximum measurement range check ---------- */ - if (STD_OK == - AFE_PlausibilityCheckTempMinMax( - ltc_state->ltcData.cellTemperature - ->cellTemperature_ddegC[stringNumber][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c])) { + if (STD_OK == AFE_PlausibilityCheckTempMinMax( + ltc_state->ltcData.cellTemperature->cellTemperature_ddegC[stringNumber][m][ts])) { numberValidMeasurements++; } else { /* Invalidate cell temperature measurement */ - ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] |= (0x01u << c); + ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] |= (0x01u << ts); cellTemperatureMeasurementValid = STD_NOT_OK; } } else { @@ -1126,9 +1125,12 @@ void LTC_Trigger(LTC_STATE_s *ltc_state) { ltc_state->reusageMeasurementMode = LTC_NOT_REUSED; /* Copy data from voltage struct into open-wire struct */ - for (uint16_t i = 0u; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - ltc_state->ltcData.openWireDetection->openWirePup[ltc_state->requestedString][i] = - ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][i]; + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + ltc_state->ltcData.openWireDetection + ->openWirePup[ltc_state->requestedString][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + cb] = + ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][m][cb]; + } } /* Set number of ADOW retries - send ADOW command with pull-down two times */ @@ -1178,11 +1180,14 @@ void LTC_Trigger(LTC_STATE_s *ltc_state) { ltc_state->reusageMeasurementMode = LTC_NOT_REUSED; /* Copy data from voltage struct into open-wire struct */ - for (uint16_t i = 0u; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - ltc_state->ltcData.openWireDetection->openWirePdown[ltc_state->requestedString][i] = - ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][i]; + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint16_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + ltc_state->ltcData.openWireDetection + ->openWirePdown[ltc_state->requestedString] + [(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + cb] = + ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][m][cb]; + } } - LTC_StateTransition( ltc_state, LTC_STATEMACH_OPENWIRE_CHECK, LTC_PERFORM_OPENWIRE_CHECK, LTC_STATEMACH_SHORTTIME); } else if (ltc_state->substate == LTC_PERFORM_OPENWIRE_CHECK) { @@ -1292,7 +1297,7 @@ static void LTC_SaveRXtoVoltagebuffer_Fuelcell( uint8_t stringNumber) { uint16_t cellOffset = 0; uint16_t val_ui = 0; - int16_t voltage = 0; + int16_t voltage_mV = 0; uint64_t bitmask = 0; uint16_t buffer_LSB = 0; uint16_t buffer_MSB = 0; @@ -1340,15 +1345,14 @@ static void LTC_SaveRXtoVoltagebuffer_Fuelcell( /* Check signed bit if measured value is negative or not */ if ((val_ui & (1u << (12u - 1u))) == 0u) { - voltage = (int16_t)(((val_ui & 0x7FFu)) * LTC_FUEL_CELL_LSB_RESOLUTION_mV); /* Unit mV */ + voltage_mV = (int16_t)(((val_ui & 0x7FFu)) * LTC_FUEL_CELL_LSB_RESOLUTION_mV); /* Unit mV */ } else { - voltage = (int16_t)(((((~val_ui) + 1) & 0x7FF)) * (-LTC_FUEL_CELL_LSB_RESOLUTION_mV)); /* Unit mV */ + voltage_mV = (int16_t)(((((~val_ui) + 1) & 0x7FF)) * (-LTC_FUEL_CELL_LSB_RESOLUTION_mV)); /* Unit mV */ } if (ltc_state->ltcData.errorTable->PEC_valid[stringNumber][m] == true) { - ltc_state->ltcData.cellVoltage->cellVoltage_mV[stringNumber] - [(ltc_state->ltcData.usedCellIndex[stringNumber]) + - (m * BS_NR_OF_CELL_BLOCKS_PER_MODULE)] = voltage; + ltc_state->ltcData.cellVoltage + ->cellVoltage_mV[stringNumber][m][ltc_state->ltcData.usedCellIndex[stringNumber]] = voltage_mV; bitmask = ~bitmask; /* negate bitmask to only validate flags of this voltage register */ ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][(m / LTC_NUMBER_OF_LTC_PER_MODULE)] &= bitmask; @@ -1783,18 +1787,18 @@ extern void TEST_LTC_SetFirstMeasurementCycleFinished(LTC_STATE_s *ltc_state) { } \ } -TEST_LTC_DEFINE_GET(ltc_cmdWRCFG); -TEST_LTC_DEFINE_GET(ltc_cmdRDCFG); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVA_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVB_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVC_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVD_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVE_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVF_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVG_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVH_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVI_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_cmdADCV_normal_Fuelcell); -TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PUP_100ms_fuelcell); -TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PDOWN_100ms_fuelcell); +TEST_LTC_DEFINE_GET(ltc_cmdWRCFG) +TEST_LTC_DEFINE_GET(ltc_cmdRDCFG) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVA_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVB_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVC_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVD_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVE_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVF_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVG_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVH_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVI_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_cmdADCV_normal_Fuelcell) +TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PUP_100ms_fuelcell) +TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PDOWN_100ms_fuelcell) #endif diff --git a/src/app/driver/afe/ltc/6806/ltc_6806.json b/src/app/driver/afe/ltc/6806/ltc_6806.json index ab69d8bb..2183cc4a 100644 --- a/src/app/driver/afe/ltc/6806/ltc_6806.json +++ b/src/app/driver/afe/ltc/6806/ltc_6806.json @@ -2,6 +2,8 @@ "include": [ ".", "config", + "../common", + "../common/config", "../../api" ] } diff --git a/src/app/driver/afe/ltc/6806/wscript b/src/app/driver/afe/ltc/6806/wscript index 8779f102..db99a008 100644 --- a/src/app/driver/afe/ltc/6806/wscript +++ b/src/app/driver/afe/ltc/6806/wscript @@ -49,17 +49,11 @@ def build(bld): os.path.join("config", "ltc_6806_cfg.c"), os.path.join("ltc_6806.c"), os.path.join("..", "api", "ltc_afe.c"), - os.path.join("..", "common", "config", "ltc_afe_dma_cfg.c"), os.path.join("..", "common", "ltc_afe_dma.c"), os.path.join("..", "common", "ltc_pec.c"), os.path.join("..", "..", "api", "afe_plausibility.c"), ] includes = [ - ".", - os.path.join("..", "..", "api"), - os.path.join("config"), - os.path.join("..", "common"), - os.path.join("..", "common", "config"), os.path.join("..", "..", "..", "config"), os.path.join("..", "..", "..", "dma"), os.path.join("..", "..", "..", "foxmath"), @@ -76,6 +70,7 @@ def build(bld): os.path.join("..", "..", "..", "..", "main", "include"), os.path.join("..", "..", "..", "..", "task", "os"), ] + includes.extend(bld.env.INCLUDES_AFE) includes.extend(bld.env.INCLUDES_RTOS) cflags = bld.env.CFLAGS_FOXBMS target = f"{bld.env.APPNAME.lower()}-afe-driver" diff --git a/src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.c b/src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.c index aea1dc07..1567aad3 100644 --- a/src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.c +++ b/src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.c @@ -43,8 +43,8 @@ * @file ltc_6813-1_cfg.c * @author foxBMS Team * @date 2015-02-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix LTC * diff --git a/src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.h b/src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.h index f5ee235b..31fc257a 100644 --- a/src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.h +++ b/src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.h @@ -43,8 +43,8 @@ * @file ltc_6813-1_cfg.h * @author foxBMS Team * @date 2015-02-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix LTC * @@ -177,7 +177,7 @@ /** LTC SPI wakeup time */ #define LTC_SPI_WAKEUP_WAIT_TIME_US (30u) -/** LTC statemachine short time definition in ms */ +/** LTC state machine short time definition in ms */ #define LTC_STATEMACH_SHORTTIME (1) /** @@ -271,9 +271,9 @@ */ #define LTC_STATEMACH_MEAS_SINGLE_GPIO_FILTERED_TCYCLE (68) -/** LTC statemachine sequence error timing in ms */ +/** LTC state machine sequence error timing in ms */ #define LTC_STATEMACH_SEQERRTTIME (5) -/** LTC statemachine CRC-transmission error timing in ms */ +/** LTC state machine CRC-transmission error timing in ms */ #define LTC_STATEMACH_PECERRTIME (1) /** diff --git a/src/app/driver/afe/ltc/6813-1/ltc_6813-1.c b/src/app/driver/afe/ltc/6813-1/ltc_6813-1.c index 4fcc9ec9..7150535f 100644 --- a/src/app/driver/afe/ltc/6813-1/ltc_6813-1.c +++ b/src/app/driver/afe/ltc/6813-1/ltc_6813-1.c @@ -43,8 +43,8 @@ * @file ltc_6813-1.c * @author foxBMS Team * @date 2019-09-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix LTC * @@ -450,16 +450,24 @@ static LTC_RETURN_TYPE_e LTC_CheckStateRequest(LTC_STATE_s *ltc_state, LTC_REQUE static void LTC_InitializeDatabase(LTC_STATE_s *ltc_state) { for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { ltc_state->ltcData.cellVoltage->state = 0; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + ltc_state->ltcData.cellVoltage->cellVoltage_mV[s][m][cb] = 0u; + } + } + for (uint16_t i = 0; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - ltc_state->ltcData.cellVoltage->cellVoltage_mV[s][i] = 0; ltc_state->ltcData.openWireDetection->openWirePup[s][i] = 0; ltc_state->ltcData.openWireDetection->openWirePdown[s][i] = 0; ltc_state->ltcData.openWireDetection->openWireDelta[s][i] = 0; } ltc_state->ltcData.cellTemperature->state = 0; - for (uint16_t i = 0; i < BS_NR_OF_TEMP_SENSORS_PER_STRING; i++) { - ltc_state->ltcData.cellTemperature->cellTemperature_ddegC[s][i] = 0; + + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t ts = 0; ts < BS_NR_OF_TEMP_SENSORS_PER_STRING; ts++) { + ltc_state->ltcData.cellTemperature->cellTemperature_ddegC[s][m][ts] = 0; + } } ltc_state->ltcData.balancingFeedback->state = 0; @@ -530,9 +538,9 @@ static void LTC_StateTransition(LTC_STATE_s *ltc_state, LTC_STATEMACH_e state, u /** * @brief condition-based state transition depending on retVal * - * If retVal is #STD_OK, after timer_ms_ok is elapsed the LTC statemachine will + * If retVal is #STD_OK, after timer_ms_ok is elapsed the LTC state machine will * transition into state_ok and substate_ok, otherwise after timer_ms_nok the - * statemachine will transition to state_nok and substate_nok. Depending on + * state machine will transition to state_nok and substate_nok. Depending on * value of retVal the corresponding diagnosis entry will be called. * * @param ltc_state state of the ltc state machine @@ -584,7 +592,7 @@ extern void LTC_SaveVoltages(LTC_STATE_s *ltc_state, uint8_t stringNumber) { int32_t stringVoltage_mV = 0; uint16_t numberValidMeasurements = 0; for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { /* ------- 1. Check open-wires ----------------- * Is cell N input not open wire && * Is cell N+1 input not open wire && @@ -592,30 +600,28 @@ extern void LTC_SaveVoltages(LTC_STATE_s *ltc_state, uint8_t stringNumber) { * If so, everything okay, else set cell voltage measurement to invalid. */ if ((ltc_state->ltcData.openWire - ->openWire[stringNumber][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)) + c] == 0u) && + ->openWire[stringNumber][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)) + cb] == 0u) && (ltc_state->ltcData.openWire - ->openWire[stringNumber][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)) + c + 1u] == 0u) && - ((ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] & (0x01u << c)) == 0u)) { + ->openWire[stringNumber][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1u)) + cb + 1u] == 0u) && + ((ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] & (0x01u << cb)) == 0u)) { /* Cell voltage is valid -> perform minimum/maximum plausibility check */ /* ------- 2. Perform minimum/maximum measurement range check ---------- */ if (STD_OK == AFE_PlausibilityCheckVoltageMeasurementRange( - ltc_state->ltcData.cellVoltage - ->cellVoltage_mV[stringNumber][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c], + ltc_state->ltcData.cellVoltage->cellVoltage_mV[stringNumber][m][cb], ltc_plausibleCellVoltages681x)) { /* Cell voltage is valid -> calculate string voltage */ /* -------- 3. Calculate string values ------------- */ - stringVoltage_mV += ltc_state->ltcData.cellVoltage - ->cellVoltage_mV[stringNumber][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]; + stringVoltage_mV += ltc_state->ltcData.cellVoltage->cellVoltage_mV[stringNumber][m][cb]; numberValidMeasurements++; } else { /* Invalidate cell voltage measurement */ - ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01u << c); + ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01u << cb); cellVoltageMeasurementValid = STD_NOT_OK; } } else { /* Set cell voltage measurement value invalid, if not already invalid because of PEC Error */ - ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01u << c); + ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01u << cb); cellVoltageMeasurementValid = STD_NOT_OK; } } @@ -637,23 +643,21 @@ extern void LTC_SaveTemperatures(LTC_STATE_s *ltc_state, uint8_t stringNumber) { uint16_t numberValidMeasurements = 0; for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { /* ------- 1. Check valid flag ----------------- * Is cell temperature valid because of previous PEC error * If so, everything okay, else set cell temperature measurement to invalid. */ - if ((ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] & (0x01u << c)) == 0u) { + if ((ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] & (0x01u << ts)) == 0u) { /* Cell temperature is valid -> perform minimum/maximum plausibility check */ /* ------- 2. Perform minimum/maximum measurement range check ---------- */ - if (STD_OK == - AFE_PlausibilityCheckTempMinMax( - ltc_state->ltcData.cellTemperature - ->cellTemperature_ddegC[stringNumber][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c])) { + if (STD_OK == AFE_PlausibilityCheckTempMinMax( + ltc_state->ltcData.cellTemperature->cellTemperature_ddegC[stringNumber][m][ts])) { numberValidMeasurements++; } else { /* Invalidate cell temperature measurement */ - ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] |= (0x01u << c); + ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] |= (0x01u << ts); cellTemperatureMeasurementValid = STD_NOT_OK; } } else { @@ -2813,9 +2817,12 @@ void LTC_Trigger(LTC_STATE_s *ltc_state) { ltc_state->reusageMeasurementMode = LTC_NOT_REUSED; /* Copy data from voltage struct into open-wire struct */ - for (uint16_t i = 0u; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - ltc_state->ltcData.openWireDetection->openWirePup[ltc_state->requestedString][i] = - ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][i]; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint16_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + ltc_state->ltcData.openWireDetection + ->openWirePup[ltc_state->requestedString][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + cb] = + ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][m][cb]; + } } /* Set number of ADOW retries - send ADOW command with pull-down two times */ @@ -2865,9 +2872,13 @@ void LTC_Trigger(LTC_STATE_s *ltc_state) { ltc_state->reusageMeasurementMode = LTC_NOT_REUSED; /* Copy data from voltage struct into open-wire struct */ - for (uint16_t i = 0u; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - ltc_state->ltcData.openWireDetection->openWirePdown[ltc_state->requestedString][i] = - ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][i]; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + ltc_state->ltcData.openWireDetection + ->openWirePdown[ltc_state->requestedString] + [(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + cb] = + ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][m][cb]; + } } LTC_StateTransition( ltc_state, LTC_STATEMACH_OPENWIRE_CHECK, LTC_PERFORM_OPENWIRE_CHECK, LTC_STATEMACH_SHORTTIME); @@ -2999,8 +3010,7 @@ static void LTC_SaveMuxMeasurement( ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][i] & (~(1u << sensor_idx)); - ltc_state->ltcData.cellTemperature - ->cellTemperature_ddegC[stringNumber][(i * (BS_NR_OF_TEMP_SENSORS_PER_MODULE)) + sensor_idx] = + ltc_state->ltcData.cellTemperature->cellTemperature_ddegC[stringNumber][i][sensor_idx] = temperature_ddegC; } else { /* Set invalid flag */ @@ -3092,9 +3102,7 @@ static void LTC_SaveRxToVoltageBuffer( /* Check PEC for every LTC in the daisy-chain */ if (ltc_state->ltcData.errorTable->PEC_valid[stringNumber][m] == true) { ltc_state->ltcData.cellVoltage - ->cellVoltage_mV[stringNumber] - [(ltc_state->ltcData.usedCellIndex[stringNumber]) + - (m * BS_NR_OF_CELL_BLOCKS_PER_MODULE)] = voltage; + ->cellVoltage_mV[stringNumber][m][ltc_state->ltcData.usedCellIndex[stringNumber]] = voltage; bitmask = ~bitmask; /* negate bitmask to only validate flags of this voltage register */ ltc_state->ltcData.cellVoltage ->invalidCellVoltage[stringNumber][(m / LTC_NUMBER_OF_LTC_PER_MODULE)] &= bitmask; @@ -4781,43 +4789,43 @@ extern void TEST_LTC_SetFirstMeasurementCycleFinished(LTC_STATE_s *ltc_state) { data[i] = (uint8_t)(VARIABLE)[i]; \ } \ } -TEST_LTC_DEFINE_GET(ltc_cmdWRCFG); -TEST_LTC_DEFINE_GET(ltc_cmdWRCFG2); -TEST_LTC_DEFINE_GET(ltc_cmdRDCFG); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVA); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVB); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVC); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVD); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVE); -TEST_LTC_DEFINE_GET(ltc_cmdRDCVF); -TEST_LTC_DEFINE_GET(ltc_cmdWRCOMM); -TEST_LTC_DEFINE_GET(ltc_cmdSTCOMM); -TEST_LTC_DEFINE_GET(ltc_cmdRDCOMM); -TEST_LTC_DEFINE_GET(ltc_cmdRDAUXA); -TEST_LTC_DEFINE_GET(ltc_cmdRDAUXB); -TEST_LTC_DEFINE_GET(ltc_cmdRDAUXC); -TEST_LTC_DEFINE_GET(ltc_cmdRDAUXD); -TEST_LTC_DEFINE_GET(ltc_cmdADCV_normal_DCP0); -TEST_LTC_DEFINE_GET(ltc_cmdADCV_normal_DCP1); -TEST_LTC_DEFINE_GET(ltc_cmdADCV_filtered_DCP0); -TEST_LTC_DEFINE_GET(ltc_cmdADCV_filtered_DCP1); -TEST_LTC_DEFINE_GET(ltc_cmdADCV_fast_DCP0); -TEST_LTC_DEFINE_GET(ltc_cmdADCV_fast_DCP1); -TEST_LTC_DEFINE_GET(ltc_cmdADCV_fast_DCP0_twocells); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_normal_GPIO1); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_filtered_GPIO1); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_fast_GPIO1); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_normal_GPIO2); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_filtered_GPIO2); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_fast_GPIO2); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_normal_GPIO3); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_filtered_GPIO3); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_fast_GPIO3); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_normal_ALLGPIOS); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_filtered_ALLGPIOS); -TEST_LTC_DEFINE_GET(ltc_cmdADAX_fast_ALLGPIOS); -TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PUP_normal_DCP0); -TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PDOWN_normal_DCP0); -TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PUP_filtered_DCP0); -TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PDOWN_filtered_DCP0); +TEST_LTC_DEFINE_GET(ltc_cmdWRCFG) +TEST_LTC_DEFINE_GET(ltc_cmdWRCFG2) +TEST_LTC_DEFINE_GET(ltc_cmdRDCFG) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVA) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVB) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVC) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVD) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVE) +TEST_LTC_DEFINE_GET(ltc_cmdRDCVF) +TEST_LTC_DEFINE_GET(ltc_cmdWRCOMM) +TEST_LTC_DEFINE_GET(ltc_cmdSTCOMM) +TEST_LTC_DEFINE_GET(ltc_cmdRDCOMM) +TEST_LTC_DEFINE_GET(ltc_cmdRDAUXA) +TEST_LTC_DEFINE_GET(ltc_cmdRDAUXB) +TEST_LTC_DEFINE_GET(ltc_cmdRDAUXC) +TEST_LTC_DEFINE_GET(ltc_cmdRDAUXD) +TEST_LTC_DEFINE_GET(ltc_cmdADCV_normal_DCP0) +TEST_LTC_DEFINE_GET(ltc_cmdADCV_normal_DCP1) +TEST_LTC_DEFINE_GET(ltc_cmdADCV_filtered_DCP0) +TEST_LTC_DEFINE_GET(ltc_cmdADCV_filtered_DCP1) +TEST_LTC_DEFINE_GET(ltc_cmdADCV_fast_DCP0) +TEST_LTC_DEFINE_GET(ltc_cmdADCV_fast_DCP1) +TEST_LTC_DEFINE_GET(ltc_cmdADCV_fast_DCP0_twocells) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_normal_GPIO1) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_filtered_GPIO1) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_fast_GPIO1) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_normal_GPIO2) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_filtered_GPIO2) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_fast_GPIO2) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_normal_GPIO3) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_filtered_GPIO3) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_fast_GPIO3) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_normal_ALLGPIOS) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_filtered_ALLGPIOS) +TEST_LTC_DEFINE_GET(ltc_cmdADAX_fast_ALLGPIOS) +TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PUP_normal_DCP0) +TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PDOWN_normal_DCP0) +TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PUP_filtered_DCP0) +TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PDOWN_filtered_DCP0) #endif diff --git a/src/app/driver/afe/ltc/6813-1/ltc_6813-1.json b/src/app/driver/afe/ltc/6813-1/ltc_6813-1.json index ab69d8bb..2183cc4a 100644 --- a/src/app/driver/afe/ltc/6813-1/ltc_6813-1.json +++ b/src/app/driver/afe/ltc/6813-1/ltc_6813-1.json @@ -2,6 +2,8 @@ "include": [ ".", "config", + "../common", + "../common/config", "../../api" ] } diff --git a/src/app/driver/afe/ltc/6813-1/wscript b/src/app/driver/afe/ltc/6813-1/wscript index be00a9a9..62b2aba3 100644 --- a/src/app/driver/afe/ltc/6813-1/wscript +++ b/src/app/driver/afe/ltc/6813-1/wscript @@ -49,17 +49,11 @@ def build(bld): os.path.join("config", "ltc_6813-1_cfg.c"), os.path.join("ltc_6813-1.c"), os.path.join("..", "api", "ltc_afe.c"), - os.path.join("..", "common", "config", "ltc_afe_dma_cfg.c"), os.path.join("..", "common", "ltc_afe_dma.c"), os.path.join("..", "common", "ltc_pec.c"), os.path.join("..", "..", "api", "afe_plausibility.c"), ] includes = [ - ".", - os.path.join("..", "..", "api"), - os.path.join("config"), - os.path.join("..", "common"), - os.path.join("..", "common", "config"), os.path.join("..", "..", "..", "config"), os.path.join("..", "..", "..", "dma"), os.path.join("..", "..", "..", "foxmath"), @@ -76,6 +70,7 @@ def build(bld): os.path.join("..", "..", "..", "..", "main", "include"), os.path.join("..", "..", "..", "..", "task", "os"), ] + includes.extend(bld.env.INCLUDES_AFE) includes.extend(bld.env.INCLUDES_RTOS) cflags = bld.env.CFLAGS_FOXBMS target = f"{bld.env.APPNAME.lower()}-afe-driver" diff --git a/src/app/driver/afe/ltc/api/ltc_afe.c b/src/app/driver/afe/ltc/api/ltc_afe.c index 11535057..e4fd6cfa 100644 --- a/src/app/driver/afe/ltc/api/ltc_afe.c +++ b/src/app/driver/afe/ltc/api/ltc_afe.c @@ -43,8 +43,8 @@ * @file ltc_afe.c * @author foxBMS Team * @date 2020-05-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix AFE * diff --git a/src/app/driver/afe/ltc/common/config/ltc_cfg.h b/src/app/driver/afe/ltc/common/config/ltc_cfg.h index 60a20fb0..8ee9f4e5 100644 --- a/src/app/driver/afe/ltc/common/config/ltc_cfg.h +++ b/src/app/driver/afe/ltc/common/config/ltc_cfg.h @@ -43,8 +43,8 @@ * @file ltc_cfg.h * @author foxBMS Team * @date 2015-02-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix LTC * diff --git a/src/app/driver/afe/ltc/common/ltc.h b/src/app/driver/afe/ltc/common/ltc.h index 97dc9b78..e1827876 100644 --- a/src/app/driver/afe/ltc/common/ltc.h +++ b/src/app/driver/afe/ltc/common/ltc.h @@ -43,8 +43,8 @@ * @file ltc.h * @author foxBMS Team * @date 2015-09-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix LTC * diff --git a/src/app/driver/afe/ltc/common/ltc_afe_dma.c b/src/app/driver/afe/ltc/common/ltc_afe_dma.c index e17fdc3c..f5d9e53b 100644 --- a/src/app/driver/afe/ltc/common/ltc_afe_dma.c +++ b/src/app/driver/afe/ltc/common/ltc_afe_dma.c @@ -43,8 +43,8 @@ * @file ltc_afe_dma.c * @author foxBMS Team * @date 2020-05-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix AFE * diff --git a/src/app/driver/afe/ltc/common/ltc_afe_dma.h b/src/app/driver/afe/ltc/common/ltc_afe_dma.h index ec987300..6df5b64b 100644 --- a/src/app/driver/afe/ltc/common/ltc_afe_dma.h +++ b/src/app/driver/afe/ltc/common/ltc_afe_dma.h @@ -43,8 +43,8 @@ * @file ltc_afe_dma.h * @author foxBMS Team * @date 2020-05-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix AFE * diff --git a/src/app/driver/afe/ltc/common/ltc_defs.h b/src/app/driver/afe/ltc/common/ltc_defs.h index a8846ccc..276f4366 100644 --- a/src/app/driver/afe/ltc/common/ltc_defs.h +++ b/src/app/driver/afe/ltc/common/ltc_defs.h @@ -43,8 +43,8 @@ * @file ltc_defs.h * @author foxBMS Team * @date 2015-09-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix LTC * @@ -364,7 +364,7 @@ typedef enum { LTC_SAVE_MUX_MEASUREMENT_MUXMEASUREMENT, /*!< */ } LTC_STATEMACH_MUXMEASUREMENT_SUB_e; -/** State requests for the LTC statemachine */ +/** State requests for the LTC state machine */ typedef enum { LTC_STATE_INIT_REQUEST, /*!< */ LTC_STATE_USER_IO_WRITE_REQUEST, /*!< */ @@ -396,7 +396,7 @@ typedef enum { } LTC_STATE_REQUEST_e; /** - * Possible return values when state requests are made to the LTC statemachine + * Possible return values when state requests are made to the LTC state machine */ typedef enum { LTC_OK, /*!< LTC --> ok */ diff --git a/src/app/driver/afe/ltc/common/ltc_pec.c b/src/app/driver/afe/ltc/common/ltc_pec.c index dba24b26..52c309c8 100644 --- a/src/app/driver/afe/ltc/common/ltc_pec.c +++ b/src/app/driver/afe/ltc/common/ltc_pec.c @@ -43,8 +43,8 @@ * @file ltc_pec.c * @author foxBMS Team * @date 2022-11-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix LTC * @@ -79,7 +79,7 @@ uint16_t LTC_CalculatePec15(uint8_t length, const uint8_t *data) { /* Pre-computed CRC15 Table for polynomial 0xC599 */ static const uint16_t ltc_crc15Table[LTC_PEC_PRECOMPUTED_TABLE_SIZE] = { - 0x0000u, 0x4599u, 0x4EABu, 0x00B32, 0x58CFu, 0x1D56u, 0x1664u, 0x53FDu, 0x7407u, 0x319Eu, 0x3AACu, 0x7F35u, + 0x0000u, 0x4599u, 0x4EABu, 0x0B32u, 0x58CFu, 0x1D56u, 0x1664u, 0x53FDu, 0x7407u, 0x319Eu, 0x3AACu, 0x7F35u, 0x2CC8u, 0x6951u, 0x6263u, 0x27FAu, 0x2D97u, 0x680Eu, 0x633Cu, 0x26A5u, 0x7558u, 0x30C1u, 0x3BF3u, 0x7E6Au, 0x5990u, 0x1C09u, 0x173Bu, 0x52A2u, 0x015Fu, 0x44C6u, 0x4FF4u, 0x0A6Du, 0x5B2Eu, 0x1EB7u, 0x1585u, 0x501Cu, 0x03E1u, 0x4678u, 0x4D4Au, 0x08D3u, 0x2F29u, 0x6AB0u, 0x6182u, 0x241Bu, 0x77E6u, 0x327Fu, 0x394Du, 0x7CD4u, diff --git a/src/app/driver/afe/ltc/common/ltc_pec.h b/src/app/driver/afe/ltc/common/ltc_pec.h index d6b73a59..0b9683d6 100644 --- a/src/app/driver/afe/ltc/common/ltc_pec.h +++ b/src/app/driver/afe/ltc/common/ltc_pec.h @@ -43,8 +43,8 @@ * @file ltc_pec.h * @author foxBMS Team * @date 2022-11-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix LTC * diff --git a/src/app/driver/afe/maxim/api/mxm_afe.c b/src/app/driver/afe/maxim/api/mxm_afe.c index 0142e12f..9e221d7d 100644 --- a/src/app/driver/afe/maxim/api/mxm_afe.c +++ b/src/app/driver/afe/maxim/api/mxm_afe.c @@ -43,8 +43,8 @@ * @file mxm_afe.c * @author foxBMS Team * @date 2020-06-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix AFE * diff --git a/src/app/driver/afe/maxim/common/config/mxm_cfg.c b/src/app/driver/afe/maxim/common/config/mxm_cfg.c index df3fe51c..0a0e1a9f 100644 --- a/src/app/driver/afe/maxim/common/config/mxm_cfg.c +++ b/src/app/driver/afe/maxim/common/config/mxm_cfg.c @@ -43,8 +43,8 @@ * @file mxm_cfg.c * @author foxBMS Team * @date 2019-01-09 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/config/mxm_cfg.h b/src/app/driver/afe/maxim/common/config/mxm_cfg.h index 0311bbae..e870cdb5 100644 --- a/src/app/driver/afe/maxim/common/config/mxm_cfg.h +++ b/src/app/driver/afe/maxim/common/config/mxm_cfg.h @@ -43,8 +43,8 @@ * @file mxm_cfg.h * @author foxBMS Team * @date 2019-01-09 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_17841b.c b/src/app/driver/afe/maxim/common/mxm_17841b.c index b3010b7c..6bd6ee9e 100644 --- a/src/app/driver/afe/maxim/common/mxm_17841b.c +++ b/src/app/driver/afe/maxim/common/mxm_17841b.c @@ -43,8 +43,8 @@ * @file mxm_17841b.c * @author foxBMS Team * @date 2018-12-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * @@ -302,21 +302,21 @@ static STD_RETURN_TYPE_e MXM_41BRegisterWrite( /* check if command is a write command (write addresses in MAX17841B are even) */ if ((command % 2u) == 0u) { /* construct tx buffer */ - pInstance->spiTXBuffer[0] = command; + pInstance->spiTxBuffer[0] = command; /* message has payload --> copy into buffer */ if ((kpkPayload != NULL_PTR) && (lengthPayload != 0u)) { for (uint8_t i = 0u; i < lengthPayload; i++) { - pInstance->spiTXBuffer[i + 1u] = kpkPayload[i]; + pInstance->spiTxBuffer[i + 1u] = kpkPayload[i]; } /* null rest of tx buffer */ for (uint8_t i = lengthPayload + 1u; i < MXM_SPI_TX_BUFFER_LENGTH; i++) { - pInstance->spiTXBuffer[i] = 0u; + pInstance->spiTxBuffer[i] = 0u; } /* send command with payload */ - retval = MXM_SendData(pInstance->spiTXBuffer, (uint16_t)lengthPayload + 1u); + retval = MXM_SendData(pInstance->spiTxBuffer, (uint16_t)lengthPayload + 1u); } else if ((kpkPayload == NULL_PTR) && (lengthPayload == 0u)) { /* send command without payload */ - retval = MXM_SendData(pInstance->spiTXBuffer, 1); + retval = MXM_SendData(pInstance->spiTxBuffer, 1); } else { /* invalid configuration */ } @@ -340,13 +340,13 @@ static STD_RETURN_TYPE_e MXM_41BRegisterRead( /* check if command is a read command (read addresses in MAX17841B are odd) */ if ((command % 2u) != 0u) { /* construct tx buffer */ - pInstance->spiTXBuffer[0] = command; + pInstance->spiTxBuffer[0] = command; /* null rest of tx buffer */ for (uint16_t i = 1u; i < MXM_SPI_TX_BUFFER_LENGTH; i++) { - pInstance->spiTXBuffer[i] = 0u; + pInstance->spiTxBuffer[i] = 0u; } /* send command with payload */ - retval = MXM_ReceiveData(pInstance->spiTXBuffer, pRxBuffer, ((uint16_t)length + 1u)); + retval = MXM_ReceiveData(pInstance->spiTxBuffer, pRxBuffer, ((uint16_t)length + 1u)); } return retval; } @@ -357,8 +357,8 @@ static STD_RETURN_TYPE_e MXM_41BConfigRegisterWrite(MXM_41B_INSTANCE_s *pInstanc uint8_t mxm_spi_temp_buffer[MXM_41B_CONFIG_REGISTER_LENGTH] = {0}; /* AXIVION Disable Style Generic-NoMagicNumbers: Magic numbers for index value of array is clear in usage */ - mxm_spi_temp_buffer[0u] = pInstance->regRXIntEnable; - mxm_spi_temp_buffer[1u] = pInstance->regTXIntEnable; + mxm_spi_temp_buffer[0u] = pInstance->regRxIntEnable; + mxm_spi_temp_buffer[1u] = pInstance->regTxIntEnable; mxm_spi_temp_buffer[2u] = MXM_41B_RX_INT_FLAG_DEFAULT_VALUE; mxm_spi_temp_buffer[3u] = MXM_41B_TX_INT_FLAG_DEFAULT_VALUE; mxm_spi_temp_buffer[4u] = pInstance->regConfig1; @@ -385,21 +385,21 @@ static STD_RETURN_TYPE_e MXM_41BBufferWrite( /* AXIVION Routine Generic-MissingParameterAssert: extendMessage: parameter accepts whole range */ /* write address and length to buffer */ - pInstance->spiTXBuffer[0] = (uint16_t)MXM_BUF_WR_LD_Q_0; - pInstance->spiTXBuffer[1] = (uint16_t)messageLength + extendMessage; + pInstance->spiTxBuffer[0] = (uint16_t)MXM_BUF_WR_LD_Q_0; + pInstance->spiTxBuffer[1] = (uint16_t)messageLength + extendMessage; /* iterate of complete TX buffer and * write into proper fields, null rest */ for (uint8_t i = 0; i < (MXM_SPI_TX_BUFFER_LENGTH - 2u); i++) { if (i < messageLength) { - pInstance->spiTXBuffer[i + 2u] = kpkMessage[i]; + pInstance->spiTxBuffer[i + 2u] = kpkMessage[i]; } else { - pInstance->spiTXBuffer[i + 2u] = 0x00u; + pInstance->spiTxBuffer[i + 2u] = 0x00u; } } /* send data */ - return MXM_SendData(pInstance->spiTXBuffer, ((uint16_t)messageLength + 2u)); + return MXM_SendData(pInstance->spiTxBuffer, ((uint16_t)messageLength + 2u)); } static void MXM_41BTransitionToIdleSuccess(MXM_41B_INSTANCE_s *pInstance) { @@ -408,7 +408,6 @@ static void MXM_41BTransitionToIdleSuccess(MXM_41B_INSTANCE_s *pInstance) { pInstance->state = MXM_STATEMACH_41B_IDLE; pInstance->substate = MXM_41B_ENTRY_SUBSTATE; *pInstance->processed = MXM_41B_STATE_PROCESSED; - return; } static void MXM_41BTransitionToIdleError(MXM_41B_INSTANCE_s *pInstance) { @@ -417,19 +416,17 @@ static void MXM_41BTransitionToIdleError(MXM_41B_INSTANCE_s *pInstance) { pInstance->state = MXM_STATEMACH_41B_IDLE; pInstance->substate = MXM_41B_ENTRY_SUBSTATE; *pInstance->processed = MXM_41B_STATE_ERROR; - return; } static void MXM_41BInitializeRegisterCopies(MXM_41B_INSTANCE_s *pInstance) { FAS_ASSERT(pInstance != NULL_PTR); - pInstance->regRXStatus = 0u; - pInstance->regTXStatus = 0u; - pInstance->regRXIntEnable = MXM_41B_RX_INT_ENABLE_DEFAULT_VALUE; - pInstance->regTXIntEnable = MXM_41B_TX_INT_ENABLE_DEFAULT_VALUE; + pInstance->regRxStatus = 0u; + pInstance->regTxStatus = 0u; + pInstance->regRxIntEnable = MXM_41B_RX_INT_ENABLE_DEFAULT_VALUE; + pInstance->regTxIntEnable = MXM_41B_TX_INT_ENABLE_DEFAULT_VALUE; pInstance->regConfig1 = MXM_41B_CONFIG_1_DEFAULT_VALUE; pInstance->regConfig2 = MXM_41B_CONFIG_2_DEFAULT_VALUE; pInstance->regConfig3 = MXM_41B_CONFIG_3_DEFAULT_VALUE; - return; } static void MXM_41BStateHandlerInit(MXM_41B_INSTANCE_s *pInstance) { @@ -460,7 +457,7 @@ static void MXM_41BStateHandlerInit(MXM_41B_INSTANCE_s *pInstance) { } } else if (pInstance->substate == MXM_41B_INIT_READ_CONFIG_REGISTERS) { const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead( - pInstance, MXM_REG_RX_INTERRUPT_ENABLE_R, pInstance->spiRXBuffer, MXM_41B_CONFIG_REGISTER_LENGTH); + pInstance, MXM_REG_RX_INTERRUPT_ENABLE_R, pInstance->spiRxBuffer, MXM_41B_CONFIG_REGISTER_LENGTH); if (retval == STD_OK) { pInstance->substate = MXM_41B_INIT_CHECK_INITIALIZATION; @@ -494,7 +491,7 @@ static void MXM_41BStateHandlerInit(MXM_41B_INSTANCE_s *pInstance) { MXM_41B_CONFIG_3_DEFAULT_VALUE}; for (uint8_t i = 0; i < MXM_41B_CONFIG_REGISTER_LENGTH; i++) { - if (pInstance->spiRXBuffer[i + 1u] != mxm_41B_reg_default_values[i]) { + if (pInstance->spiRxBuffer[i + 1u] != mxm_41B_reg_default_values[i]) { retval = STD_NOT_OK; } } @@ -520,7 +517,7 @@ static void MXM_41BStateHandlerGetVersion(MXM_41B_INSTANCE_s *pInstance) { if (pInstance->substate == MXM_41B_VERSION_REQUEST_REGISTER) { /* read two byte in order to read also the adjacent version register */ - const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_MODEL_R, pInstance->spiRXBuffer, 2); + const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_MODEL_R, pInstance->spiRxBuffer, 2); if (retval == STD_OK) { pInstance->substate = MXM_41B_VERSION_VERIFY; @@ -528,12 +525,12 @@ static void MXM_41BStateHandlerGetVersion(MXM_41B_INSTANCE_s *pInstance) { } else if (pInstance->substate == MXM_41B_VERSION_VERIFY) { if (MXM_GetSPIStateReady() == STD_OK) { /* get model from model register and high nibble of mask revision (should be 0x8410) */ - pInstance->hwModel = - (uint16_t)((pInstance->spiRXBuffer[1] & MXM_41B_BIT_MASK_ONE_BYTE) << MXM_41B_BIT_SHIFT_HALF_BYTE); - pInstance->hwModel |= - (uint16_t)((pInstance->spiRXBuffer[2] & MXM_41B_BIT_MASK_HIGH_NIBBLE) >> MXM_41B_BIT_SHIFT_HALF_BYTE); + pInstance->hardwareModel = + (uint16_t)((pInstance->spiRxBuffer[1] & MXM_41B_BIT_MASK_ONE_BYTE) << MXM_41B_BIT_SHIFT_HALF_BYTE); + pInstance->hardwareModel |= + (uint16_t)((pInstance->spiRxBuffer[2] & MXM_41B_BIT_MASK_HIGH_NIBBLE) >> MXM_41B_BIT_SHIFT_HALF_BYTE); /* extract mask revision from low nibble */ - pInstance->hwMaskRevision = (uint8_t)(pInstance->spiRXBuffer[2] & MXM_41B_BIT_MASK_LOW_NIBBLE); + pInstance->hardwareMaskRevision = (uint8_t)(pInstance->spiRxBuffer[2] & MXM_41B_BIT_MASK_LOW_NIBBLE); MXM_41BTransitionToIdleSuccess(pInstance); } @@ -571,15 +568,15 @@ static void MXM_41BStateHandlerReadStatusRegister(MXM_41B_INSTANCE_s *pInstance) if (pInstance->substate == MXM_41B_READ_STATUS_REGISTER_SEND) { /* read rx and tx status register */ - const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_RX_STATUS_R, pInstance->spiRXBuffer, 2); + const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_RX_STATUS_R, pInstance->spiRxBuffer, 2); if (retval == STD_NOT_OK) { MXM_41BTransitionToIdleError(pInstance); } else { pInstance->substate = MXM_41B_READ_STATUS_REGISTER_PROCESS; } } else if (pInstance->substate == MXM_41B_READ_STATUS_REGISTER_PROCESS) { - pInstance->regRXStatus = (uint8_t)(pInstance->spiRXBuffer[1] & 0xFFu); - pInstance->regTXStatus = (uint8_t)(pInstance->spiRXBuffer[2] & 0xFFu); + pInstance->regRxStatus = (uint8_t)(pInstance->spiRxBuffer[1] & 0xFFu); + pInstance->regTxStatus = (uint8_t)(pInstance->spiRxBuffer[2] & 0xFFu); MXM_41BTransitionToIdleSuccess(pInstance); } else { /* something is very broken */ @@ -595,14 +592,14 @@ static void MXM_41BStateHandlerUartTransaction(MXM_41B_INSTANCE_s *pInstance) { } if (pInstance->substate == MXM_41B_UART_READ_RX_SPACE) { - const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_RX_SPACE_R, pInstance->spiRXBuffer, 1u); + const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_RX_SPACE_R, pInstance->spiRxBuffer, 1u); if (retval == STD_NOT_OK) { MXM_41BTransitionToIdleError(pInstance); } else { pInstance->substate = MXM_41B_UART_READ_RX_SPACE_PARSE; } } else if (pInstance->substate == MXM_41B_UART_READ_RX_SPACE_PARSE) { - pInstance->regRxSpace = (uint8_t)(pInstance->spiRXBuffer[1] & MXM_41B_BIT_MASK_ONE_BYTE); + pInstance->regRxSpace = (uint8_t)(pInstance->spiRxBuffer[1] & MXM_41B_BIT_MASK_ONE_BYTE); pInstance->substate = MXM_41B_UART_WRITE_LOAD_QUEUE; } else if (pInstance->substate == MXM_41B_UART_WRITE_LOAD_QUEUE) { @@ -621,7 +618,7 @@ static void MXM_41BStateHandlerUartTransaction(MXM_41B_INSTANCE_s *pInstance) { const uint8_t payloadLength = pInstance->payloadLength + 1u; /* send read load queue */ const STD_RETURN_TYPE_e retval = - MXM_41BRegisterRead(pInstance, MXM_BUF_RD_LD_Q_0, pInstance->spiRXBuffer, payloadLength); + MXM_41BRegisterRead(pInstance, MXM_BUF_RD_LD_Q_0, pInstance->spiRxBuffer, payloadLength); if (retval == STD_NOT_OK) { MXM_41BTransitionToIdleError(pInstance); @@ -632,12 +629,12 @@ static void MXM_41BStateHandlerUartTransaction(MXM_41B_INSTANCE_s *pInstance) { /* verify load queue */ STD_RETURN_TYPE_e retval = STD_OK; /* check message length */ - if (pInstance->spiRXBuffer[1] != (pInstance->payloadLength + (uint16_t)pInstance->extendMessageBytes)) { + if (pInstance->spiRxBuffer[1] != (pInstance->payloadLength + (uint16_t)pInstance->extendMessageBytes)) { retval = STD_NOT_OK; } for (uint8_t i = 0; i < pInstance->payloadLength; i++) { FAS_ASSERT(pInstance->pPayload != NULL_PTR); - if (pInstance->spiRXBuffer[i + 2u] != pInstance->pPayload[i]) { + if (pInstance->spiRxBuffer[i + 2u] != pInstance->pPayload[i]) { /* message corrupted during SPI transfer */ retval = STD_NOT_OK; } @@ -656,7 +653,7 @@ static void MXM_41BStateHandlerUartTransaction(MXM_41B_INSTANCE_s *pInstance) { } } else if (pInstance->substate == MXM_41B_UART_WAIT_FOR_RX_STATUS_CHANGE_WRITE) { /* poll RX status change */ - const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_RX_STATUS_R, pInstance->spiRXBuffer, 1); + const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_RX_STATUS_R, pInstance->spiRxBuffer, 1); if (retval == STD_NOT_OK) { MXM_41BTransitionToIdleError(pInstance); @@ -665,7 +662,7 @@ static void MXM_41BStateHandlerUartTransaction(MXM_41B_INSTANCE_s *pInstance) { } } else if (pInstance->substate == MXM_41B_UART_WAIT_FOR_RX_STATUS_CHANGE_READ_AND_READ_BACK_RCV_BUF) { /* update RX status register copy with received buffer */ - pInstance->regRXStatus = (uint8_t)(pInstance->spiRXBuffer[1] & MXM_41B_BIT_MASK_ONE_BYTE); + pInstance->regRxStatus = (uint8_t)(pInstance->spiRxBuffer[1] & MXM_41B_BIT_MASK_ONE_BYTE); /* check if RX_OVERFLOW_Status is 1 */ MXM_41B_REG_BIT_VALUE rx_overflow_status_value = MXM_41B_REG_FALSE; const STD_RETURN_TYPE_e resultWrongRegisterOverflow = @@ -691,7 +688,7 @@ static void MXM_41BStateHandlerUartTransaction(MXM_41B_INSTANCE_s *pInstance) { const uint8_t payloadLength = pInstance->payloadLength + 1u + pInstance->extendMessageBytes; /* read back receive buffer */ const STD_RETURN_TYPE_e retval = - MXM_41BRegisterRead(pInstance, MXM_BUF_RD_NXT_MSG, pInstance->spiRXBuffer, payloadLength); + MXM_41BRegisterRead(pInstance, MXM_BUF_RD_NXT_MSG, pInstance->spiRxBuffer, payloadLength); if (retval == STD_NOT_OK) { MXM_41BTransitionToIdleError(pInstance); @@ -709,10 +706,10 @@ static void MXM_41BStateHandlerUartTransaction(MXM_41B_INSTANCE_s *pInstance) { } } } else if (pInstance->substate == MXM_41B_UART_READ_BACK_RECEIVE_BUFFER_SAVE) { - if ((pInstance->spiRXBuffer != NULL_PTR) && (pInstance->pRxBuffer != NULL_PTR)) { + if ((pInstance->spiRxBuffer != NULL_PTR) && (pInstance->pRxBuffer != NULL_PTR)) { for (uint16_t i = 0; i < ((uint16_t)pInstance->payloadLength + pInstance->extendMessageBytes); i++) { if (i < pInstance->rxBufferLength) { - pInstance->pRxBuffer[i] = pInstance->spiRXBuffer[i + 1u]; + pInstance->pRxBuffer[i] = pInstance->spiRxBuffer[i + 1u]; } } } @@ -730,7 +727,7 @@ static void MXM_41BStateHandlerCheckFmea(MXM_41B_INSTANCE_s *pInstance) { } if (pInstance->substate == MXM_41B_FMEA_REQUEST_REGISTER) { - const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_FMEA_R, pInstance->spiRXBuffer, 1); + const STD_RETURN_TYPE_e retval = MXM_41BRegisterRead(pInstance, MXM_REG_FMEA_R, pInstance->spiRxBuffer, 1); if (retval == STD_OK) { pInstance->substate = MXM_41B_FMEA_VERIFY; @@ -738,7 +735,7 @@ static void MXM_41BStateHandlerCheckFmea(MXM_41B_INSTANCE_s *pInstance) { } else if (pInstance->substate == MXM_41B_FMEA_VERIFY) { STD_RETURN_TYPE_e retval = STD_NOT_OK; if (MXM_GetSPIStateReady() == STD_OK) { - pInstance->regFmea = pInstance->spiRXBuffer[1u]; + pInstance->regFmea = pInstance->spiRxBuffer[1u]; if (pInstance->regFmea == 0u) { retval = STD_OK; } @@ -872,18 +869,18 @@ extern STD_RETURN_TYPE_e MXM_41BWriteRegisterFunction( value, 4, MXM_41B_KEEP_ALIVE, pInstance->regConfig3); /* MXM_41B_KEEP_ALIVE is 0st bit of regConfig3 */ break; case MXM_41B_REG_FUNCTION_RX_ERROR_INT: - pInstance->regRXIntEnable = mxm_41bWriteValue( + pInstance->regRxIntEnable = mxm_41bWriteValue( value, 1, MXM_41B_RX_ERROR, - pInstance->regRXIntEnable); /* MXM_41B_RX_ERROR is 7th bit of regRXIntEnable */ + pInstance->regRxIntEnable); /* MXM_41B_RX_ERROR is 7th bit of regRxIntEnable */ break; case MXM_41B_REG_FUNCTION_RX_OVERFLOW_INT: - pInstance->regRXIntEnable = mxm_41bWriteValue( + pInstance->regRxIntEnable = mxm_41bWriteValue( value, 1, MXM_41B_RX_OVERFLOW_INT_ENABLE, - pInstance->regRXIntEnable); /* MXM_41B_RX_OVERFLOW is 2nd bit of regRXIntEnable */ + pInstance->regRxIntEnable); /* MXM_41B_RX_OVERFLOW is 2nd bit of regRxIntEnable */ break; default: retval = STD_NOT_OK; @@ -905,16 +902,16 @@ extern STD_RETURN_TYPE_e MXM_41BReadRegisterFunction( switch (registerFunction) { case MXM_41B_REG_FUNCTION_RX_BUSY_STATUS: - *pValue = mxm_41bReadValue(kpkInstance->regRXStatus, 1, MXM_41B_RX_BUSY_STATUS); /* 5th bit */ + *pValue = mxm_41bReadValue(kpkInstance->regRxStatus, 1, MXM_41B_RX_BUSY_STATUS); /* 5th bit */ break; case MXM_41B_REG_FUNCTION_RX_STOP_STATUS: - *pValue = mxm_41bReadValue(kpkInstance->regRXStatus, 1, MXM_41B_RX_STOP_STATUS); /* 1st bit */ + *pValue = mxm_41bReadValue(kpkInstance->regRxStatus, 1, MXM_41B_RX_STOP_STATUS); /* 1st bit */ break; case MXM_41B_REG_FUNCTION_RX_OVERFLOW_STATUS: - *pValue = mxm_41bReadValue(kpkInstance->regRXStatus, 1, MXM_41B_RX_OVERFLOW_STATUS); /* 3rd bit */ + *pValue = mxm_41bReadValue(kpkInstance->regRxStatus, 1, MXM_41B_RX_OVERFLOW_STATUS); /* 3rd bit */ break; case MXM_41B_REG_FUNCTION_RX_EMPTY_STATUS: - *pValue = mxm_41bReadValue(kpkInstance->regRXStatus, 1, MXM_41B_RX_EMPTY_STATUS); /* 0th bit */ + *pValue = mxm_41bReadValue(kpkInstance->regRxStatus, 1, MXM_41B_RX_EMPTY_STATUS); /* 0th bit */ break; case MXM_41B_REG_FUNCTION_TX_PREAMBLES: *pValue = mxm_41bReadValue(kpkInstance->regConfig2, 1, MXM_41B_TX_PREAMBLES); /* 5th bit */ @@ -979,27 +976,27 @@ extern void MXM_41BInitializeStateStruct(MXM_41B_INSTANCE_s *pInstance) { MXM_41BInitializeRegisterCopies(pInstance); - pInstance->state = MXM_STATEMACH_41B_UNINITIALIZED; - pInstance->substate = MXM_41B_ENTRY_SUBSTATE; - pInstance->pPayload = NULL_PTR; - pInstance->payloadLength = 0u; - pInstance->pRxBuffer = NULL_PTR; - pInstance->rxBufferLength = 0u; - pInstance->processed = NULL_PTR; - pInstance->extendMessageBytes = 0u; - pInstance->waitCounter = 0u; - pInstance->regRxSpace = 0u; - pInstance->regFmea = 0u; - pInstance->hwModel = 0u; - pInstance->hwMaskRevision = 0u; - pInstance->shutdownTimeStamp = 0u; + pInstance->state = MXM_STATEMACH_41B_UNINITIALIZED; + pInstance->substate = MXM_41B_ENTRY_SUBSTATE; + pInstance->pPayload = NULL_PTR; + pInstance->payloadLength = 0u; + pInstance->pRxBuffer = NULL_PTR; + pInstance->rxBufferLength = 0u; + pInstance->processed = NULL_PTR; + pInstance->extendMessageBytes = 0u; + pInstance->waitCounter = 0u; + pInstance->regRxSpace = 0u; + pInstance->regFmea = 0u; + pInstance->hardwareModel = 0u; + pInstance->hardwareMaskRevision = 0u; + pInstance->shutdownTimeStamp = 0u; for (uint32_t i = 0u; i < MXM_SPI_RX_BUFFER_LENGTH; i++) { - pInstance->spiRXBuffer[i] = 0u; + pInstance->spiRxBuffer[i] = 0u; } for (uint32_t i = 0u; i < MXM_SPI_TX_BUFFER_LENGTH; i++) { - pInstance->spiTXBuffer[i] = 0u; + pInstance->spiTxBuffer[i] = 0u; } } diff --git a/src/app/driver/afe/maxim/common/mxm_17841b.h b/src/app/driver/afe/maxim/common/mxm_17841b.h index 8434bd0f..23eb55a5 100644 --- a/src/app/driver/afe/maxim/common/mxm_17841b.h +++ b/src/app/driver/afe/maxim/common/mxm_17841b.h @@ -43,8 +43,8 @@ * @file mxm_17841b.h * @author foxBMS Team * @date 2018-12-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * @@ -72,7 +72,7 @@ * @brief SPI TX buffer length * * This define defines the length of the SPI TX buffer. - * This TX buffer is declared in #MXM_41B_INSTANCE_s::spiTXBuffer. + * This TX buffer is declared in #MXM_41B_INSTANCE_s::spiTxBuffer. * The buffer has to be large enough to accommodate every * relevant SPI transaction. */ @@ -168,20 +168,20 @@ typedef struct { MXM_41B_STATE_REQUEST_STATUS_e *processed; /*!< status-indicator of the state-machine */ uint8_t extendMessageBytes; /*!< pass on number of bytes by which the TX-message shall be extended */ uint8_t waitCounter; /*!< general error counter, will be reset in funtions */ - uint8_t regRXIntEnable; /*!< local storage for the RX Interrupt Enable register */ - uint8_t regTXIntEnable; /*!< local storage for the TX Interrupt Enable register */ - uint8_t regRXStatus; /*!< local storage for the RX Status register */ - uint8_t regTXStatus; /*!< local storage for the TX status register */ + uint8_t regRxIntEnable; /*!< local storage for the RX Interrupt Enable register */ + uint8_t regTxIntEnable; /*!< local storage for the TX Interrupt Enable register */ + uint8_t regRxStatus; /*!< local storage for the RX Status register */ + uint8_t regTxStatus; /*!< local storage for the TX status register */ uint8_t regConfig1; /*!< local storage for the Config 1 register */ uint8_t regConfig2; /*!< local storage for the Config 2 register */ uint8_t regConfig3; /*!< local storage for the Config 3 register */ uint8_t regRxSpace; /*!< RX space register (shows the left space in RX buffer) */ uint8_t regFmea; /*!< FMEA register */ - uint16_t hwModel; /*!< model number of the connected IC */ - uint8_t hwMaskRevision; /*!< mask revision of the connected IC */ + uint16_t hardwareModel; /*!< model number of the connected IC */ + uint8_t hardwareMaskRevision; /*!< mask revision of the connected IC */ uint32_t shutdownTimeStamp; /*!< timestamp of the last shutdown (or startup) action */ - uint16_t spiRXBuffer[MXM_SPI_RX_BUFFER_LENGTH]; /*!< rx buffer for SPI */ - uint16_t spiTXBuffer[MXM_SPI_TX_BUFFER_LENGTH]; /*!< tx buffer for SPI */ + uint16_t spiRxBuffer[MXM_SPI_RX_BUFFER_LENGTH]; /*!< rx buffer for SPI */ + uint16_t spiTxBuffer[MXM_SPI_TX_BUFFER_LENGTH]; /*!< tx buffer for SPI */ } MXM_41B_INSTANCE_s; /*========== Extern Constant and Variable Declarations ======================*/ diff --git a/src/app/driver/afe/maxim/common/mxm_1785x.c b/src/app/driver/afe/maxim/common/mxm_1785x.c index 64cc105d..e9fdae9e 100644 --- a/src/app/driver/afe/maxim/common/mxm_1785x.c +++ b/src/app/driver/afe/maxim/common/mxm_1785x.c @@ -43,8 +43,8 @@ * @file mxm_1785x.c * @author foxBMS Team * @date 2019-01-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * @@ -119,7 +119,7 @@ static const AFE_PLAUSIBILITY_VALUES_s mxm_plausibleCellVoltages = { /*========== Static Function Prototypes =====================================*/ -/** @brief Retrieves data from lower statemachine and writes it to the rx buffer. */ +/** @brief Retrieves data from lower state machine and writes it to the rx buffer. */ static void MXM_GetDataFrom5XStateMachine(MXM_MONITORING_INSTANCE_s *pInstance); /** @@ -1105,25 +1105,23 @@ extern STD_RETURN_TYPE_e MXM_ParseVoltagesIntoDB(const MXM_MONITORING_INSTANCE_s (int32_t)kpkInstance->localVoltages.blockVoltages[i_mod]; FAS_ASSERT( BS_NR_OF_CELL_BLOCKS_PER_MODULE <= MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE); /*!< invalid configuration! */ - for (uint8_t i_bat = 0; i_bat < BS_NR_OF_CELL_BLOCKS_PER_MODULE; i_bat++) { - uint16_t cell_counter_db = (moduleNumber * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + i_bat; - uint16_t cell_counter_max = ((uint16_t)i_mod * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE) + i_bat; + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + uint16_t cell_counter_max = ((uint16_t)i_mod * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE) + cb; const uint16_t cellVoltageLocal_mV = kpkInstance->localVoltages.cellVoltages_mV[cell_counter_max]; if ((int32_t)cellVoltageLocal_mV > INT16_MAX) { - kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][cell_counter_db] = INT16_MAX; + kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][i_mod][cb] = INT16_MAX; } else { - kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][cell_counter_db] = + kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][i_mod][cb] = (int16_t)cellVoltageLocal_mV; } const STD_RETURN_TYPE_e valueIsPlausible = AFE_PlausibilityCheckVoltageMeasurementRange( - kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][cell_counter_db], - mxm_plausibleCellVoltages); + kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][i_mod][cb], mxm_plausibleCellVoltages); if ((valueIsPlausible == STD_OK) && moduleIsConnected) { numberValidVoltageMeasurements[stringNumber]++; } else { /* Invalidate cell voltage measurement */ kpkInstance->pCellVoltages_table->invalidCellVoltage[stringNumber][moduleNumber] |= - ((uint64_t)1u << i_bat); + ((uint64_t)1u << cb); } } } @@ -1140,14 +1138,13 @@ extern STD_RETURN_TYPE_e MXM_ParseVoltagesIntoDB(const MXM_MONITORING_INSTANCE_s /* store aux measurement from AUX2 (MUX0) */ if (kpkInstance->muxCounter < BS_NR_OF_TEMP_SENSORS_PER_MODULE) { - const uint16_t temperatureIndexDb = (moduleNumber * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + - kpkInstance->muxCounter; + const uint16_t temperatureIndexDb = kpkInstance->muxCounter; const uint16_t temperatureIndexMxm = ((uint16_t)i_mod * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE) + 2u; const uint16_t auxVoltage_mV = kpkInstance->localVoltages.auxVoltages_mV[temperatureIndexMxm]; /* const uint16_t temporaryVoltage = (auxVoltage_mV / ((float_t)3300 - auxVoltage_mV)) * 1000; */ const int16_t temperature_ddegC = TSI_GetTemperature(auxVoltage_mV); - kpkInstance->pCellTemperatures_table->cellTemperature_ddegC[stringNumber][temperatureIndexDb] = - temperature_ddegC; + kpkInstance->pCellTemperatures_table + ->cellTemperature_ddegC[stringNumber][moduleNumber][temperatureIndexDb] = temperature_ddegC; const STD_RETURN_TYPE_e valueIsPlausible = AFE_PlausibilityCheckTempMinMax(temperature_ddegC); if ((valueIsPlausible == STD_OK) && moduleIsConnected) { numberValidTemperatureMeasurements[stringNumber]++; diff --git a/src/app/driver/afe/maxim/common/mxm_1785x.h b/src/app/driver/afe/maxim/common/mxm_1785x.h index 1871e50b..7a73250b 100644 --- a/src/app/driver/afe/maxim/common/mxm_1785x.h +++ b/src/app/driver/afe/maxim/common/mxm_1785x.h @@ -43,8 +43,8 @@ * @file mxm_1785x.h * @author foxBMS Team * @date 2019-01-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * @@ -144,7 +144,7 @@ extern void MXM_InitializeStateStruct( extern void MXM_CheckIfErrorCounterCanBeReset(MXM_MONITORING_INSTANCE_s *pInstance); /** - * @brief Fill the balancing datastructure + * @brief Fill the balancing data structure * @details This function fills the data-structure that describes * which balancing channels of the monitoring ICs should be * activated. @@ -154,7 +154,7 @@ extern void MXM_CheckIfErrorCounterCanBeReset(MXM_MONITORING_INSTANCE_s *pInstan extern STD_RETURN_TYPE_e MXM_ConstructBalancingBuffer(MXM_BALANCING_STATE_s *pBalancingInstance); /** - * @brief Handle the statemachine-transactions for a WRITEALL + * @brief Handle the state machine-transactions for a WRITEALL * @details Before calling this function, update the command buffer of * the state-variable. Then call this function and pass on the * state-variable and the next state. The function will @@ -171,7 +171,7 @@ extern void MXM_HandleStateWriteall( MXM_STATEMACHINE_OPERATION_STATES_e nextState); /** - * @brief Handle the statemachine-transactions for a READALL + * @brief Handle the state machine-transactions for a READALL * @details Call this function and pass on the state-variable, the * register to be read and the next state. The function will * handle the communication with the lower state-machine and diff --git a/src/app/driver/afe/maxim/common/mxm_1785x_tools.c b/src/app/driver/afe/maxim/common/mxm_1785x_tools.c index 9b2ce1e3..4ac9b673 100644 --- a/src/app/driver/afe/maxim/common/mxm_1785x_tools.c +++ b/src/app/driver/afe/maxim/common/mxm_1785x_tools.c @@ -43,8 +43,8 @@ * @file mxm_1785x_tools.c * @author foxBMS Team * @date 2020-07-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_1785x_tools.h b/src/app/driver/afe/maxim/common/mxm_1785x_tools.h index c36dc753..ecf0369a 100644 --- a/src/app/driver/afe/maxim/common/mxm_1785x_tools.h +++ b/src/app/driver/afe/maxim/common/mxm_1785x_tools.h @@ -43,8 +43,8 @@ * @file mxm_1785x_tools.h * @author foxBMS Team * @date 2020-07-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * @@ -88,7 +88,7 @@ typedef enum { MXM_STATEMACHINE_STATES_MAXSTATE, /*!< highest state */ } MXM_STATEMACHINE_STATES_e; -/** states of the #MXM_StateMachineOperation() statemachine */ +/** states of the #MXM_StateMachineOperation() state machine */ typedef enum { MXM_INIT_ENTRY, MXM_INIT_DEVCFG1, diff --git a/src/app/driver/afe/maxim/common/mxm_41b_register_map.h b/src/app/driver/afe/maxim/common/mxm_41b_register_map.h index 9be6da23..54eef5ce 100644 --- a/src/app/driver/afe/maxim/common/mxm_41b_register_map.h +++ b/src/app/driver/afe/maxim/common/mxm_41b_register_map.h @@ -43,8 +43,8 @@ * @file mxm_41b_register_map.h * @author foxBMS Team * @date 2020-06-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_afe_dma.c b/src/app/driver/afe/maxim/common/mxm_afe_dma.c index 309e7def..b8dffd66 100644 --- a/src/app/driver/afe/maxim/common/mxm_afe_dma.c +++ b/src/app/driver/afe/maxim/common/mxm_afe_dma.c @@ -43,8 +43,8 @@ * @file mxm_afe_dma.c * @author foxBMS Team * @date 2020-06-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix AFE * @@ -53,8 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "mxm_afe_dma.h" - +#include "afe_dma.h" #include "fassert.h" #include diff --git a/src/app/driver/afe/maxim/common/mxm_basic_defines.h b/src/app/driver/afe/maxim/common/mxm_basic_defines.h index b086e15a..0ad41da8 100644 --- a/src/app/driver/afe/maxim/common/mxm_basic_defines.h +++ b/src/app/driver/afe/maxim/common/mxm_basic_defines.h @@ -43,8 +43,8 @@ * @file mxm_basic_defines.h * @author foxBMS Team * @date 2020-02-11 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_battery_management.c b/src/app/driver/afe/maxim/common/mxm_battery_management.c index 30147c84..8118c606 100644 --- a/src/app/driver/afe/maxim/common/mxm_battery_management.c +++ b/src/app/driver/afe/maxim/common/mxm_battery_management.c @@ -43,8 +43,8 @@ * @file mxm_battery_management.c * @author foxBMS Team * @date 2019-01-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * @@ -427,7 +427,6 @@ static void MXM_5XHandle41BErrorState(MXM_5X_INSTANCE_s *pInstance) { if (pInstance->errorCounter < (uint8_t)UINT8_MAX) { pInstance->errorCounter++; } - return; } static void MXM_5XTransitionToSubstate(MXM_5X_INSTANCE_s *pInstance, MXM_5X_SUBSTATES_e substate) { @@ -437,13 +436,11 @@ static void MXM_5XTransitionToSubstate(MXM_5X_INSTANCE_s *pInstance, MXM_5X_SUBS if ((pInstance->status41b == MXM_41B_STATE_PROCESSED) || (pInstance->status41b == MXM_41B_STATE_ERROR)) { pInstance->status41b = MXM_41B_STATE_UNSENT; } - return; } static void MXM_5XRepeatCurrentSubstate(MXM_5X_INSTANCE_s *pInstance) { FAS_ASSERT(pInstance != NULL_PTR); pInstance->status41b = MXM_41B_STATE_UNSENT; - return; } static void MXM_5XSignalSuccess(MXM_5X_INSTANCE_s *pInstance) { @@ -452,7 +449,6 @@ static void MXM_5XSignalSuccess(MXM_5X_INSTANCE_s *pInstance) { FAS_ASSERT(pInstance->processed != NULL_PTR); *pInstance->processed = MXM_5X_STATE_PROCESSED; pInstance->state = MXM_STATEMACH_5X_IDLE; - return; } static void MXM_5XSignalError(MXM_5X_INSTANCE_s *pInstance) { @@ -461,7 +457,6 @@ static void MXM_5XSignalError(MXM_5X_INSTANCE_s *pInstance) { FAS_ASSERT(pInstance->processed != NULL_PTR); *pInstance->processed = MXM_5X_STATE_ERROR; pInstance->state = MXM_STATEMACH_5X_IDLE; - return; } static void MXM_5XStateHandler41BFmeaCheck(MXM_5X_INSTANCE_s *pInstance5x, MXM_41B_INSTANCE_s *pInstance41b) { @@ -1049,7 +1044,7 @@ void MXM_5XStateMachine(MXM_41B_INSTANCE_s *pInstance41b, MXM_5X_INSTANCE_s *pIn switch (pInstance5x->state) { case MXM_STATEMACH_5X_UNINITIALIZED: - /* statemachine waits here for initialization */ + /* state machine waits here for initialization */ break; case MXM_STATEMACH_5X_IDLE: /* idle state currently does nothing */ diff --git a/src/app/driver/afe/maxim/common/mxm_battery_management.h b/src/app/driver/afe/maxim/common/mxm_battery_management.h index f803cb52..5e2b76fa 100644 --- a/src/app/driver/afe/maxim/common/mxm_battery_management.h +++ b/src/app/driver/afe/maxim/common/mxm_battery_management.h @@ -43,8 +43,8 @@ * @file mxm_battery_management.h * @author foxBMS Team * @date 2019-01-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * @@ -246,7 +246,7 @@ typedef struct { } MXM_5X_COMMAND_PAYLOAD_s; /** - * @brief 5x statemachine structure + * @brief 5x state machine structure **/ typedef struct { MXM_STATEMACHINE_5X_e state; /*!< state of Driver State Machine */ diff --git a/src/app/driver/afe/maxim/common/mxm_bitextract.c b/src/app/driver/afe/maxim/common/mxm_bitextract.c index 360fbc52..9fce219a 100644 --- a/src/app/driver/afe/maxim/common/mxm_bitextract.c +++ b/src/app/driver/afe/maxim/common/mxm_bitextract.c @@ -43,8 +43,8 @@ * @file mxm_bitextract.c * @author foxBMS Team * @date 2019-01-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_bitextract.h b/src/app/driver/afe/maxim/common/mxm_bitextract.h index 74ceaccb..36610337 100644 --- a/src/app/driver/afe/maxim/common/mxm_bitextract.h +++ b/src/app/driver/afe/maxim/common/mxm_bitextract.h @@ -43,8 +43,8 @@ * @file mxm_bitextract.h * @author foxBMS Team * @date 2019-01-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_crc8.c b/src/app/driver/afe/maxim/common/mxm_crc8.c index 1ffa2122..b7a2c66b 100644 --- a/src/app/driver/afe/maxim/common/mxm_crc8.c +++ b/src/app/driver/afe/maxim/common/mxm_crc8.c @@ -43,8 +43,8 @@ * @file mxm_crc8.c * @author foxBMS Team * @date 2019-02-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_crc8.h b/src/app/driver/afe/maxim/common/mxm_crc8.h index bac95d6e..32f09c26 100644 --- a/src/app/driver/afe/maxim/common/mxm_crc8.h +++ b/src/app/driver/afe/maxim/common/mxm_crc8.h @@ -43,8 +43,8 @@ * @file mxm_crc8.h * @author foxBMS Team * @date 2019-02-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_register_map.h b/src/app/driver/afe/maxim/common/mxm_register_map.h index d47c91c7..297033bf 100644 --- a/src/app/driver/afe/maxim/common/mxm_register_map.h +++ b/src/app/driver/afe/maxim/common/mxm_register_map.h @@ -43,8 +43,8 @@ * @file mxm_register_map.h * @author foxBMS Team * @date 2019-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_registry.c b/src/app/driver/afe/maxim/common/mxm_registry.c index 6d5903e9..7720e5f2 100644 --- a/src/app/driver/afe/maxim/common/mxm_registry.c +++ b/src/app/driver/afe/maxim/common/mxm_registry.c @@ -43,8 +43,8 @@ * @file mxm_registry.c * @author foxBMS Team * @date 2020-07-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/common/mxm_registry.h b/src/app/driver/afe/maxim/common/mxm_registry.h index 43b53881..1c7c589e 100644 --- a/src/app/driver/afe/maxim/common/mxm_registry.h +++ b/src/app/driver/afe/maxim/common/mxm_registry.h @@ -43,8 +43,8 @@ * @file mxm_registry.h * @author foxBMS Team * @date 2020-07-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/max17852/maxim_max17852.json b/src/app/driver/afe/maxim/max17852/maxim_max17852.json index a363a02b..8a3c28b6 100644 --- a/src/app/driver/afe/maxim/max17852/maxim_max17852.json +++ b/src/app/driver/afe/maxim/max17852/maxim_max17852.json @@ -1,5 +1,9 @@ { "include": [ + ".", + "../api/", + "../common/", + "../common/config", "../../api" ] } diff --git a/src/app/driver/afe/maxim/max17852/mxm_17852.c b/src/app/driver/afe/maxim/max17852/mxm_17852.c index 92db4ef2..df527078 100644 --- a/src/app/driver/afe/maxim/max17852/mxm_17852.c +++ b/src/app/driver/afe/maxim/max17852/mxm_17852.c @@ -43,8 +43,8 @@ * @file mxm_17852.c * @author foxBMS Team * @date 2021-11-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MXM * diff --git a/src/app/driver/afe/maxim/max17852/wscript b/src/app/driver/afe/maxim/max17852/wscript index 033b82b5..f3b9d448 100644 --- a/src/app/driver/afe/maxim/max17852/wscript +++ b/src/app/driver/afe/maxim/max17852/wscript @@ -60,11 +60,6 @@ def build(bld): os.path.join("..", "..", "api", "afe_plausibility.c"), ] includes = [ - ".", - os.path.join("..", "api"), - os.path.join("..", "common"), - os.path.join("..", "common", "config"), - os.path.join("..", "..", "api"), os.path.join("..", "..", "..", "config"), os.path.join("..", "..", "..", "foxmath"), os.path.join("..", "..", "..", "io"), @@ -79,6 +74,7 @@ def build(bld): os.path.join("..", "..", "..", "..", "engine", "diag"), os.path.join("..", "..", "..", "..", "task", "os"), ] + includes.extend(bld.env.INCLUDES_AFE) includes.extend(bld.env.INCLUDES_RTOS) cflags = bld.env.CFLAGS_FOXBMS target = f"{bld.env.APPNAME.lower()}-afe-driver" diff --git a/src/app/driver/afe/nxp/api/nxp_afe.c b/src/app/driver/afe/nxp/api/nxp_afe.c index 7bc2697e..d9d63cc9 100644 --- a/src/app/driver/afe/nxp/api/nxp_afe.c +++ b/src/app/driver/afe/nxp/api/nxp_afe.c @@ -43,8 +43,8 @@ * @file nxp_afe.c * @author foxBMS Team * @date 2020-05-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix AFE * diff --git a/src/app/driver/afe/nxp/api/nxp_afe.h b/src/app/driver/afe/nxp/api/nxp_afe.h index e5cda622..4a77d1c6 100644 --- a/src/app/driver/afe/nxp/api/nxp_afe.h +++ b/src/app/driver/afe/nxp/api/nxp_afe.h @@ -43,8 +43,8 @@ * @file nxp_afe.h * @author foxBMS Team * @date 2021-06-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix NXP * diff --git a/src/app/driver/afe/nxp/mc33775a/api/nxp_mc33775a_afe.c b/src/app/driver/afe/nxp/mc33775a/api/nxp_mc33775a_afe.c index 128129fc..fdc876ff 100644 --- a/src/app/driver/afe/nxp/mc33775a/api/nxp_mc33775a_afe.c +++ b/src/app/driver/afe/nxp/mc33775a/api/nxp_mc33775a_afe.c @@ -43,8 +43,8 @@ * @file nxp_mc33775a_afe.c * @author foxBMS Team * @date 2020-05-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix N775 * @@ -76,7 +76,7 @@ /*========== Extern Function Implementations ================================*/ extern STD_RETURN_TYPE_e NXP_Measure(void) { - N775_Meas(&n775_stateBase); + N775_Measure(&n775_stateBase); return STD_OK; } @@ -91,11 +91,6 @@ extern STD_RETURN_TYPE_e NXP_Initialize(void) { extern STD_RETURN_TYPE_e NXP_StartMeasurement(void) { STD_RETURN_TYPE_e retval = STD_NOT_OK; - - /* if (N775_SetStateRequest(N775_STATE_INITIALIZATION_REQUEST) == N775_OK) { - retval = STD_OK; - } */ - return retval; } diff --git a/src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.c b/src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.c index 423caf33..bca0fb54 100644 --- a/src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.c +++ b/src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.c @@ -43,8 +43,8 @@ * @file nxp_mc33775a_cfg.c * @author foxBMS Team * @date 2020-05-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix N775 * diff --git a/src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.h b/src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.h index 61bc4f1d..31412041 100644 --- a/src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.h +++ b/src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.h @@ -43,8 +43,8 @@ * @file nxp_mc33775a_cfg.h * @author foxBMS Team * @date 2020-05-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix N775 * @@ -134,11 +134,6 @@ */ #define N775_TRANSMISSION_TIMEOUT (10u) -/** - * N775 statemachine short time definition in ms - */ -#define N775_STATEMACH_SHORTTIME (1u) - /** * N775 Maximum time from wakeup event to possible communication in ms * 2.4ms in data sheet @@ -179,16 +174,9 @@ */ #define N775_MAX_N_BYTES_FOR_DATA_RECEPTION (N775_TX_MESSAGE_LENGTH * N775_MAX_NUMBER_OF_VOLTAGES) -/** - * Transmit functions - */ -#define N775_SendData(txbuf, rxbuf, length) SPI_TransmitReceiveDataDma(&spi_nxp775InterfaceTx[0], txbuf, rxbuf, length) - /*========== Extern Constant and Variable Declarations ======================*/ -/** - * Multiplexer measurement sequence - */ +/** Multiplexer measurement sequence */ extern N775_MUX_CH_CFG_s n775_muxSequence[N775_MUX_SEQUENCE_LENGTH]; /*========== Extern Function Prototypes =====================================*/ diff --git a/src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.c b/src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.c index 3f2b6263..81a07bf0 100644 --- a/src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.c +++ b/src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.c @@ -43,8 +43,8 @@ * @file nxp_afe_dma.c * @author foxBMS Team * @date 2020-05-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix AFE * @@ -78,6 +78,7 @@ /* Function called on DMA complete interrupts (TX and RX). */ void AFE_DmaCallback(uint8_t spiIndex) { + FAS_ASSERT((spiIndex == 0u) || (spiIndex == 3u)); if ((spiIndex == 0u)) { /* SPI 1 = Master SPI */ (void)OS_NotifyIndexedFromIsr(ftsk_taskHandleAfe, N775_NOTIFICATION_TX_INDEX, N775_TX_NOTIFIED_VALUE); @@ -87,11 +88,9 @@ void AFE_DmaCallback(uint8_t spiIndex) { /* Set slave SPI pins as GIO to deactivate them */ dma_spiInterfaces[spiIndex]->PC0 &= 0xFFFFFF00; (void)OS_NotifyIndexedFromIsr(ftsk_taskHandleAfe, N775_NOTIFICATION_RX_INDEX, N775_RX_NOTIFIED_VALUE); - } else { - FAS_ASSERT(FAS_TRAP); + } else { /* LCOV_EXCL_LINE */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ } - - return; } /*========== Externalized Static Function Implementations (Unit Test) =======*/ diff --git a/src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.h b/src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.h index bb1ea198..7a548257 100644 --- a/src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.h +++ b/src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.h @@ -43,8 +43,8 @@ * @file nxp_afe_dma.h * @author foxBMS Team * @date 2020-05-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix AFE * @@ -74,29 +74,23 @@ extern g_dmaCTRL afe_n775DmaControlPacketRx; /** * @brief gets the SPI transmit status. - * * @return retval true if transmission still ongoing, false otherwise - * */ extern bool AFE_IsTxTransmitOngoing(void); /** * @brief gets the SPI transmit status. - * * @return retval true if transmission still ongoing, false otherwise - * */ extern bool AFE_IsRxTransmitOngoing(void); /** * @brief sets the SPI transmit status. - * */ extern void AFE_SetTxTransmitOngoing(void); /** * @brief sets the SPI transmit status. - * */ extern void AFE_SetRxTransmitOngoing(void); diff --git a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.c b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.c index 107bf92d..23aa671d 100644 --- a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.c +++ b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.c @@ -20,6 +20,19 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * @file nxp_mc33775a-ll.c + * @author NXP + * @date 2022-07-29 (date of creation) + * @updated 2023-09-05 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix N775 + * + * @brief Low level driver for the MC33775A + * + */ + /*========== Includes =======================================================*/ #include "nxp_mc33775a-ll.h" @@ -183,12 +196,12 @@ extern N775_COMMUNICATION_STATUS_e N775_CommunicationRead( uint16_t deviceAddress, uint16_t registerAddress, uint16_t *pValue, - N775_STATE_s *n775_state) { + N775_STATE_s *pState) { FAS_ASSERT(pValue != NULL_PTR); - FAS_ASSERT(n775_state != NULL_PTR); - FAS_ASSERT(n775_state->pSpiTxSequence != NULL_PTR); - FAS_ASSERT(n775_state->pSpiRxSequence != NULL_PTR); - return N775_CommunicationReadMultiple(deviceAddress, 1, 1, registerAddress, pValue, n775_state); + FAS_ASSERT(pState != NULL_PTR); + FAS_ASSERT(pState->pSpiTxSequence != NULL_PTR); + FAS_ASSERT(pState->pSpiRxSequence != NULL_PTR); + return N775_CommunicationReadMultiple(deviceAddress, 1, 1, registerAddress, pValue, pState); } extern N775_COMMUNICATION_STATUS_e N775_CommunicationReadMultiple( @@ -197,11 +210,11 @@ extern N775_COMMUNICATION_STATUS_e N775_CommunicationReadMultiple( uint16_t responseLength, uint16_t registerAddress, uint16_t *pValues, - N775_STATE_s *n775_state) { + N775_STATE_s *pState) { FAS_ASSERT(pValues != NULL_PTR); - FAS_ASSERT(n775_state != NULL_PTR); - FAS_ASSERT(n775_state->pSpiTxSequence != NULL_PTR); - FAS_ASSERT(n775_state->pSpiRxSequence != NULL_PTR); + FAS_ASSERT(pState != NULL_PTR); + FAS_ASSERT(pState->pSpiTxSequence != NULL_PTR); + FAS_ASSERT(pState->pSpiRxSequence != NULL_PTR); /* Number of registers to read */ uint16_t itemsReadRemaining = numberOfItems; @@ -274,10 +287,10 @@ extern N775_COMMUNICATION_STATUS_e N775_CommunicationReadMultiple( rxBufferLength <= (N775_WRITE_SPI_BUFFER_SIZE + ((N775_READ_HEADER_SPI_BUFFER_SIZE + N775_READ_PAYLOAD_SPI_BUFFER_SIZE) * N775_MAX_ANSWER_FRAMES))); - SPI_SlaveSetReceiveDataDma(n775_state->pSpiRxSequence, n775FromTplTxBuffer, n775FromTplRxBuffer, rxBufferLength); + SPI_SlaveSetReceiveDataDma(pState->pSpiRxSequence, n775FromTplTxBuffer, n775FromTplRxBuffer, rxBufferLength); /* send message */ - SPI_TransmitReceiveDataDma(n775_state->pSpiTxSequence, n775ToTplTxBuffer, n775ToTplRxBuffer, 4u); + SPI_TransmitReceiveDataDma(pState->pSpiTxSequence, n775ToTplTxBuffer, n775ToTplRxBuffer, 4u); bool n775_rxCompleted = true; uint32_t notificationRx = N775_WaitForRxCompletedNotification(); @@ -291,8 +304,8 @@ extern N775_COMMUNICATION_STATUS_e N775_CommunicationReadMultiple( } if (n775_rxCompleted == false) { - n775_state->pSpiRxSequence->pNode->INT0 &= ~DMAREQEN_BIT; - n775_state->pSpiRxSequence->pNode->GCR1 &= ~SPIEN_BIT; + pState->pSpiRxSequence->pNode->INT0 &= ~DMAREQEN_BIT; + pState->pSpiRxSequence->pNode->GCR1 &= ~SPIEN_BIT; communicationStatus = N775_COMMUNICATION_ERROR_TIMEOUT; } else { for (uint16_t i = 0; i < nrAnswerFrames; i++) { @@ -331,7 +344,7 @@ extern N775_COMMUNICATION_STATUS_e N775_CommunicationReadMultiple( &rsp_reg_addr, &rsp_length, rsp_values, - n775_state->currentString); + pState->currentString); if (communicationStatus == N775_COMMUNICATION_OK) { /* SM.e.30 : Communication - Unique ID */ diff --git a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.h b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.h index 69d7db9d..89a163e9 100644 --- a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.h +++ b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.h @@ -20,6 +20,19 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * @file nxp_mc33775a-ll.h + * @author NXP + * @date 2022-07-29 (date of creation) + * @updated 2023-09-05 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix N775 + * + * @brief Header for the low level driver for the MC33775A + * + */ + #ifndef FOXBMS__NXP_MC33775A_LL_H_ #define FOXBMS__NXP_MC33775A_LL_H_ @@ -73,14 +86,14 @@ void N775_CommunicationWrite( * @param deviceAddress * @param registerAddress * @param pValue - * @param n775_state + * @param pState * @return returns 0 on success and >=1 in error case */ N775_COMMUNICATION_STATUS_e N775_CommunicationRead( uint16_t deviceAddress, uint16_t registerAddress, uint16_t *pValue, - N775_STATE_s *n775_state); + N775_STATE_s *pState); /** * @brief Read multiple values from specific registers in a specific device @@ -89,7 +102,7 @@ N775_COMMUNICATION_STATUS_e N775_CommunicationRead( * @param responseLength * @param registerAddress * @param pValues - * @param n775_state + * @param pState * @return returns 0 on success and >=1 in error case */ N775_COMMUNICATION_STATUS_e N775_CommunicationReadMultiple( @@ -98,7 +111,7 @@ N775_COMMUNICATION_STATUS_e N775_CommunicationReadMultiple( uint16_t responseLength, uint16_t registerAddress, uint16_t *pValues, - N775_STATE_s *n775_state); + N775_STATE_s *pState); /** * @brief Reset the message counter for one or all devices diff --git a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.c b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.c index 1d891396..50a31391 100644 --- a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.c +++ b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.c @@ -43,8 +43,8 @@ * @file nxp_mc33775a.c * @author foxBMS Team * @date 2020-05-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix N775 * @@ -58,8 +58,6 @@ #include "nxp_mc33775a-ll.h" /* clang-format on */ -#include "HL_gio.h" -#include "HL_system.h" #pragma diag_push #pragma diag_suppress 232 #include "MC33775A.h" @@ -68,11 +66,9 @@ #include "afe.h" #include "afe_dma.h" #include "database.h" -#include "diag.h" #include "fassert.h" #include "fstd_types.h" #include "ftask.h" -#include "io.h" #include "mcu.h" #include "os.h" #include "spi.h" @@ -97,7 +93,7 @@ static DATA_BLOCK_SLAVE_CONTROL_s n775_slaveControl = {.header.uniqueId = DATA_B static DATA_BLOCK_OPEN_WIRE_s n775_openWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; /**@}*/ static N775_SUPPLY_CURRENT_s n775_supplyCurrent = {0}; -static N775_ERRORTABLE_s n775_errorTable = {0}; +static N775_ERROR_TABLE_s n775_errorTable = {0}; /*========== Extern Constant and Variable Definitions =======================*/ @@ -124,369 +120,325 @@ N775_STATE_s n775_stateBase = { }; /*========== Static Function Prototypes =====================================*/ -static void N775_SetFirstMeasurementCycleFinished(N775_STATE_s *n775_state); -static void N775_InitializeDatabase(N775_STATE_s *n775_state); -static void N775_ResetStringSequence(N775_STATE_s *n775_state); -static void N775_IncrementStringSequence(N775_STATE_s *n775_state); -static void N775_ResetMuxIndex(N775_STATE_s *n775_state); -static void N775_IncrementMuxIndex(N775_STATE_s *n775_state); -static void N775_ErrorHandling(N775_STATE_s *n775_state, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module); -static void N775_Init(N775_STATE_s *n775_state); -static STD_RETURN_TYPE_e N775_Enumerate(N775_STATE_s *n775_state); -static void N775_I2cInit(N775_STATE_s *n775_state); -static void N775_StartMeasurement(N775_STATE_s *n775_state); -static void N775_CaptureMeasurement(N775_STATE_s *n775_state); -static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state); -static STD_RETURN_TYPE_e N775_SetMuxChannel(N775_STATE_s *n775_state); -static void N775_BalanceSetup(N775_STATE_s *n775_state); -static void N775_BalanceControl(N775_STATE_s *n775_state); -static void N775_waitTime(uint32_t milliseconds); - -/*========== Static Function Implementations ================================*/ +/** + * @brief manages balancing. + * @details Reads balancing order from database and balances the corresponding + * cells. + * @param pState state of the NXP MC33775A driver + */ +static void N775_BalanceControl(N775_STATE_s *pState); -/*========== Extern Function Implementations ================================*/ +/** + * @brief setups balancing. + * @details Sets all balancing timer to max to allow for software balancing + * control. + * @param pState state of the NXP MC33775A driver + */ +static void N775_BalanceSetup(N775_STATE_s *pState); /** - * @brief in the database, initializes the fields related to the N775 driver. - * - * This function loops through all the N775-related data fields in the database - * and sets them to 0. It should be called in the initialization or re-initialization - * routine of the N775 driver. - * - * @param n775_state state of the N775A driver - * + * @brief captures the measurement. + * @details The MC33775A measures continuously. + * This function takes a snapshot on all slaves in the daisy-chain. + * @param pState state of the NXP MC33775A driver */ -static void N775_InitializeDatabase(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); - uint16_t iterator = 0; +static void N775_CaptureMeasurement(N775_STATE_s *pState); - for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) { - n775_state->n775Data.cellVoltage->state = 0; - n775_state->n775Data.minMax->minimumCellVoltage_mV[stringNumber] = 0; - n775_state->n775Data.minMax->maximumCellVoltage_mV[stringNumber] = 0; - n775_state->n775Data.minMax->nrModuleMinimumCellVoltage[stringNumber] = 0; - n775_state->n775Data.minMax->nrModuleMaximumCellVoltage[stringNumber] = 0; - n775_state->n775Data.minMax->nrCellMinimumCellVoltage[stringNumber] = 0; - n775_state->n775Data.minMax->nrCellMaximumCellVoltage[stringNumber] = 0; - for (iterator = 0u; iterator < BS_NR_OF_CELL_BLOCKS_PER_STRING; iterator++) { - n775_state->n775Data.cellVoltage->cellVoltage_mV[stringNumber][iterator] = 0; - } +/** + * @brief enumerates the N775 slaves. + * @details This function gives the slaves in the daisy-chain an address. + * @param pState state of the NXP MC33775A driver + */ +static STD_RETURN_TYPE_e N775_Enumerate(N775_STATE_s *pState); +/** + * @brief handles error when doing measurements. + * @details This function is used in the measurement function. + * It sets the errors flags in the error table according to the value + * returned by the communication function. + * @param pState state of the NXP MC33775A driver + * @param returnedValue status of the low-level communication + * @param module number of module addressed + */ +static void N775_ErrorHandling(N775_STATE_s *pState, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module); - n775_state->n775Data.cellTemperature->state = 0; - n775_state->n775Data.minMax->minimumTemperature_ddegC[stringNumber] = 0; - n775_state->n775Data.minMax->maximumTemperature_ddegC[stringNumber] = 0; - n775_state->n775Data.minMax->nrModuleMinimumTemperature[stringNumber] = 0; - n775_state->n775Data.minMax->nrModuleMaximumTemperature[stringNumber] = 0; - n775_state->n775Data.minMax->nrSensorMinimumTemperature[stringNumber] = 0; - n775_state->n775Data.minMax->nrSensorMaximumTemperature[stringNumber] = 0; - for (iterator = 0u; iterator < BS_NR_OF_TEMP_SENSORS_PER_STRING; iterator++) { - n775_state->n775Data.cellTemperature->cellTemperature_ddegC[stringNumber][iterator] = 0; - } +/** + * @brief updates index in mux sequence. + * @param pState state of the NXP MC33775A driver + */ +static void N775_IncrementMuxIndex(N775_STATE_s *pState); - for (iterator = 0u; iterator < BS_NR_OF_CELL_BLOCKS_PER_STRING; iterator++) { - n775_state->n775Data.balancingControl->balancingState[stringNumber][iterator] = 0; - } - for (iterator = 0u; iterator < BS_NR_OF_MODULES_PER_STRING; iterator++) { - n775_state->n775Data.errorTable->communicationOk[stringNumber][iterator] = false; - n775_state->n775Data.errorTable->noCommunicationTimeout[stringNumber][iterator] = false; - n775_state->n775Data.errorTable->crcIsValid[stringNumber][iterator] = false; - n775_state->n775Data.errorTable->mux0IsOk[stringNumber][iterator] = false; - n775_state->n775Data.errorTable->mux1IsOK[stringNumber][iterator] = false; - n775_state->n775Data.errorTable->mux2IsOK[stringNumber][iterator] = false; - n775_state->n775Data.errorTable->mux3IsOK[stringNumber][iterator] = false; - } - for (iterator = 0u; iterator < BS_NR_OF_MODULES_PER_STRING; iterator++) { - n775_state->n775Data.uid[stringNumber][iterator] = 0; - } - } +/** + * @brief increments index in string sequence. + * @param pState state of the NXP MC33775A driver + */ +static void N775_IncrementStringSequence(N775_STATE_s *pState); - DATA_WRITE_DATA(n775_state->n775Data.cellVoltage); - DATA_WRITE_DATA(n775_state->n775Data.cellTemperature); - DATA_WRITE_DATA(n775_state->n775Data.minMax); - DATA_WRITE_DATA(n775_state->n775Data.balancingControl); -} +/** + * @brief initializes the N775 driver. + * @details This function enumerates the slaves and starts the measurement. + * @param pState state of the NXP MC33775A driver + */ +static void N775_Initialize(N775_STATE_s *pState); -void N775_Meas(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); +/** + * @brief in the database, initializes the fields related to the N775 driver. + * @details This function loops through all the N775-related data fields in the + * database and sets them to 0. + * It shall be called in the initialization or re-initialization + * routine of the N775 driver. + * @param pState state of the NXP MC33775A driver + * + */ +static void N775_InitializeDatabase(N775_STATE_s *pState); - N775_InitializeDatabase(n775_state); - /* Initialize SPI sequence pointers */ - n775_state->pSpiTxSequenceStart = spi_nxp775InterfaceTx; - n775_state->pSpiRxSequenceStart = spi_nxp775InterfaceRx; +/** + * @brief init I2C for the N775 slaves. + * @details This function makes slaves ready for I2C transactions with on-slave + * devices. + * @param pState state of the NXP MC33775A driver + */ +static void N775_InitializeI2c(N775_STATE_s *pState); - /* Initialize each string */ - N775_ResetStringSequence(n775_state); - while (n775_state->currentString < BS_NR_OF_STRINGS) { - /* Initialize mux sequence pointers */ - n775_state->pMuxSequenceStart[n775_state->currentString] = n775_muxSequence; - N775_Init(n775_state); - N775_IncrementStringSequence(n775_state); - } +/** + * @brief reset index in string sequence. + * @param pState state of the NXP MC33775A driver + */ +static void N775_ResetStringSequence(N775_STATE_s *pState); - while (1) { - N775_ResetStringSequence(n775_state); +/** + * @brief resets index in mux sequence. + * @param pState state of the NXP MC33775A driver + */ +static void N775_ResetMuxIndex(N775_STATE_s *pState); - while (n775_state->currentString < BS_NR_OF_STRINGS) { - if (N775_USE_MUX_FOR_TEMP == true) { - /* Set mux channel according to mux sequence */ - N775_SetMuxChannel(n775_state); - } - N775_CaptureMeasurement(n775_state); - if (N775_USE_MUX_FOR_TEMP == true) { - /* Update index in mux sequence */ - N775_IncrementMuxIndex(n775_state); - } - N775_BalanceControl(n775_state); +/** + * @brief sets the measurement initialization status. + * @param pState state of the NXP MC33775A driver + */ +static void N775_SetFirstMeasurementCycleFinished(N775_STATE_s *pState); - N775_TransmitI2c(n775_state); +/** + * @brief sets mux channel. + * @details This function uses I2C to set the mux channel. + * @param pState state of the NXP MC33775A driver + */ +static STD_RETURN_TYPE_e N775_SetMuxChannel(N775_STATE_s *pState); - for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - if (N775_IsFirstMeasurementCycleFinished(n775_state) == true) { - if (n775_state->n775Data.errorTable->noCommunicationTimeout[n775_state->currentString][m] == 0u) { - /* Daisy-chain does not answer: initialize it again */ - n775_state->pMuxSequenceStart[n775_state->currentString] = n775_muxSequence; - N775_Init(n775_state); - /* Daisy-chain re-initialized: no need to check further slaves */ - break; - } - } - } +/** + * @brief starts the measurement. + * @details The MC33775A measures continuously. + * This function starts the measurement. + * @param pState state of the NXP MC33775A driver + */ +static void N775_StartMeasurement(N775_STATE_s *pState); - N775_IncrementStringSequence(n775_state); - } +/** + * @brief transmit over I2C on NXP slave. + * @param pState state of the NXP MC33775A driver + */ +static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *pState); - /* Set flag when all strings have been measured */ - if ((n775_state->currentString == BS_NR_OF_STRINGS) && - (N775_IsFirstMeasurementCycleFinished(n775_state) == 0u)) { - N775_SetFirstMeasurementCycleFinished(n775_state); - } - } -} +/** + * @brief waits for a definite amount of time in ms. + * @details This function uses FreeRTOS. It blocks the tasks for the given + * amount of milliseconds. + * @param milliseconds time to wait in ms + */ +static void N775_Wait(uint32_t milliseconds); -STD_RETURN_TYPE_e N775_I2cWrite(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength) { - FAS_ASSERT(pData != NULL_PTR); - FAS_ASSERT((dataLength > 0u) && (dataLength <= 13u)); - STD_RETURN_TYPE_e retVal = STD_NOT_OK; - AFE_I2C_QUEUE_s transactionData; +/*========== Static Function Implementations ================================*/ - transactionData.module = module; - transactionData.deviceAddress = deviceAddress; - transactionData.writeDataLength = dataLength; - transactionData.transferType = AFE_I2C_TRANSFER_TYPE_WRITE; - for (uint8_t i = 0u; i < dataLength; i++) { - transactionData.writeData[i] = pData[i]; - } - if (OS_SendToBackOfQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) { - /* queue is not full */ - /* wating for transfer to finish */ - if (OS_ReceiveFromQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, N775_I2C_FINISHED_TIMEOUT_ms) == - OS_SUCCESS) { - if (transactionData.transferType == AFE_I2C_TRANSFER_TYPE_WRITE_SUCCESS) { - retVal = STD_OK; - } - } - } else { - /* queue is full */ - } +static void N775_BalanceControl(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); - return retVal; -} + N775_BalanceSetup(pState); -STD_RETURN_TYPE_e N775_I2cWriteRead( - uint8_t module, - uint8_t deviceAddress, - uint8_t *pDataWrite, - uint8_t writeDataLength, - uint8_t *pDataRead, - uint8_t readDataLength) { - FAS_ASSERT(pDataWrite != NULL_PTR); - FAS_ASSERT(pDataRead != NULL_PTR); - FAS_ASSERT(writeDataLength > 0u); - FAS_ASSERT(readDataLength > 0u); - FAS_ASSERT((uint16_t)(writeDataLength + readDataLength) <= 12u); - STD_RETURN_TYPE_e retVal = STD_NOT_OK; - AFE_I2C_QUEUE_s transactionData; + DATA_READ_DATA(pState->n775Data.balancingControl); - transactionData.module = module; - transactionData.deviceAddress = deviceAddress; - transactionData.writeDataLength = writeDataLength; - transactionData.readDataLength = readDataLength; - transactionData.transferType = AFE_I2C_TRANSFER_TYPE_WRITEREAD; - for (uint8_t i = 0u; i < writeDataLength; i++) { - transactionData.writeData[i] = pDataWrite[i]; - } - if (OS_SendToBackOfQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) { - /* queue is not full */ - /* wating for transfer to finish */ - if (OS_ReceiveFromQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, N775_I2C_FINISHED_TIMEOUT_ms) == - OS_SUCCESS) { - if (transactionData.transferType == AFE_I2C_TRANSFER_TYPE_READ_SUCCESS) { - for (uint8_t i = 0u; i < readDataLength; i++) { - pDataRead[i] = transactionData.readData[i]; - } - retVal = STD_OK; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + uint8_t deviceAddress = m + 1u; + uint16_t balancingState = 0u; + for (uint16_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { + if (pState->n775Data.balancingControl + ->balancingState[pState->currentString][c + (m * BS_NR_OF_CELL_BLOCKS_PER_MODULE)] != 0u) { + balancingState |= 1u << c; } } - } else { - /* queue is full */ + /* All channels active --> 14 bits set to 1 --> 0x3FFF */ + FAS_ASSERT(balancingState <= 0x3FFFu); + /* Enable channels, one written to a channels means balancing active */ + N775_CommunicationWrite(deviceAddress, MC33775_BAL_CH_CFG_OFFSET, balancingState, pState->pSpiTxSequence); } - - return retVal; } -STD_RETURN_TYPE_e N775_I2cRead(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength) { - FAS_ASSERT(pData != NULL_PTR); - FAS_ASSERT((dataLength > 0u) && (dataLength <= 13u)); - STD_RETURN_TYPE_e retVal = STD_NOT_OK; - AFE_I2C_QUEUE_s transactionData; +static void N775_BalanceSetup(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); - transactionData.module = module; - transactionData.deviceAddress = deviceAddress; - transactionData.readDataLength = dataLength; - transactionData.transferType = AFE_I2C_TRANSFER_TYPE_READ; - if (OS_SendToBackOfQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) { - /* queue is not full */ - /* wating for transfer to finish */ - if (OS_ReceiveFromQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, N775_I2C_FINISHED_TIMEOUT_ms) == - OS_SUCCESS) { - if (transactionData.transferType == AFE_I2C_TRANSFER_TYPE_READ_SUCCESS) { - for (uint8_t i = 0u; i < dataLength; i++) { - pData[i] = transactionData.readData[i]; - } - retVal = STD_OK; - } - } - } else { - /* queue is full */ - } + /* Set global timeout counter to max value */ + N775_CommunicationWrite( + N775_BROADCAST_ADDRESS, MC33775_BAL_GLOB_TO_TMR_OFFSET, N775_GLOBAL_BALANCING_TIMER, pState->pSpiTxSequence); - return retVal; -} + /* Disable pre-balancing timer by setting it to zero */ + N775_CommunicationWrite( + N775_BROADCAST_ADDRESS, MC33775_BAL_PRE_TMR_OFFSET, N775_PRE_BALANCING_TIMER, pState->pSpiTxSequence); -/** - * @brief reset index in string sequence. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_ResetStringSequence(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); + /* Set PWM value for all channels to 100%, set balancing timer for all channels to maximum value */ + N775_CommunicationWrite( + N775_BROADCAST_ADDRESS, + MC33775_BAL_TMR_CH_ALL_OFFSET, + (MC33775_BAL_TMR_CH_ALL_PWM_PWM100_ENUM_VAL << MC33775_BAL_TMR_CH_ALL_PWM_POS) | + (N775_ALL_CHANNEL_BALANCING_TIMER << MC33775_BAL_TMR_CH_ALL_BALTIME_POS), + pState->pSpiTxSequence); - n775_state->currentString = 0u; - n775_state->pSpiTxSequence = n775_state->pSpiTxSequenceStart + n775_state->currentString; - n775_state->pSpiRxSequence = n775_state->pSpiRxSequenceStart + n775_state->currentString; + /* Select timer based balancing and enable balancing */ + N775_CommunicationWrite( + N775_BROADCAST_ADDRESS, + MC33775_BAL_GLOB_CFG_OFFSET, + (MC33775_BAL_GLOB_CFG_BALEN_ENABLED_ENUM_VAL << MC33775_BAL_GLOB_CFG_BALEN_POS) | + (MC33775_BAL_GLOB_CFG_TMRBALEN_STOP_ENUM_VAL << MC33775_BAL_GLOB_CFG_TMRBALEN_POS), + pState->pSpiTxSequence); } -/** - * @brief updates index in string sequence. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_IncrementStringSequence(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); +static void N775_CaptureMeasurement(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); - n775_state->currentString++; - n775_state->pSpiTxSequence = n775_state->pSpiTxSequenceStart + n775_state->currentString; - n775_state->pSpiRxSequence = n775_state->pSpiRxSequenceStart + n775_state->currentString; -} + uint16_t primaryRawValues[20] = {0u}; + uint16_t secondaryRawValues[4] = {0u}; + uint16_t currentRawValue = 0u; + int16_t primaryValues[20] = {0u}; + int16_t secondaryValues[4] = {0u}; + int16_t currentValue = 0u; + N775_COMMUNICATION_STATUS_e retValPrimary = N775_COMMUNICATION_OK; + N775_COMMUNICATION_STATUS_e retValSecondary = N775_COMMUNICATION_OK; + N775_COMMUNICATION_STATUS_e retValSupplyCurrent = N775_COMMUNICATION_OK; + uint16_t error = 0u; + bool gpio03Error = false; + bool gpio47Error = false; -/** - * @brief resets index in mux sequence. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_ResetMuxIndex(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); + /* Send capture command. This ends the last cycle and starts a new one */ + N775_CommunicationWrite( + N775_BROADCAST_ADDRESS, + MC33775_ALLM_APP_CTRL_OFFSET, + (1u << MC33775_ALLM_APP_CTRL_PAUSEBAL_POS) | (0x3FFu << MC33775_PRMM_APP_CTRL_CAPVC_POS) | + (MC33775_PRMM_APP_CTRL_VCOLNUM_DISABLED_ENUM_VAL << MC33775_PRMM_APP_CTRL_VCOLNUM_POS), + pState->pSpiTxSequence); + /* Wait for measurements to take place */ + N775_Wait(N775_MEASUREMENT_CAPTURE_TIME_MS); + /* Send capture command. This ends the last cycle and starts a new one */ + N775_CommunicationWrite( + N775_BROADCAST_ADDRESS, + MC33775_ALLM_APP_CTRL_OFFSET, + (0u << MC33775_ALLM_APP_CTRL_PAUSEBAL_POS) | (0x3FFu << MC33775_PRMM_APP_CTRL_CAPVC_POS) | + (MC33775_PRMM_APP_CTRL_VCOLNUM_DISABLED_ENUM_VAL << MC33775_PRMM_APP_CTRL_VCOLNUM_POS), + pState->pSpiTxSequence); + /* Wait for measurements to be ready */ + N775_Wait(N775_MEASUREMENT_READY_TIME_MS); - n775_state->currentMux[n775_state->currentString] = 0u; - n775_state->pMuxSequence[n775_state->currentString] = n775_state->pMuxSequenceStart[n775_state->currentString]; -} + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + uint8_t deviceAddress = m + 1u; + retValPrimary = N775_CommunicationReadMultiple( + deviceAddress, 20, 4u, MC33775_PRMM_APP_VC_CNT_OFFSET, primaryRawValues, pState); + retValSecondary = N775_CommunicationReadMultiple( + deviceAddress, 4, 4u, MC33775_SECM_APP_AIN4_OFFSET, secondaryRawValues, pState); + if (N775_CHECK_SUPPLY_CURRENT == true) { + retValSupplyCurrent = + N775_CommunicationRead(deviceAddress, MC33775_SECM_PER_NPNISENSE_OFFSET, ¤tRawValue, pState); + } -/** - * @brief updates index in mux sequence. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_IncrementMuxIndex(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); + N775_ErrorHandling(pState, retValPrimary, m); + if (retValPrimary == N775_COMMUNICATION_OK) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + /* Store cell voltages */ + if (N775_INVALID_REGISTER_VALUE != primaryRawValues[cb + 1u]) { + primaryValues[cb + 1u] = (int16_t)primaryRawValues[cb + 1u]; + pState->n775Data.cellVoltage->cellVoltage_mV[pState->currentString][m][cb] = + (((float_t)primaryValues[cb + 1u]) * 154.0e-6f * 1000.0f); + } else { + error++; + } + } + for (uint8_t g = 0u; g < 4u; g++) { + /* Store GPIO voltages */ + if (N775_INVALID_REGISTER_VALUE != primaryRawValues[g + 16u]) { + primaryValues[g + 16u] = (int16_t)primaryRawValues[g + 16u]; + pState->n775Data.allGpioVoltage + ->gpioVoltages_mV[pState->currentString][g + (m * BS_NR_OF_GPIOS_PER_MODULE)] = + (((float_t)primaryValues[g + 16u]) * 154.0e-6f * 1000.0f); + } else { + gpio03Error = true; + error++; + } + } + /* Store module voltage */ + if (N775_INVALID_REGISTER_VALUE != primaryRawValues[15u]) { + primaryValues[15u] = (int16_t)primaryRawValues[15u]; + pState->n775Data.cellVoltage->moduleVoltage_mV[pState->currentString][m] = + (((float_t)primaryValues[15u]) * 2.58e-3f * 1000.0f); + } else { + error++; + } + } - n775_state->currentMux[n775_state->currentString]++; - if (n775_state->currentMux[n775_state->currentString] >= N775_MUX_SEQUENCE_LENGTH) { - n775_state->currentMux[n775_state->currentString] = 0u; - } - n775_state->pMuxSequence[n775_state->currentString] = n775_state->pMuxSequenceStart[n775_state->currentString] + - n775_state->currentMux[n775_state->currentString]; -} + N775_ErrorHandling(pState, retValSecondary, m); + if (retValSecondary == N775_COMMUNICATION_OK) { + for (uint8_t g = 4u; g < 8u; g++) { + if (N775_INVALID_REGISTER_VALUE != secondaryRawValues[g - 4u]) { + secondaryValues[g - 4u] = (int16_t)secondaryRawValues[g - 4u]; + pState->n775Data.allGpioVoltage + ->gpioVoltages_mV[pState->currentString][g + (m * BS_NR_OF_GPIOS_PER_MODULE)] = + (((float_t)secondaryValues[g - 4u]) * 154.0e-6f * 1000.0f); + } else { + gpio47Error = true; + error++; + } + } + } -/** - * @brief handles error when doing measurements. - * - * This function is used in the measurement function. It sets the errors flags in - * the error table according to the value returned by the communication function. - * - * @param n775_state state of the N775A driver - * @param returnedValue status of the low-level communication - * @param module number of module addressed - * - */ -static void N775_ErrorHandling(N775_STATE_s *n775_state, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module) { - FAS_ASSERT(n775_state != NULL_PTR); + /* Set temperature values */ + if (N775_USE_MUX_FOR_TEMP == true) { + /* Mux case */ + if (gpio03Error == false) { + pState->n775Data.cellTemperature + ->cellTemperature_ddegC[pState->currentString][m][pState->currentMux[pState->currentString]] = + N775_ConvertVoltagesToTemperatures( + pState->n775Data.allGpioVoltage + ->gpioVoltages_mV[pState->currentString] + [N775_MUXED_TEMP_GPIO_POSITION + (m * BS_NR_OF_GPIOS_PER_MODULE)]); + } + } else if (N775_USE_MUX_FOR_TEMP == false) { + /* No mux case */ + if ((gpio03Error == false) && (gpio47Error == false)) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { + pState->n775Data.cellTemperature->cellTemperature_ddegC[pState->currentString][m][ts] = + N775_ConvertVoltagesToTemperatures( + pState->n775Data.allGpioVoltage + ->gpioVoltages_mV[pState->currentString][ts + (m * BS_NR_OF_GPIOS_PER_MODULE)]); + } + } + } else { + /* Invalid value for switch case */ + FAS_ASSERT(FAS_TRAP); + } - if (returnedValue == N775_COMMUNICATION_OK) { - n775_state->n775Data.errorTable->communicationOk[n775_state->currentString][module] = true; - n775_state->n775Data.errorTable->noCommunicationTimeout[n775_state->currentString][module] = true; - n775_state->n775Data.errorTable->crcIsValid[n775_state->currentString][module] = true; - } else { - n775_state->n775Data.errorTable->communicationOk[n775_state->currentString][module] = false; - switch (returnedValue) { - case N775_COMMUNICATION_ERROR_TIMEOUT: - n775_state->n775Data.errorTable->noCommunicationTimeout[n775_state->currentString][module] = false; - break; - case N775_COMMUNICATION_ERROR_WRONG_CRC: - n775_state->n775Data.errorTable->crcIsValid[n775_state->currentString][module] = false; - break; - default: - n775_state->n775Data.errorTable->communicationOk[n775_state->currentString][module] = false; - break; + if (N775_CHECK_SUPPLY_CURRENT == true) { + N775_ErrorHandling(pState, retValSupplyCurrent, m); + if (retValSupplyCurrent == N775_COMMUNICATION_OK) { + if (N775_INVALID_REGISTER_VALUE != currentRawValue) { + currentValue = (int16_t)currentRawValue; + pState->n775Data.supplyCurrent->current[pState->currentString][m] = + (((float_t)currentValue) * 7.69e-6f * 1000.0f); + } else { + error++; + } + } } } -} - -/** - * @brief initializes the N775 driver. - * - * This function enumerates the slaves and starts the measurement. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_Init(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); - - /* Reset mux sequence */ - N775_ResetMuxIndex(n775_state); - /* Initialize daisy-chain */ - if (STD_OK != N775_Enumerate(n775_state)) { - /* error handling */} - N775_StartMeasurement(n775_state); - N775_I2cInit(n775_state); - N775_BalanceSetup(n775_state); + DATA_WRITE_DATA(pState->n775Data.cellVoltage, pState->n775Data.cellTemperature, pState->n775Data.allGpioVoltage); } -/** - * @brief enumerates the N775 slaves. - * - * This function gives the slaves in the daisy-chain an address. - * - * @param n775_state state of the N775A driver - * - */ -static STD_RETURN_TYPE_e N775_Enumerate(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); +static STD_RETURN_TYPE_e N775_Enumerate(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); uint16_t readValue = 0u; uint16_t uid[3u] = {0}; N775_COMMUNICATION_STATUS_e returnedValue = N775_COMMUNICATION_OK; @@ -499,17 +451,17 @@ static STD_RETURN_TYPE_e N775_Enumerate(N775_STATE_s *n775_state) { i, MC33775_SYS_MODE_OFFSET, (MC33775_SYS_MODE_TARGETMODE_DEEPSLEEP_ENUM_VAL << MC33775_SYS_MODE_TARGETMODE_POS), - n775_state->pSpiTxSequence); - N775_waitTime(1u); + pState->pSpiTxSequence); + N775_Wait(1u); /* Wake up slave */ - returnedValue = N775_CommunicationRead(i, MC33775_SYS_COM_CFG_OFFSET, &readValue, n775_state); + returnedValue = N775_CommunicationRead(i, MC33775_SYS_COM_CFG_OFFSET, &readValue, pState); /* If slave is not enumerated */ if (returnedValue != N775_COMMUNICATION_OK) { /* Wait until the slave has woken up */ - N775_waitTime(N775_WAKEUP_TIME_MS); + N775_Wait(N775_WAKEUP_TIME_MS); - returnedValue = N775_CommunicationRead(i, MC33775_SYS_COM_CFG_OFFSET, &readValue, n775_state); + returnedValue = N775_CommunicationRead(i, MC33775_SYS_COM_CFG_OFFSET, &readValue, pState); /* If slave is not enumerated */ if (returnedValue != N775_COMMUNICATION_OK) { /* Enumerate slave */ @@ -518,13 +470,13 @@ static STD_RETURN_TYPE_e N775_Enumerate(N775_STATE_s *n775_state) { MC33775_SYS_COM_CFG_OFFSET, i + (N775_DEFAULT_CHAIN_ADDRESS << 6) + (MC33775_SYS_COM_CFG_BUSFW_ENABLED_ENUM_VAL << MC33775_SYS_COM_CFG_BUSFW_POS), - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); } /* Reset the message counter of the driver */ - N775_ResetMessageCounter((N775_DEFAULT_CHAIN_ADDRESS << 6) + i, n775_state->currentString); + N775_ResetMessageCounter((N775_DEFAULT_CHAIN_ADDRESS << 6) + i, pState->currentString); /* Check that the device has been enumerated */ - returnedValue = N775_CommunicationRead(i, MC33775_SYS_VERSION_OFFSET, &readValue, n775_state); + returnedValue = N775_CommunicationRead(i, MC33775_SYS_VERSION_OFFSET, &readValue, pState); if (returnedValue == N775_COMMUNICATION_OK) { retVal = STD_OK; } @@ -539,31 +491,134 @@ static STD_RETURN_TYPE_e N775_Enumerate(N775_STATE_s *n775_state) { MC33775_SYS_COM_TO_CFG_OFFSET, (N775_TIMEOUT_SWITCH << MC33775_SYS_COM_TO_CFG_COMTODISABLE_POS) | (N775_TIMEOUT_TO_SLEEP_10MS << MC33775_SYS_COM_TO_CFG_COMTO_POS), - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); + + /* read uid of each device */ + returnedValue = N775_CommunicationReadMultiple(i, 3u, 3u, MC33775_SYS_UID_LOW_OFFSET, uid, pState); + if (returnedValue == N775_COMMUNICATION_OK) { + pState->n775Data.uid[pState->currentString][i - 1u] = 0u; + for (uint8_t j = 0u; j <= 3u; j++) { + pState->n775Data.uid[pState->currentString][i - 1u] |= ((uint64_t)uid[j]) << (16u * j); + } + } + } + + return retVal; +} + +static void N775_ErrorHandling(N775_STATE_s *pState, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module) { + FAS_ASSERT(pState != NULL_PTR); + + if (returnedValue == N775_COMMUNICATION_OK) { + pState->n775Data.errorTable->communicationOk[pState->currentString][module] = true; + pState->n775Data.errorTable->noCommunicationTimeout[pState->currentString][module] = true; + pState->n775Data.errorTable->crcIsValid[pState->currentString][module] = true; + } else { + pState->n775Data.errorTable->communicationOk[pState->currentString][module] = false; + switch (returnedValue) { + case N775_COMMUNICATION_ERROR_TIMEOUT: + pState->n775Data.errorTable->noCommunicationTimeout[pState->currentString][module] = false; + break; + case N775_COMMUNICATION_ERROR_WRONG_CRC: + pState->n775Data.errorTable->crcIsValid[pState->currentString][module] = false; + break; + default: + pState->n775Data.errorTable->communicationOk[pState->currentString][module] = false; + break; + } + } +} + +static void N775_IncrementMuxIndex(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); + + pState->currentMux[pState->currentString]++; + if (pState->currentMux[pState->currentString] >= N775_MUX_SEQUENCE_LENGTH) { + pState->currentMux[pState->currentString] = 0u; + } + pState->pMuxSequence[pState->currentString] = pState->pMuxSequenceStart[pState->currentString] + + pState->currentMux[pState->currentString]; +} + +static void N775_IncrementStringSequence(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); + + pState->currentString++; + pState->pSpiTxSequence = pState->pSpiTxSequenceStart + pState->currentString; + pState->pSpiRxSequence = pState->pSpiRxSequenceStart + pState->currentString; +} + +static void N775_Initialize(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); + + /* Reset mux sequence */ + N775_ResetMuxIndex(pState); + + /* Initialize daisy-chain */ + if (STD_OK != N775_Enumerate(pState)) { + /* error handling */} + N775_StartMeasurement(pState); + N775_InitializeI2c(pState); + N775_BalanceSetup(pState); +} + +static void N775_InitializeDatabase(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); + uint16_t iterator = 0; - /* read uid of each device */ - returnedValue = N775_CommunicationReadMultiple(i, 3u, 3u, MC33775_SYS_UID_LOW_OFFSET, uid, n775_state); - if (returnedValue == N775_COMMUNICATION_OK) { - n775_state->n775Data.uid[n775_state->currentString][i - 1u] = 0u; - for (uint8_t j = 0u; j <= 3u; j++) { - n775_state->n775Data.uid[n775_state->currentString][i - 1u] |= ((uint64_t)uid[j]) << (16u * j); + for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) { + pState->n775Data.cellVoltage->state = 0; + pState->n775Data.minMax->minimumCellVoltage_mV[stringNumber] = 0; + pState->n775Data.minMax->maximumCellVoltage_mV[stringNumber] = 0; + pState->n775Data.minMax->nrModuleMinimumCellVoltage[stringNumber] = 0; + pState->n775Data.minMax->nrModuleMaximumCellVoltage[stringNumber] = 0; + pState->n775Data.minMax->nrCellMinimumCellVoltage[stringNumber] = 0; + pState->n775Data.minMax->nrCellMaximumCellVoltage[stringNumber] = 0; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_STRING; cb++) { + pState->n775Data.cellVoltage->cellVoltage_mV[stringNumber][m][cb] = 0; } } + + pState->n775Data.cellTemperature->state = 0; + pState->n775Data.minMax->minimumTemperature_ddegC[stringNumber] = 0; + pState->n775Data.minMax->maximumTemperature_ddegC[stringNumber] = 0; + pState->n775Data.minMax->nrModuleMinimumTemperature[stringNumber] = 0; + pState->n775Data.minMax->nrModuleMaximumTemperature[stringNumber] = 0; + pState->n775Data.minMax->nrSensorMinimumTemperature[stringNumber] = 0; + pState->n775Data.minMax->nrSensorMaximumTemperature[stringNumber] = 0; + + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { + pState->n775Data.cellTemperature->cellTemperature_ddegC[stringNumber][m][ts] = 0; + } + } + + for (iterator = 0u; iterator < BS_NR_OF_CELL_BLOCKS_PER_STRING; iterator++) { + pState->n775Data.balancingControl->balancingState[stringNumber][iterator] = 0; + } + for (iterator = 0u; iterator < BS_NR_OF_MODULES_PER_STRING; iterator++) { + pState->n775Data.errorTable->communicationOk[stringNumber][iterator] = false; + pState->n775Data.errorTable->noCommunicationTimeout[stringNumber][iterator] = false; + pState->n775Data.errorTable->crcIsValid[stringNumber][iterator] = false; + pState->n775Data.errorTable->mux0IsOk[stringNumber][iterator] = false; + pState->n775Data.errorTable->mux1IsOK[stringNumber][iterator] = false; + pState->n775Data.errorTable->mux2IsOK[stringNumber][iterator] = false; + pState->n775Data.errorTable->mux3IsOK[stringNumber][iterator] = false; + } + for (iterator = 0u; iterator < BS_NR_OF_MODULES_PER_STRING; iterator++) { + pState->n775Data.uid[stringNumber][iterator] = 0; + } } - return retVal; + DATA_WRITE_DATA(pState->n775Data.cellVoltage); + DATA_WRITE_DATA(pState->n775Data.cellTemperature); + DATA_WRITE_DATA(pState->n775Data.minMax); + DATA_WRITE_DATA(pState->n775Data.balancingControl); } -/** - * @brief init I2C for the N775 slaves. - * - * This function makes slaves ready for I2C transactions with on-slave devices. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_I2cInit(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); +static void N775_InitializeI2c(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); /* Enable the I2C module and select 400 kHz */ N775_CommunicationWrite( @@ -571,197 +626,153 @@ static void N775_I2cInit(N775_STATE_s *n775_state) { MC33775_I2C_CFG_OFFSET, (MC33775_I2C_CFG_EN_ENABLED_ENUM_VAL << MC33775_I2C_CFG_EN_POS) + (MC33775_I2C_CFG_CLKSEL_F_400K_ENUM_VAL << MC33775_I2C_CFG_CLKSEL_POS), - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); } -/** - * @brief starts the measurement. - * - * The MC33775A measures continuously. This function - * starts the measurement. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_StartMeasurement(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); +static void N775_ResetStringSequence(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); - /* Enable cell voltage measurements */ - N775_CommunicationWrite(N775_BROADCAST_ADDRESS, MC33775_ALLM_VCVB_CFG_OFFSET, 0x3FFF, n775_state->pSpiTxSequence); - /* Enable analog inputs 0-3 and module voltage measurement */ - N775_CommunicationWrite(N775_BROADCAST_ADDRESS, MC33775_PRMM_AIN_CFG_OFFSET, 0x1F, n775_state->pSpiTxSequence); - /* Enable analog inputs 4-7 measurement */ - N775_CommunicationWrite(N775_BROADCAST_ADDRESS, MC33775_SECM_AIN_CFG_OFFSET, 0x0F, n775_state->pSpiTxSequence); - /* Set pause of balancing before measurement start, enable the measurement units simultaneously */ - N775_CommunicationWrite( - N775_BROADCAST_ADDRESS, - MC33775_ALLM_CFG_OFFSET, - (N775_BALPAUSELEN_10US << MC33775_ALLM_CFG_BALPAUSELEN_POS) | (1 << MC33775_ALLM_CFG_MEASEN_POS), - n775_state->pSpiTxSequence); + pState->currentString = 0u; + pState->pSpiTxSequence = pState->pSpiTxSequenceStart + pState->currentString; + pState->pSpiRxSequence = pState->pSpiRxSequenceStart + pState->currentString; +} - N775_waitTime(N775_TIME_AFTER_MEASUREMENT_START_MS); +static void N775_ResetMuxIndex(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); + + pState->currentMux[pState->currentString] = 0u; + pState->pMuxSequence[pState->currentString] = pState->pMuxSequenceStart[pState->currentString]; } -/** - * @brief captures the measurement. - * - * The MC33775A measures continuously. - * This function takes a snapshot on all slaves in the daisy-chain. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_CaptureMeasurement(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); +static void N775_SetFirstMeasurementCycleFinished(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); - uint16_t primaryRawValues[20] = {0u}; - uint16_t secondaryRawValues[4] = {0u}; - uint16_t currentRawValue = 0u; - int16_t primaryValues[20] = {0u}; - int16_t secondaryValues[4] = {0u}; - int16_t currentValue = 0u; - N775_COMMUNICATION_STATUS_e retValPrimary = N775_COMMUNICATION_OK; - N775_COMMUNICATION_STATUS_e retValSecondary = N775_COMMUNICATION_OK; - N775_COMMUNICATION_STATUS_e retValSupplyCurrent = N775_COMMUNICATION_OK; - uint16_t error = 0u; - bool gpio03Error = false; - bool gpio47Error = false; + OS_EnterTaskCritical(); + pState->firstMeasurementMade = true; + OS_ExitTaskCritical(); +} - /* Send capture command. This ends the last cycle and starts a new one */ +static STD_RETURN_TYPE_e N775_SetMuxChannel(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); + FAS_ASSERT(pState->pMuxSequence[pState->currentString]->muxId < 4u); + FAS_ASSERT(pState->pMuxSequence[pState->currentString]->muxChannel <= 0xFFu); + + uint16_t readValue = 0u; + uint8_t dataI2c = 0u; + uint8_t addressI2c_write = N775_ADG728_ADDRESS_UPPERBITS; + uint8_t addressI2c_read = N775_ADG728_ADDRESS_UPPERBITS; + uint16_t tries = 0u; + STD_RETURN_TYPE_e retVAL = STD_OK; + N775_COMMUNICATION_STATUS_e returnedValue = N775_COMMUNICATION_OK; + + /* First set channel */ + + /* Set bit1 and bit0 with mux address, write to mux */ + addressI2c_write |= ((pState->pMuxSequence[pState->currentString]->muxId) << 1u) | N775_I2C_WRITE; + /* Set bit1 and bit0 with mux address, read from mux */ + addressI2c_read |= ((pState->pMuxSequence[pState->currentString]->muxId) << 1u) | N775_I2C_READ; + + /** + * Set data to send, contains channel bit (8 channels) + * 1 means channel active, 0 means channel inactive + */ + if (pState->pMuxSequence[pState->currentString]->muxChannel == 0xFF) { + /* 0xFF in mux sequence means disable all channels */ + dataI2c = 0u; + } else { + dataI2c = (uint8_t)(1u << (pState->pMuxSequence[pState->currentString]->muxChannel)); + } + + /* Write data to send on I2C bus in registers */ N775_CommunicationWrite( N775_BROADCAST_ADDRESS, - MC33775_ALLM_APP_CTRL_OFFSET, - (1u << MC33775_ALLM_APP_CTRL_PAUSEBAL_POS) | (0x3FFu << MC33775_PRMM_APP_CTRL_CAPVC_POS) | - (MC33775_PRMM_APP_CTRL_VCOLNUM_DISABLED_ENUM_VAL << MC33775_PRMM_APP_CTRL_VCOLNUM_POS), - n775_state->pSpiTxSequence); - /* Wait for measurements to take place */ - N775_waitTime(N775_MEASUREMENT_CAPTURE_TIME_MS); - /* Send capture command. This ends the last cycle and starts a new one */ + MC33775_I2C_DATA0_OFFSET, + (addressI2c_write << MC33775_I2C_DATA0_BYTE0_POS) | (dataI2c << MC33775_I2C_DATA0_BYTE1_POS), + pState->pSpiTxSequence); + + /* Read with a repeated start directly after write */ N775_CommunicationWrite( N775_BROADCAST_ADDRESS, - MC33775_ALLM_APP_CTRL_OFFSET, - (0u << MC33775_ALLM_APP_CTRL_PAUSEBAL_POS) | (0x3FFu << MC33775_PRMM_APP_CTRL_CAPVC_POS) | - (MC33775_PRMM_APP_CTRL_VCOLNUM_DISABLED_ENUM_VAL << MC33775_PRMM_APP_CTRL_VCOLNUM_POS), - n775_state->pSpiTxSequence); - /* Wait for measurements to be ready */ - N775_waitTime(N775_MEASUREMENT_READY_TIME_MS); + MC33775_I2C_DATA1_OFFSET, + (addressI2c_read << MC33775_I2C_DATA1_BYTE2_POS) | (N775_I2C_DUMMY_BYTE << MC33775_I2C_DATA1_BYTE3_POS), + pState->pSpiTxSequence); - for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - uint8_t deviceAddress = m + 1u; - retValPrimary = N775_CommunicationReadMultiple( - deviceAddress, 20, 4u, MC33775_PRMM_APP_VC_CNT_OFFSET, primaryRawValues, n775_state); - retValSecondary = N775_CommunicationReadMultiple( - deviceAddress, 4, 4u, MC33775_SECM_APP_AIN4_OFFSET, secondaryRawValues, n775_state); - if (N775_CHECK_SUPPLY_CURRENT == true) { - retValSupplyCurrent = - N775_CommunicationRead(deviceAddress, MC33775_SECM_PER_NPNISENSE_OFFSET, ¤tRawValue, n775_state); - } + /* Write into the control register to start transaction */ + N775_CommunicationWrite( + N775_BROADCAST_ADDRESS, + MC33775_I2C_CTRL_OFFSET, + (N775_I2C_NR_BYTES_FOR_MUX_WRITE << MC33775_I2C_CTRL_START_POS) | + ((MC33775_I2C_CTRL_STPAFTER_STOP_ENUM_VAL << MC33775_I2C_CTRL_STPAFTER_POS) + + (N775_I2C_NR_BYTES_TO_SWITCH_TO_READ_FOR_UX_READ << MC33775_I2C_CTRL_RDAFTER_POS)), + pState->pSpiTxSequence); - N775_ErrorHandling(n775_state, retValPrimary, m); - if (retValPrimary == N775_COMMUNICATION_OK) { - for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { - /* Store cell voltages */ - if (N775_INVALID_REGISTER_VALUE != primaryRawValues[c + 1u]) { - primaryValues[c + 1u] = (int16_t)primaryRawValues[c + 1u]; - n775_state->n775Data.cellVoltage - ->cellVoltage_mV[n775_state->currentString][c + (m * BS_NR_OF_CELL_BLOCKS_PER_MODULE)] = - (((float_t)primaryValues[c + 1u]) * 154.0e-6f * 1000.0f); - } else { - error++; - } - } - for (uint8_t g = 0u; g < 4u; g++) { - /* Store GPIO voltages */ - if (N775_INVALID_REGISTER_VALUE != primaryRawValues[g + 16u]) { - primaryValues[g + 16u] = (int16_t)primaryRawValues[g + 16u]; - n775_state->n775Data.allGpioVoltage - ->gpioVoltages_mV[n775_state->currentString][g + (m * BS_NR_OF_GPIOS_PER_MODULE)] = - (((float_t)primaryValues[g + 16u]) * 154.0e-6f * 1000.0f); + /** + * Wait util transaction ends, test on last device in daisy-chain + * So device address = number of modules + */ + tries = N775_FLAG_READY_TRIES; + do { + returnedValue = + N775_CommunicationRead(BS_NR_OF_MODULES_PER_STRING, MC33775_I2C_STAT_OFFSET, &readValue, pState); + tries--; + N775_Wait(2u); + } while ((readValue & MC33775_I2C_STAT_PENDING_MSK) && (returnedValue == N775_COMMUNICATION_OK) && (tries > 0u)); + + if ((returnedValue == N775_COMMUNICATION_OK) && (tries > 0u)) { + /** + * Get I2C read data, on last device in daisy-chain + * Use result to set error state for all slaves to avoid + * reading all slaves in daisy-chain. + */ + returnedValue = + N775_CommunicationRead(BS_NR_OF_MODULES_PER_STRING, MC33775_I2C_DATA1_OFFSET, &readValue, pState); + readValue = readValue >> MC33775_I2C_DATA1_BYTE3_POS; + + if (returnedValue == N775_COMMUNICATION_OK) { + if (N775_CHECK_MUX_STATE == true) { + if (readValue == dataI2c) { + /* OK */ + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + pState->n775Data.errorTable->mux0IsOk[pState->currentString][m] = true; + } } else { - gpio03Error = true; - error++; + /* Not OK */ + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + pState->n775Data.errorTable->mux0IsOk[pState->currentString][m] = false; + } } - } - /* Store module voltage */ - if (N775_INVALID_REGISTER_VALUE != primaryRawValues[15u]) { - primaryValues[15u] = (int16_t)primaryRawValues[15u]; - n775_state->n775Data.cellVoltage->moduleVoltage_mV[n775_state->currentString][m] = - (((float_t)primaryValues[15u]) * 2.58e-3f * 1000.0f); } else { - error++; + retVAL = STD_NOT_OK; } } + } else { + retVAL = STD_NOT_OK; + } - N775_ErrorHandling(n775_state, retValSecondary, m); - if (retValSecondary == N775_COMMUNICATION_OK) { - for (uint8_t g = 4u; g < 8u; g++) { - if (N775_INVALID_REGISTER_VALUE != secondaryRawValues[g - 4u]) { - secondaryValues[g - 4u] = (int16_t)secondaryRawValues[g - 4u]; - n775_state->n775Data.allGpioVoltage - ->gpioVoltages_mV[n775_state->currentString][g + (m * BS_NR_OF_GPIOS_PER_MODULE)] = - (((float_t)secondaryValues[g - 4u]) * 154.0e-6f * 1000.0f); - } else { - gpio47Error = true; - error++; - } - } - } + return retVAL; +} - /* Set temperature values */ - if (N775_USE_MUX_FOR_TEMP == true) { - /* Mux case */ - if (gpio03Error == false) { - n775_state->n775Data.cellTemperature - ->cellTemperature_ddegC[n775_state->currentString] - [n775_state->currentMux[n775_state->currentString] + - (m * BS_NR_OF_TEMP_SENSORS_PER_MODULE)] = - N775_ConvertVoltagesToTemperatures( - n775_state->n775Data.allGpioVoltage - ->gpioVoltages_mV[n775_state->currentString] - [N775_MUXED_TEMP_GPIO_POSITION + (m * BS_NR_OF_GPIOS_PER_MODULE)]); - } - } else if (N775_USE_MUX_FOR_TEMP == false) { - /* No mux case */ - if ((gpio03Error == false) && (gpio47Error == false)) { - for (uint16_t t = 0u; t < BS_NR_OF_TEMP_SENSORS_PER_MODULE; t++) { - n775_state->n775Data.cellTemperature - ->cellTemperature_ddegC[n775_state->currentString][t + (m * BS_NR_OF_TEMP_SENSORS_PER_MODULE)] = - N775_ConvertVoltagesToTemperatures( - n775_state->n775Data.allGpioVoltage - ->gpioVoltages_mV[n775_state->currentString][t + (m * BS_NR_OF_GPIOS_PER_MODULE)]); - } - } - } else { - /* Invalid value for switch case */ - FAS_ASSERT(FAS_TRAP); - } +static void N775_StartMeasurement(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); - if (N775_CHECK_SUPPLY_CURRENT == true) { - N775_ErrorHandling(n775_state, retValSupplyCurrent, m); - if (retValSupplyCurrent == N775_COMMUNICATION_OK) { - if (N775_INVALID_REGISTER_VALUE != currentRawValue) { - currentValue = (int16_t)currentRawValue; - n775_state->n775Data.supplyCurrent->current[n775_state->currentString][m] = - (((float_t)currentValue) * 7.69e-6f * 1000.0f); - } else { - error++; - } - } - } - } + /* Enable cell voltage measurements */ + N775_CommunicationWrite(N775_BROADCAST_ADDRESS, MC33775_ALLM_VCVB_CFG_OFFSET, 0x3FFF, pState->pSpiTxSequence); + /* Enable analog inputs 0-3 and module voltage measurement */ + N775_CommunicationWrite(N775_BROADCAST_ADDRESS, MC33775_PRMM_AIN_CFG_OFFSET, 0x1F, pState->pSpiTxSequence); + /* Enable analog inputs 4-7 measurement */ + N775_CommunicationWrite(N775_BROADCAST_ADDRESS, MC33775_SECM_AIN_CFG_OFFSET, 0x0F, pState->pSpiTxSequence); + /* Set pause of balancing before measurement start, enable the measurement units simultaneously */ + N775_CommunicationWrite( + N775_BROADCAST_ADDRESS, + MC33775_ALLM_CFG_OFFSET, + (N775_BALPAUSELEN_10US << MC33775_ALLM_CFG_BALPAUSELEN_POS) | (1 << MC33775_ALLM_CFG_MEASEN_POS), + pState->pSpiTxSequence); - DATA_WRITE_DATA( - n775_state->n775Data.cellVoltage, n775_state->n775Data.cellTemperature, n775_state->n775Data.allGpioVoltage); + N775_Wait(N775_TIME_AFTER_MEASUREMENT_START_MS); } -/** - * @brief tranmit over I2C on NXP slave. - * - * @param n775_state state of the N775A driver - * - */ -static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); +static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); uint8_t i2cAddressByte = 0u; uint16_t readValue = 0u; uint16_t tries = 0u; @@ -793,7 +804,7 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { MC33775_I2C_DATA0_OFFSET, (i2cAddressByte << MC33775_I2C_DATA0_BYTE0_POS) | (transactionData.writeData[0u] << MC33775_I2C_DATA0_BYTE1_POS), - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); if (transactionData.writeDataLength > 1u) { /* Now set data to be written to I2C device */ @@ -817,14 +828,14 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { transactionData.module + 1u, registerStartAddress + registerIncrement, dataToWrite, - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); registerIncrement++; bytesWritten = 0u; dataToWrite = 0u; } } } - /* Data to write ready, now start transmisison */ + /* Data to write ready, now start transmission */ /* Write into the control register to start transaction */ N775_CommunicationWrite( transactionData.module + 1u, @@ -833,14 +844,14 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { ((transactionData.writeDataLength + 1u) << MC33775_I2C_CTRL_START_POS) | ((MC33775_I2C_CTRL_STPAFTER_STOP_ENUM_VAL << MC33775_I2C_CTRL_STPAFTER_POS) + (0u << MC33775_I2C_CTRL_RDAFTER_POS)), - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); /* Wait until transaction ends */ tries = N775_FLAG_READY_TRIES; do { returnedValue = N775_CommunicationRead( - transactionData.module + 1u, MC33775_I2C_STAT_OFFSET, &readValue, n775_state); + transactionData.module + 1u, MC33775_I2C_STAT_OFFSET, &readValue, pState); tries--; - N775_waitTime(2u); + N775_Wait(2u); } while ((readValue & MC33775_I2C_STAT_PENDING_MSK) && (returnedValue == N775_COMMUNICATION_OK) && (tries > 0u)); @@ -864,7 +875,7 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { transactionData.module + 1u, MC33775_I2C_DATA0_OFFSET, i2cAddressByte << MC33775_I2C_DATA0_BYTE0_POS, - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); /* Write into the control register to start transaction */ /* Stop condition after transfer, no repeated start */ N775_CommunicationWrite( @@ -873,14 +884,14 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { /* transactionData.dataLength + 1u: data + I2C device address byte */ ((transactionData.readDataLength + 1u) << MC33775_I2C_CTRL_START_POS) | ((1u << MC33775_I2C_CTRL_STPAFTER_POS) + (0u << MC33775_I2C_CTRL_RDAFTER_POS)), - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); /* Wait until transaction ends */ tries = N775_FLAG_READY_TRIES; do { returnedValue = N775_CommunicationRead( - transactionData.module + 1u, MC33775_I2C_STAT_OFFSET, &readValue, n775_state); + transactionData.module + 1u, MC33775_I2C_STAT_OFFSET, &readValue, pState); tries--; - N775_waitTime(2u); + N775_Wait(2u); } while ((readValue & MC33775_I2C_STAT_PENDING_MSK) && (returnedValue == N775_COMMUNICATION_OK) && (tries > 0u)); /* Now retrieve read data */ @@ -896,7 +907,7 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { 4u, MC33775_I2C_DATA0_OFFSET, readData, - n775_state); + pState); /* First data register only contains one byte of the read data */ transactionData.readData[0u] = (uint8_t)((readData[0u] & 0xFF00) >> 8u); @@ -933,7 +944,7 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { MC33775_I2C_DATA0_OFFSET, ((i2cAddressByte | N775_I2C_WRITE) << MC33775_I2C_DATA0_BYTE0_POS) | (transactionData.writeData[0u] << MC33775_I2C_DATA0_BYTE1_POS), - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); if (transactionData.writeDataLength > 1u) { /* Now set data to be written to I2C device */ @@ -958,7 +969,7 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { transactionData.module + 1u, registerStartAddress + registerIncrement, dataToWrite, - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); registerIncrement++; bytesWritten = 0u; dataToWrite = 0u; @@ -969,7 +980,7 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { transactionData.module + 1u, MC33775_I2C_DATA1_OFFSET, ((i2cAddressByte | N775_I2C_READ) << MC33775_I2C_DATA1_BYTE2_POS), - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); } /* Write into the control register to start transaction */ @@ -983,14 +994,14 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { << MC33775_I2C_CTRL_START_POS) | ((1u << MC33775_I2C_CTRL_STPAFTER_POS) + ((1u + transactionData.writeDataLength) << MC33775_I2C_CTRL_RDAFTER_POS)), - n775_state->pSpiTxSequence); + pState->pSpiTxSequence); /* Wait until transaction ends */ tries = N775_FLAG_READY_TRIES; do { returnedValue = N775_CommunicationRead( - transactionData.module + 1u, MC33775_I2C_STAT_OFFSET, &readValue, n775_state); + transactionData.module + 1u, MC33775_I2C_STAT_OFFSET, &readValue, pState); tries--; - N775_waitTime(2u); + N775_Wait(2u); } while ((readValue & MC33775_I2C_STAT_PENDING_MSK) && (returnedValue == N775_COMMUNICATION_OK) && (tries > 0u)); /* Now retrieve read data */ @@ -1011,7 +1022,7 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { } returnedValue = N775_CommunicationReadMultiple( - transactionData.module + 1u, nrOfRegisterToRead, 4u, registerOffset, readData, n775_state); + transactionData.module + 1u, nrOfRegisterToRead, 4u, registerOffset, readData, pState); /* Second data register only contains one byte of the read data (byte3) Read data starts at second register because: @@ -1053,249 +1064,253 @@ static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *n775_state) { } } retVal = STD_OK; - transactionData.transferType = AFE_I2C_TRANSFER_TYPE_READ_SUCCESS; - } - if (OS_SendToBackOfQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) { - /* Queue is not full */ - } else { - /* Queue is full */ - retVal = STD_NOT_OK; - } - break; - - default: - /* Invalid value transfer type */ - FAS_ASSERT(FAS_TRAP); - break; - } - } - } - - return retVal; -} - -/** - * @brief sets mux channel. - * - * This function uses I2C to set the mux channel. - * - * @param n775_state state of the N775A driver - * - */ -static STD_RETURN_TYPE_e N775_SetMuxChannel(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); - FAS_ASSERT(n775_state->pMuxSequence[n775_state->currentString]->muxId < 4u); - FAS_ASSERT(n775_state->pMuxSequence[n775_state->currentString]->muxChannel <= 0xFFu); - - uint16_t readValue = 0u; - uint8_t dataI2c = 0u; - uint8_t addressI2c_write = N775_ADG728_ADDRESS_UPPERBITS; - uint8_t addressI2c_read = N775_ADG728_ADDRESS_UPPERBITS; - uint16_t tries = 0u; - STD_RETURN_TYPE_e retVAL = STD_OK; - N775_COMMUNICATION_STATUS_e returnedValue = N775_COMMUNICATION_OK; - - /* First set channel */ - - /* Set bit1 and bit0 with mux address, write to mux */ - addressI2c_write |= ((n775_state->pMuxSequence[n775_state->currentString]->muxId) << 1u) | N775_I2C_WRITE; - /* Set bit1 and bit0 with mux address, read from mux */ - addressI2c_read |= ((n775_state->pMuxSequence[n775_state->currentString]->muxId) << 1u) | N775_I2C_READ; + transactionData.transferType = AFE_I2C_TRANSFER_TYPE_READ_SUCCESS; + } + if (OS_SendToBackOfQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) { + /* Queue is not full */ + } else { + /* Queue is full */ + retVal = STD_NOT_OK; + } + break; - /** - * Set data to send, contains channel bit (8 channels) - * 1 means channel active, 0 means channel inactive - */ - if (n775_state->pMuxSequence[n775_state->currentString]->muxChannel == 0xFF) { - /* 0xFF in mux sequence means disable all channels */ - dataI2c = 0u; - } else { - dataI2c = (uint8_t)(1u << (n775_state->pMuxSequence[n775_state->currentString]->muxChannel)); + default: + /* Invalid value transfer type */ + FAS_ASSERT(FAS_TRAP); + break; + } + } } - /* Write data to send on I2C bus in registers */ - N775_CommunicationWrite( - N775_BROADCAST_ADDRESS, - MC33775_I2C_DATA0_OFFSET, - (addressI2c_write << MC33775_I2C_DATA0_BYTE0_POS) | (dataI2c << MC33775_I2C_DATA0_BYTE1_POS), - n775_state->pSpiTxSequence); - - /* Read with a repeated start directly after write */ - N775_CommunicationWrite( - N775_BROADCAST_ADDRESS, - MC33775_I2C_DATA1_OFFSET, - (addressI2c_read << MC33775_I2C_DATA1_BYTE2_POS) | (N775_I2C_DUMMY_BYTE << MC33775_I2C_DATA1_BYTE3_POS), - n775_state->pSpiTxSequence); + return retVal; +} - /* Write into the control register to start transaction */ - N775_CommunicationWrite( - N775_BROADCAST_ADDRESS, - MC33775_I2C_CTRL_OFFSET, - (N775_I2C_NR_BYTES_FOR_MUX_WRITE << MC33775_I2C_CTRL_START_POS) | - ((MC33775_I2C_CTRL_STPAFTER_STOP_ENUM_VAL << MC33775_I2C_CTRL_STPAFTER_POS) + - (N775_I2C_NR_BYTES_TO_SWITCH_TO_READ_FOR_UX_READ << MC33775_I2C_CTRL_RDAFTER_POS)), - n775_state->pSpiTxSequence); +static void N775_Wait(uint32_t milliseconds) { + uint32_t current_time = OS_GetTickCount(); + /* Block task without possibility to wake up */ + OS_DelayTaskUntil(¤t_time, milliseconds); +} - /** - * Wait util transaction ends, test on last device in daisy-chain - * So device address = number of modules - */ - tries = N775_FLAG_READY_TRIES; - do { - returnedValue = - N775_CommunicationRead(BS_NR_OF_MODULES_PER_STRING, MC33775_I2C_STAT_OFFSET, &readValue, n775_state); - tries--; - N775_waitTime(2u); - } while ((readValue & MC33775_I2C_STAT_PENDING_MSK) && (returnedValue == N775_COMMUNICATION_OK) && (tries > 0u)); +/*========== Extern Function Implementations ================================*/ - if ((returnedValue == N775_COMMUNICATION_OK) && (tries > 0u)) { - /** - * Get I2C read data, on last device in daisy-chain - * Use result to set error state for all slaves to avoid - * reading all slaves in daisy-chain. - */ - returnedValue = - N775_CommunicationRead(BS_NR_OF_MODULES_PER_STRING, MC33775_I2C_DATA1_OFFSET, &readValue, n775_state); - readValue = readValue >> MC33775_I2C_DATA1_BYTE3_POS; +extern STD_RETURN_TYPE_e N775_I2cRead(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength) { + FAS_ASSERT(pData != NULL_PTR); + FAS_ASSERT((dataLength > 0u) && (dataLength <= 13u)); + STD_RETURN_TYPE_e retVal = STD_NOT_OK; + AFE_I2C_QUEUE_s transactionData; - if (returnedValue == N775_COMMUNICATION_OK) { - if (N775_CHECK_MUX_STATE == true) { - if (readValue == dataI2c) { - /* OK */ - for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - n775_state->n775Data.errorTable->mux0IsOk[n775_state->currentString][m] = true; - } - } else { - /* Not OK */ - for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - n775_state->n775Data.errorTable->mux0IsOk[n775_state->currentString][m] = false; - } + transactionData.module = module; + transactionData.deviceAddress = deviceAddress; + transactionData.readDataLength = dataLength; + transactionData.transferType = AFE_I2C_TRANSFER_TYPE_READ; + if (OS_SendToBackOfQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) { + /* queue is not full */ + /* waiting for transfer to finish */ + if (OS_ReceiveFromQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, N775_I2C_FINISHED_TIMEOUT_ms) == + OS_SUCCESS) { + if (transactionData.transferType == AFE_I2C_TRANSFER_TYPE_READ_SUCCESS) { + for (uint8_t i = 0u; i < dataLength; i++) { + pData[i] = transactionData.readData[i]; } - } else { - retVAL = STD_NOT_OK; + retVal = STD_OK; } } } else { - retVAL = STD_NOT_OK; + /* queue is full */ } - return retVAL; + return retVal; } -/** - * @brief setups balancing. - * - * Sets all balancing timer to max to allow for software balancing control. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_BalanceSetup(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); - - /* Set global timeout counter to max value */ - N775_CommunicationWrite( - N775_BROADCAST_ADDRESS, - MC33775_BAL_GLOB_TO_TMR_OFFSET, - N775_GLOBAL_BALANCING_TIMER, - n775_state->pSpiTxSequence); - - /* Disable pre-balancing timer by setting it to zero */ - N775_CommunicationWrite( - N775_BROADCAST_ADDRESS, MC33775_BAL_PRE_TMR_OFFSET, N775_PRE_BALANCING_TIMER, n775_state->pSpiTxSequence); +extern STD_RETURN_TYPE_e N775_I2cWrite(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength) { + FAS_ASSERT(pData != NULL_PTR); + FAS_ASSERT((dataLength > 0u) && (dataLength <= 13u)); + STD_RETURN_TYPE_e retVal = STD_NOT_OK; + AFE_I2C_QUEUE_s transactionData; - /* Set PWM value for all channels to 100%, set balancing timer for all channels to maximum value */ - N775_CommunicationWrite( - N775_BROADCAST_ADDRESS, - MC33775_BAL_TMR_CH_ALL_OFFSET, - (MC33775_BAL_TMR_CH_ALL_PWM_PWM100_ENUM_VAL << MC33775_BAL_TMR_CH_ALL_PWM_POS) | - (N775_ALL_CHANNEL_BALANCING_TIMER << MC33775_BAL_TMR_CH_ALL_BALTIME_POS), - n775_state->pSpiTxSequence); + transactionData.module = module; + transactionData.deviceAddress = deviceAddress; + transactionData.writeDataLength = dataLength; + transactionData.transferType = AFE_I2C_TRANSFER_TYPE_WRITE; + for (uint8_t i = 0u; i < dataLength; i++) { + transactionData.writeData[i] = pData[i]; + } + if (OS_SendToBackOfQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) { + /* queue is not full */ + /* waiting for transfer to finish */ + if (OS_ReceiveFromQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, N775_I2C_FINISHED_TIMEOUT_ms) == + OS_SUCCESS) { + if (transactionData.transferType == AFE_I2C_TRANSFER_TYPE_WRITE_SUCCESS) { + retVal = STD_OK; + } + } + } else { + /* queue is full */ + } - /* Select timer based balancing and enable balancing */ - N775_CommunicationWrite( - N775_BROADCAST_ADDRESS, - MC33775_BAL_GLOB_CFG_OFFSET, - (MC33775_BAL_GLOB_CFG_BALEN_ENABLED_ENUM_VAL << MC33775_BAL_GLOB_CFG_BALEN_POS) | - (MC33775_BAL_GLOB_CFG_TMRBALEN_STOP_ENUM_VAL << MC33775_BAL_GLOB_CFG_TMRBALEN_POS), - n775_state->pSpiTxSequence); + return retVal; } -/** - * @brief manages balancing. - * - * Reads balancing order from database and balances the corresponding cells. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_BalanceControl(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); - - N775_BalanceSetup(n775_state); - - DATA_READ_DATA(n775_state->n775Data.balancingControl); +extern STD_RETURN_TYPE_e N775_I2cWriteRead( + uint8_t module, + uint8_t deviceAddress, + uint8_t *pDataWrite, + uint8_t writeDataLength, + uint8_t *pDataRead, + uint8_t readDataLength) { + FAS_ASSERT(pDataWrite != NULL_PTR); + FAS_ASSERT(pDataRead != NULL_PTR); + FAS_ASSERT(writeDataLength > 0u); + FAS_ASSERT(readDataLength > 0u); + FAS_ASSERT((uint16_t)(writeDataLength + readDataLength) <= 12u); + STD_RETURN_TYPE_e retVal = STD_NOT_OK; + AFE_I2C_QUEUE_s transactionData; - for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - uint8_t deviceAddress = m + 1u; - uint16_t balancingState = 0u; - for (uint16_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { - if (n775_state->n775Data.balancingControl - ->balancingState[n775_state->currentString][c + (m * BS_NR_OF_CELL_BLOCKS_PER_MODULE)] != 0u) { - balancingState |= 1u << c; + transactionData.module = module; + transactionData.deviceAddress = deviceAddress; + transactionData.writeDataLength = writeDataLength; + transactionData.readDataLength = readDataLength; + transactionData.transferType = AFE_I2C_TRANSFER_TYPE_WRITEREAD; + for (uint8_t i = 0u; i < writeDataLength; i++) { + transactionData.writeData[i] = pDataWrite[i]; + } + if (OS_SendToBackOfQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) { + /* queue is not full */ + /* waiting for transfer to finish */ + if (OS_ReceiveFromQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, N775_I2C_FINISHED_TIMEOUT_ms) == + OS_SUCCESS) { + if (transactionData.transferType == AFE_I2C_TRANSFER_TYPE_READ_SUCCESS) { + for (uint8_t i = 0u; i < readDataLength; i++) { + pDataRead[i] = transactionData.readData[i]; + } + retVal = STD_OK; } } - /* All channels active --> 14 bits set to 1 --> 0x3FFF */ - FAS_ASSERT(balancingState <= 0x3FFFu); - /* Enable channels, one written to a channels means balancing active */ - N775_CommunicationWrite(deviceAddress, MC33775_BAL_CH_CFG_OFFSET, balancingState, n775_state->pSpiTxSequence); + } else { + /* queue is full */ } + + return retVal; } -extern bool N775_IsFirstMeasurementCycleFinished(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); +extern bool N775_IsFirstMeasurementCycleFinished(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); bool retval = false; OS_EnterTaskCritical(); - retval = n775_state->firstMeasurementMade; + retval = pState->firstMeasurementMade; OS_ExitTaskCritical(); return retval; } -/** - * @brief sets the measurement initialization status. - * - * @param n775_state state of the N775A driver - * - */ -static void N775_SetFirstMeasurementCycleFinished(N775_STATE_s *n775_state) { - FAS_ASSERT(n775_state != NULL_PTR); +extern void N775_Measure(N775_STATE_s *pState) { + FAS_ASSERT(pState != NULL_PTR); - OS_EnterTaskCritical(); - n775_state->firstMeasurementMade = true; - OS_ExitTaskCritical(); -} + N775_InitializeDatabase(pState); + /* Initialize SPI sequence pointers */ + pState->pSpiTxSequenceStart = spi_nxp775InterfaceTx; + pState->pSpiRxSequenceStart = spi_nxp775InterfaceRx; -extern void TEST_N775_SetFirstMeasurementCycleFinished(N775_STATE_s *n775_state) { - N775_SetFirstMeasurementCycleFinished(n775_state); -} + /* Initialize each string */ + N775_ResetStringSequence(pState); + while (pState->currentString < BS_NR_OF_STRINGS) { + /* Initialize mux sequence pointers */ + pState->pMuxSequenceStart[pState->currentString] = n775_muxSequence; + N775_Initialize(pState); + N775_IncrementStringSequence(pState); + } -/** - * @brief waits for a definite amount of time in ms. - * - * This function uses FreeRTOS. It blocks the tasks for - * the given amount of milliseconds. - * - * @param milliseconds time to wait in ms - * - */ -void N775_waitTime(uint32_t milliseconds) { - uint32_t current_time = OS_GetTickCount(); - /* Block task without possibility to wake up */ - OS_DelayTaskUntil(¤t_time, milliseconds); + while (1) { + N775_ResetStringSequence(pState); + + while (pState->currentString < BS_NR_OF_STRINGS) { + if (N775_USE_MUX_FOR_TEMP == true) { + /* Set mux channel according to mux sequence */ + N775_SetMuxChannel(pState); + } + N775_CaptureMeasurement(pState); + if (N775_USE_MUX_FOR_TEMP == true) { + /* Update index in mux sequence */ + N775_IncrementMuxIndex(pState); + } + N775_BalanceControl(pState); + + N775_TransmitI2c(pState); + + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + if (N775_IsFirstMeasurementCycleFinished(pState) == true) { + if (pState->n775Data.errorTable->noCommunicationTimeout[pState->currentString][m] == 0u) { + /* Daisy-chain does not answer: initialize it again */ + pState->pMuxSequenceStart[pState->currentString] = n775_muxSequence; + N775_Initialize(pState); + /* Daisy-chain re-initialized: no need to check further slaves */ + break; + } + } + } + + N775_IncrementStringSequence(pState); + } + + /* Set flag when all strings have been measured */ + if ((pState->currentString == BS_NR_OF_STRINGS) && (N775_IsFirstMeasurementCycleFinished(pState) == 0u)) { + N775_SetFirstMeasurementCycleFinished(pState); + } + } } /*========== Externalized Static Function Implementations (Unit Test) =======*/ #ifdef UNITY_UNIT_TEST +extern void TEST_N775_BalanceControl(N775_STATE_s *pState) { + N775_BalanceControl(pState); +} +extern void TEST_N775_BalanceSetup(N775_STATE_s *pState) { + N775_BalanceSetup(pState); +} +extern void TEST_N775_CaptureMeasurement(N775_STATE_s *pState) { + N775_CaptureMeasurement(pState); +} +extern STD_RETURN_TYPE_e TEST_N775_Enumerate(N775_STATE_s *pState) { + return N775_Enumerate(pState); +} +extern void TEST_N775_ErrorHandling(N775_STATE_s *pState, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module) { + N775_ErrorHandling(pState, returnedValue, module); +} +extern void TEST_N775_IncrementMuxIndex(N775_STATE_s *pState) { + N775_IncrementMuxIndex(pState); +} +extern void TEST_N775_IncrementStringSequence(N775_STATE_s *pState) { + N775_IncrementStringSequence(pState); +} +extern void TEST_N775_Initialize(N775_STATE_s *pState) { + N775_Initialize(pState); +} +extern void TEST_N775_InitializeDatabase(N775_STATE_s *pState) { + N775_InitializeDatabase(pState); +} +extern void TEST_N775_InitializeI2c(N775_STATE_s *pState) { + N775_InitializeI2c(pState); +} +extern void TEST_N775_ResetStringSequence(N775_STATE_s *pState) { + N775_ResetStringSequence(pState); +} +extern void TEST_N775_ResetMuxIndex(N775_STATE_s *pState) { + N775_ResetMuxIndex(pState); +} +extern void TEST_N775_SetFirstMeasurementCycleFinished(N775_STATE_s *pState) { + N775_SetFirstMeasurementCycleFinished(pState); +} +extern STD_RETURN_TYPE_e TEST_N775_SetMuxChannel(N775_STATE_s *pState) { + return N775_SetMuxChannel(pState); +} +extern void TEST_N775_StartMeasurement(N775_STATE_s *pState) { + N775_StartMeasurement(pState); +} +extern STD_RETURN_TYPE_e TEST_N775_TransmitI2c(N775_STATE_s *pState) { + return N775_TransmitI2c(pState); +} +extern void TEST_N775_Wait(uint32_t milliseconds) { + N775_Wait(milliseconds); +} #endif diff --git a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.h b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.h index fa5cbf2e..2209de29 100644 --- a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.h +++ b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.h @@ -43,13 +43,15 @@ * @file nxp_mc33775a.h * @author foxBMS Team * @date 2020-05-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix N775 * * @brief Headers for the driver for the MC33775A analog front-end. - * + * @details Defines the interface to perform measurements with the MC33775A: + * It further defines functions to write to and read from the I2C bus + * that is implement of the AFE. */ #ifndef FOXBMS__NXP_MC33775A_H_ @@ -64,55 +66,38 @@ /*========== Extern Constant and Variable Declarations ======================*/ -/** - * Variable containing the state machine state for the MC33775A driver. - */ +/** state of the state machine for the MC33775A driver */ extern N775_STATE_s n775_stateBase; /*========== Extern Function Prototypes =====================================*/ /** - * @brief trigger function for the N775 driver state machine. - * - * This function contains the sequence of events in the N775 state machine. - * It must be called time-triggered, every 1ms. - * - * @param n775_state state of the N775A driver - * - */ -extern void N775_Meas(N775_STATE_s *n775_state); - -/** - * @brief gets the measurement initialization status. - * - * @param n775_state state of the N775A driver - * - * @return true if a first measurement cycle was made, false otherwise - * + * @brief trigger a read on the I2C bus of the slave. + * @param module module number to address in the daisy-chain + * @param deviceAddress address of the I2C device addressed + * @param pData data read on I2C bus + * @param dataLength number of bytes to read */ -extern bool N775_IsFirstMeasurementCycleFinished(N775_STATE_s *n775_state); +extern STD_RETURN_TYPE_e N775_I2cRead(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength); /** - * @brief trigger a write on the I2C bus of the slave. - * + * @brief trigger a write on the I2C bus of the slave. * @param module module number to address in the daisy-chain * @param deviceAddress address of the I2C device addressed * @param pData data to write on I2C bus * @param dataLength number of bytes to write - * */ extern STD_RETURN_TYPE_e N775_I2cWrite(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength); /** - * @brief trigger a read on the I2C bus of the slave, first write address of register to read. - * - * @param module module number to address in the daisy-chain - * @param deviceAddress address of the I2C device addressed - * @param pDataWrite data written on I2C bus - * @param writeDataLength number of bytes to write - * @param pDataRead data read on I2C bus - * @param readDataLength number of bytes to read - * + * @brief trigger a read on the I2C bus of the slave, first write address of + * register to read. + * @param module module number to address in the daisy-chain + * @param deviceAddress address of the I2C device addressed + * @param pDataWrite data written on I2C bus + * @param writeDataLength number of bytes to write + * @param pDataRead data read on I2C bus + * @param readDataLength number of bytes to read */ extern STD_RETURN_TYPE_e N775_I2cWriteRead( uint8_t module, @@ -121,23 +106,43 @@ extern STD_RETURN_TYPE_e N775_I2cWriteRead( uint8_t writeDataLength, uint8_t *pDataRead, uint8_t readDataLength); + /** - * @brief trigger a read on the I2C bus of the slave. - * - * @param module module number to address in the daisy-chain - * @param deviceAddress address of the I2C device addressed - * @param pData data read on I2C bus - * @param dataLength number of bytes to read - * + * @brief gets the measurement initialization status. + * @param pState state of the N775A driver + * @return true if a first measurement cycle was made, false otherwise */ -extern STD_RETURN_TYPE_e N775_I2cRead(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength); +extern bool N775_IsFirstMeasurementCycleFinished(N775_STATE_s *pState); + +/** + * @brief trigger function for the N775 driver state machine. + * @details This function contains the sequence of events in the N775 state + * machine. + * It must be called time-triggered, every 1ms. + * @param pState state of the N775A driver + */ +extern void N775_Measure(N775_STATE_s *pState); /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST -/* Start test functions */ -extern uint8_t TEST_N775_CheckReEntrance(); -extern void TEST_N775_SetFirstMeasurementCycleFinished(N775_STATE_s *n775_state); -/* End test functions */ +#include "nxp_mc33775a-ll.h" +extern void TEST_N775_BalanceControl(N775_STATE_s *pState); +extern void TEST_N775_BalanceSetup(N775_STATE_s *pState); +extern void TEST_N775_CaptureMeasurement(N775_STATE_s *pState); +extern STD_RETURN_TYPE_e TEST_N775_Enumerate(N775_STATE_s *pState); +extern void TEST_N775_ErrorHandling(N775_STATE_s *pState, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module); +extern void TEST_N775_IncrementMuxIndex(N775_STATE_s *pState); +extern void TEST_N775_IncrementStringSequence(N775_STATE_s *pState); +extern void TEST_N775_Initialize(N775_STATE_s *pState); +extern void TEST_N775_InitializeDatabase(N775_STATE_s *pState); +extern void TEST_N775_InitializeI2c(N775_STATE_s *pState); +extern void TEST_N775_ResetStringSequence(N775_STATE_s *pState); +extern void TEST_N775_ResetMuxIndex(N775_STATE_s *pState); +extern void TEST_N775_SetFirstMeasurementCycleFinished(N775_STATE_s *pState); +extern STD_RETURN_TYPE_e TEST_N775_SetMuxChannel(N775_STATE_s *pState); +extern void TEST_N775_StartMeasurement(N775_STATE_s *pState); +extern STD_RETURN_TYPE_e TEST_N775_TransmitI2c(N775_STATE_s *pState); +extern void TEST_N775_Wait(uint32_t milliseconds); #endif #endif /* FOXBMS__NXP_MC33775A_H_ */ diff --git a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.json b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.json index d061b962..f483a21a 100644 --- a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.json +++ b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.json @@ -1,8 +1,11 @@ { "include": [ - "../../api", ".", "api", - "config" + "config", + "vendor", + "../api", + "../common", + "../../api" ] } diff --git a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a_defs.h b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a_defs.h index 314348e8..04e092c3 100644 --- a/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a_defs.h +++ b/src/app/driver/afe/nxp/mc33775a/nxp_mc33775a_defs.h @@ -43,8 +43,8 @@ * @file nxp_mc33775a_defs.h * @author foxBMS Team * @date 2020-09-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix N775 * @@ -136,7 +136,7 @@ typedef struct { bool mux1IsOK[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]; /*!< */ bool mux2IsOK[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]; /*!< */ bool mux3IsOK[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]; /*!< */ -} N775_ERRORTABLE_s; +} N775_ERROR_TABLE_s; /** error table for the LTC driver */ typedef struct { @@ -149,52 +149,14 @@ typedef struct { uint8_t muxChannel; /*!< multiplexer channel 0 - 7 */ } N775_MUX_CH_CFG_s; -/** States of the N775 state machine */ -typedef enum { - N775_STATEMACH_UNINITIALIZED, /*!< */ - N775_STATEMACH_INITIALIZATION, /*!< */ - N775_STATEMACH_WAKEUP, /*!< */ - N775_STATEMACH_ENUMERATE, /*!< */ - N775_STATEMACH_INITIALIZED, /*!< */ - N775_STATEMACH_IDLE, /*!< */ - N775_STATEMACH_STARTMEAS, /*!< */ - N775_STATEMACH_READVOLTAGE, /*!< */ - N775_STATEMACH_BALANCECONTROL, -} N775_STATEMACH_e; - -/** General substates */ -typedef enum { - N775_ENTRY, /*!< */ - N775_SECOND_WAKEUP, /*!< */ - N775_CHECK_ENUMERATION, /*!< */ - N775_ERROR_ENTRY, /*!< */ - N775_ERROR_PROCESSED, /*!< */ -} N775_STATEMACH_SUB_e; - -/** Substates for the uninitialized state */ -typedef enum { - N775_ENTRY_UNINITIALIZED = 0, /*!< Initialize-sequence */ -} N775_STATEMACH_UNINITIALIZED_SUB_e; - -/** Substates for the initialization state */ -typedef enum { - /* Init-Sequence */ - N775_ENTRY_INITIALIZATION = 0, /*!< */ - N775_START_INIT_INITIALIZATION = 1, /*!< */ - N775_RE_ENTRY_INITIALIZATION = 2, /*!< */ - N775_READ_INITIALIZATION_REGISTER = 3, /*!< */ - N775_CHECK_INITIALIZATION = 4, /*!< */ - N775_EXIT_INITIALIZATION = 5, /*!< */ -} N775_STATEMACH_INITIALIZATION_SUB_e; - -/** State requests for the N775 statemachine */ +/** State requests for the N775 state machine */ typedef enum { N775_STATE_INITIALIZATION_REQUEST, /*!< */ N775_STATE_NO_REQUEST, /*!< */ } N775_STATE_REQUEST_e; /** - * Possible return values when state requests are made to the N775 statemachine + * Possible return values when state requests are made to the N775 state machine */ typedef enum { N775_OK = 0, /*!< N775 --> ok */ @@ -223,7 +185,7 @@ typedef struct { DATA_BLOCK_SLAVE_CONTROL_s *slaveControl; DATA_BLOCK_OPEN_WIRE_s *openWire; /* Wie genau open wire check behandeln? Was genau abspeichern? */ N775_SUPPLY_CURRENT_s *supplyCurrent; - N775_ERRORTABLE_s *errorTable; + N775_ERROR_TABLE_s *errorTable; uint64_t uid[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]; } N775_DATAPTR_s; diff --git a/src/app/driver/afe/nxp/mc33775a/wscript b/src/app/driver/afe/nxp/mc33775a/wscript index 2ada406a..6616571c 100644 --- a/src/app/driver/afe/nxp/mc33775a/wscript +++ b/src/app/driver/afe/nxp/mc33775a/wscript @@ -65,19 +65,12 @@ def build(bld): os.path.join("..", "api", "nxp_afe.c"), os.path.join("api", "nxp_mc33775a_afe.c"), os.path.join("nxp_afe_dma.c"), - os.path.join("config", "nxp_afe_dma_cfg.c"), os.path.join("nxp_mc33775a.c"), os.path.join("nxp_mc33775a-ll.c"), os.path.join("config", "nxp_mc33775a_cfg.c"), os.path.join("vendor", "uc_msg_t.c"), ] includes = [ - ".", - os.path.join("api"), - os.path.join("config"), - os.path.join("vendor"), - os.path.join("..", "api"), - os.path.join("..", "..", "api"), os.path.join("..", "..", "..", "config"), os.path.join("..", "..", "..", "dma"), os.path.join("..", "..", "..", "foxmath"), @@ -98,6 +91,7 @@ def build(bld): os.path.join("..", "..", "..", "..", "task", "ftask"), os.path.join("..", "..", "..", "..", "task", "os"), ] + includes.extend(bld.env.INCLUDES_AFE) includes.extend(bld.env.INCLUDES_RTOS) cflags = bld.env.CFLAGS_FOXBMS target = f"{bld.env.APPNAME.lower()}-afe-driver" diff --git a/src/app/driver/afe/nxp/wscript b/src/app/driver/afe/nxp/wscript index abec6262..f94f4a56 100644 --- a/src/app/driver/afe/nxp/wscript +++ b/src/app/driver/afe/nxp/wscript @@ -38,7 +38,9 @@ # - "This product includes parts of foxBMS®" # - "This product is derived from foxBMS®" -"""TODO""" +"""Helper Build Script: ./src/app/driver/afe/nxp + +Helper script to recursively build the variant of the NXP AFE""" def build(bld): diff --git a/src/app/driver/afe/ti/README.md b/src/app/driver/afe/ti/README.md new file mode 100644 index 00000000..3ac8abb3 --- /dev/null +++ b/src/app/driver/afe/ti/README.md @@ -0,0 +1,45 @@ +# TI AFE Support + +The foxBMS project supports the following TI AFEs + +- [Dummy](#dummy) (API reference implementation; **non functional**) + +This document is just there to provide a short overview. +For detailed information please see the documentation. + +## Common + +- AFE DMA API implementation + [``src/app/driver/afe/api/afe_dma.h``](../api/afe_dma.h): + + Common implementation for all TI AFEs. + Defined at [``src/app/driver/afe/ti/common/api/ti_bq79xxx_afe_dma.c``](common/api/ti_bq79xxx_afe_dma.c) + +- AFE API implementation + [``src/app/driver/afe/api/afe.h``](../api/afe.h): + + Implementation of the **AFE** to **TI** wrapper: + + - [src/app/driver/afe/ti/api/ti_afe.c](api/ti_afe.c): + Defines the the ``AFE_*`` functions and wraps them to ``TI_*`` functions. + - [src/app/driver/afe/ti/api/ti_afe.h](api/ti_afe.h): Declares the ``TI_*`` + functions + +## Dummy + +- AFE DMA API implementation: + + Implementation not required as there is a generic one (see + [Common](#common)). + +- TI AFE API implementation + [``src/app/driver/afe/ti/api/ti_afe.h``](api/ti_afe.h): + + Implementation of the **TI** to **TIDUM** wrapper: + + - [src/app/driver/afe/ti/dummy/api/ti_dummy_afe.c](dummy/api/ti_dummy_afe.c): + Defines the ``TI_*`` functions and wraps them to ``TIDUM_*`` functions. + - [src/app/driver/afe/ti/dummy/ti_dummy.h](dummy/ti_dummy.h): + Declares the ``TIDUM_*`` functions. + - [src/app/driver/afe/ti/dummy/ti_dummy.c](dummy/ti_dummy.c): + Defines the ``TIDUM_*`` functions. diff --git a/src/app/driver/afe/ti/api/ti_afe.c b/src/app/driver/afe/ti/api/ti_afe.c new file mode 100644 index 00000000..a6a3f5f6 --- /dev/null +++ b/src/app/driver/afe/ti/api/ti_afe.c @@ -0,0 +1,130 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file ti_afe.c + * @author foxBMS Team + * @date 2020-05-25 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix AFE + * + * @brief AFE driver wrapper layer for TI ICs + */ + +/*========== Includes =======================================================*/ + +/* clang-format off */ +#include "afe.h" +/* clang-format on */ +#include "ti_afe.h" + +#include "battery_system_cfg.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +extern STD_RETURN_TYPE_e AFE_TriggerIc(void) { + return TI_Measure(); +} + +extern STD_RETURN_TYPE_e AFE_Initialize(void) { + return TI_Initialize(); +} + +extern STD_RETURN_TYPE_e AFE_RequestEepromRead(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TI_RequestEepromRead(string); +} + +extern STD_RETURN_TYPE_e AFE_RequestEepromWrite(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TI_RequestEepromWrite(string); +} + +extern STD_RETURN_TYPE_e AFE_RequestTemperatureRead(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TI_RequestTemperatureRead(string); +} + +extern STD_RETURN_TYPE_e AFE_RequestBalancingFeedbackRead(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TI_RequestBalancingFeedbackRead(string); +} + +extern STD_RETURN_TYPE_e AFE_RequestOpenWireCheck(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TI_RequestOpenWireCheck(string); +} + +extern STD_RETURN_TYPE_e AFE_StartMeasurement(void) { + return TI_StartMeasurement(); +} + +extern bool AFE_IsFirstMeasurementCycleFinished(void) { + return TI_IsFirstMeasurementCycleFinished(); +} + +extern STD_RETURN_TYPE_e AFE_RequestIoRead(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TI_RequestIoRead(string); +} + +STD_RETURN_TYPE_e AFE_RequestIoWrite(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TI_RequestIoWrite(string); +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/driver/afe/ti/api/ti_afe.h b/src/app/driver/afe/ti/api/ti_afe.h new file mode 100644 index 00000000..2d8cdc5d --- /dev/null +++ b/src/app/driver/afe/ti/api/ti_afe.h @@ -0,0 +1,154 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file ti_afe.h + * @author foxBMS Team + * @date 2023-09-12 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix TID + * + * @brief AFE driver wrapper layer for TI ICs + */ + +#ifndef FOXBMS__TI_AFE_H_ +#define FOXBMS__TI_AFE_H_ + +/*========== Includes =======================================================*/ +#include "fstd_types.h" + +/* clang-format off */ +#include "afe.h" +/* clang-format on */ + +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Extern Constant and Variable Declarations ======================*/ + +/*========== Extern Function Prototypes =====================================*/ + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_TriggerIc + */ +extern STD_RETURN_TYPE_e TI_Measure(void); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_Initialize + */ +extern STD_RETURN_TYPE_e TI_Initialize(void); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_RequestEepromRead + */ +extern STD_RETURN_TYPE_e TI_RequestEepromRead(uint8_t string); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_RequestEepromWrite + */ +extern STD_RETURN_TYPE_e TI_RequestEepromWrite(uint8_t string); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_RequestTemperatureRead + */ +extern STD_RETURN_TYPE_e TI_RequestTemperatureRead(uint8_t string); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_RequestBalancingFeedbackRead + */ +extern STD_RETURN_TYPE_e TI_RequestBalancingFeedbackRead(uint8_t string); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_RequestOpenWireCheck + */ +extern STD_RETURN_TYPE_e TI_RequestOpenWireCheck(uint8_t string); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_StartMeasurement + */ +extern STD_RETURN_TYPE_e TI_StartMeasurement(void); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_IsFirstMeasurementCycleFinished + */ +extern bool TI_IsFirstMeasurementCycleFinished(void); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_RequestIoRead + */ +extern STD_RETURN_TYPE_e TI_RequestIoRead(uint8_t string); + +/** + * @brief This function is used to wrap the TI AFE measurement API to the + * generic AFE measurement API + * @details This function is used to wrap #AFE_RequestIoWrite + */ +STD_RETURN_TYPE_e TI_RequestIoWrite(uint8_t string); + +/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ +#ifdef UNITY_UNIT_TEST +#endif + +#endif /* FOXBMS__TI_AFE_H_ */ diff --git a/src/app/driver/afe/ti/api/wscript b/src/app/driver/afe/ti/api/wscript new file mode 100644 index 00000000..fa0ba50e --- /dev/null +++ b/src/app/driver/afe/ti/api/wscript @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Build Script: ./src/app/driver/afe/ti/api""" + +import os + + +def build(bld): + """builds the AFE API driver objects for all TI drivers""" + source = [os.path.join("ti_afe.c")] + includes = [ + os.path.join("..", "..", "..", "..", "application", "config"), + os.path.join("..", "..", "..", "..", "main", "include"), + ] + includes.extend(bld.env.INCLUDES_AFE) + cflags = bld.env.CFLAGS_FOXBMS + target = f"{bld.env.APPNAME.lower()}-afe-ti-api" + bld.stlib(source=source, includes=includes, cflags=cflags, target=target) diff --git a/src/app/driver/afe/ti/common/api/ti_bq79xxx_afe_dma.c b/src/app/driver/afe/ti/common/api/ti_bq79xxx_afe_dma.c new file mode 100644 index 00000000..12c7013c --- /dev/null +++ b/src/app/driver/afe/ti/common/api/ti_bq79xxx_afe_dma.c @@ -0,0 +1,82 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file ti_bq79xxx_afe_dma.c + * @author foxBMS Team + * @date 2023-09-11 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix AFE + * + * @brief Driver for the DMA module for the TI driver. + * + */ + +/*========== Includes =======================================================*/ +#include "dma_cfg.h" + +#include "afe_dma.h" +#include "ftask.h" +#include "spi.h" + +#include + +/*========== Macros and Definitions =========================================*/ +#define TI_SPI_INDEX (SPI_SPI1_INDEX) + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +/* Function called on DMA complete interrupts (TX and RX). */ +void AFE_DmaCallback(uint8_t spiIndex) { + FAS_ASSERT(spiIndex == TI_SPI_INDEX); +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ diff --git a/src/app/driver/afe/ti/common/wscript b/src/app/driver/afe/ti/common/wscript new file mode 100644 index 00000000..b48adb57 --- /dev/null +++ b/src/app/driver/afe/ti/common/wscript @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Build Script: ./src/app/driver/afe/ti/common""" + +import os + + +def build(bld): + """builds the common TI AFE driver objects""" + source = [os.path.join("api", "ti_bq79xxx_afe_dma.c")] + includes = [ + os.path.join("..", "..", "..", "..", "task", "config"), + os.path.join("..", "..", "..", "..", "task", "ftask"), + os.path.join("..", "..", "..", "..", "task", "os"), + os.path.join("..", "..", "..", "..", "application", "config"), + os.path.join("..", "..", "..", "..", "engine", "config"), + os.path.join("..", "..", "..", "..", "engine", "database"), + os.path.join("..", "..", "..", "..", "main", "include"), + os.path.join("..", "..", "..", "config"), + os.path.join("..", "..", "..", "spi"), + os.path.join("..", "..", "..", "rtc"), + os.path.join("..", "..", "..", "mcu"), + ] + includes.extend(bld.env.INCLUDES_RTOS + bld.env.INCLUDES_AFE) + cflags = bld.env.CFLAGS_FOXBMS + target = f"{bld.env.APPNAME.lower()}-afe-ti-common" + bld.stlib(source=source, includes=includes, cflags=cflags, target=target) diff --git a/src/app/driver/config/interlock_cfg.c b/src/app/driver/afe/ti/dummy/api/ti_dummy_afe.c similarity index 61% rename from src/app/driver/config/interlock_cfg.c rename to src/app/driver/afe/ti/dummy/api/ti_dummy_afe.c index a6749a90..52c01f2b 100644 --- a/src/app/driver/config/interlock_cfg.c +++ b/src/app/driver/afe/ti/dummy/api/ti_dummy_afe.c @@ -40,20 +40,23 @@ */ /** - * @file interlock_cfg.c + * @file ti_dummy_afe.c * @author foxBMS Team - * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2023-09-11 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION - * @prefix CONT + * @prefix TI * - * @brief Configuration for the driver for the interlock. + * @brief Configuration for the TI dummy analog front-end * */ /*========== Includes =======================================================*/ -#include "interlock_cfg.h" +#include "ti_afe.h" +#include "ti_dummy.h" + +#include "afe_dma.h" #include @@ -69,6 +72,57 @@ /*========== Extern Function Implementations ================================*/ +extern STD_RETURN_TYPE_e TI_Measure(void) { + return TIDUM_Measure(); +} + +extern STD_RETURN_TYPE_e TI_Initialize(void) { + return TIDUM_Initialize(); +} + +extern STD_RETURN_TYPE_e TI_RequestEepromRead(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TIDUM_RequestEepromRead(string); +} + +extern STD_RETURN_TYPE_e TI_RequestEepromWrite(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TIDUM_RequestEepromWrite(string); +} + +extern STD_RETURN_TYPE_e TI_RequestTemperatureRead(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TIDUM_RequestTemperatureRead(string); +} + +extern STD_RETURN_TYPE_e TI_RequestBalancingFeedbackRead(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TIDUM_RequestBalancingFeedbackRead(string); +} + +extern STD_RETURN_TYPE_e TI_RequestOpenWireCheck(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TIDUM_RequestOpenWireCheck(string); +} + +extern STD_RETURN_TYPE_e TI_StartMeasurement(void) { + return TIDUM_StartMeasurement(); +} + +extern bool TI_IsFirstMeasurementCycleFinished(void) { + return TIDUM_IsFirstMeasurementCycleFinished(); +} + +extern STD_RETURN_TYPE_e TI_RequestIoRead(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TIDUM_RequestIoRead(string); +} + +STD_RETURN_TYPE_e TI_RequestIoWrite(uint8_t string) { + FAS_ASSERT(string < BS_NR_OF_STRINGS); + return TIDUM_RequestIoWrite(string); +} + /*========== Externalized Static Function Implementations (Unit Test) =======*/ #ifdef UNITY_UNIT_TEST #endif diff --git a/src/app/driver/afe/ti/dummy/ti_dummy.c b/src/app/driver/afe/ti/dummy/ti_dummy.c new file mode 100644 index 00000000..8a967dee --- /dev/null +++ b/src/app/driver/afe/ti/dummy/ti_dummy.c @@ -0,0 +1,127 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file ti_dummy.c + * @author foxBMS Team + * @date 2023-09-11 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS_CONFIGURATION + * @prefix TIDUM + * + * @brief Configuration for the TI dummy analog front-end + * + */ + +/*========== Includes =======================================================*/ +/* clang-format off */ +#include "afe.h" +/* clang-format on */ +#include "ti_dummy.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ +extern STD_RETURN_TYPE_e TIDUM_Measure(void) { + return STD_OK; +} + +extern STD_RETURN_TYPE_e TIDUM_Initialize(void) { + return STD_OK; +} + +extern STD_RETURN_TYPE_e TIDUM_RequestEepromRead(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + return STD_OK; +} + +extern STD_RETURN_TYPE_e TIDUM_RequestEepromWrite(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + return STD_OK; +} + +extern STD_RETURN_TYPE_e TIDUM_RequestTemperatureRead(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + return STD_OK; +} + +extern STD_RETURN_TYPE_e TIDUM_RequestBalancingFeedbackRead(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + return STD_OK; +} + +extern STD_RETURN_TYPE_e TIDUM_RequestOpenWireCheck(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + return STD_OK; +} + +extern STD_RETURN_TYPE_e TIDUM_StartMeasurement(void) { + return STD_OK; +} + +extern bool TIDUM_IsFirstMeasurementCycleFinished(void) { + return true; +} + +extern STD_RETURN_TYPE_e TIDUM_RequestIoRead(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + return STD_OK; +} + +extern STD_RETURN_TYPE_e TIDUM_RequestIoWrite(uint8_t string) { + /* AXIVION Routine Generic-MissingParameterAssert: string: parameter accepts whole range */ + return STD_OK; +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/driver/afe/debug/default/api/debug_default_afe_dma.h b/src/app/driver/afe/ti/dummy/ti_dummy.h similarity index 70% rename from src/app/driver/afe/debug/default/api/debug_default_afe_dma.h rename to src/app/driver/afe/ti/dummy/ti_dummy.h index 06b8d92a..bb956083 100644 --- a/src/app/driver/afe/debug/default/api/debug_default_afe_dma.h +++ b/src/app/driver/afe/ti/dummy/ti_dummy.h @@ -40,25 +40,26 @@ */ /** - * @file debug_default_afe_dma.h + * @file ti_dummy.h * @author foxBMS Team - * @date 2020-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup DRIVERS - * @prefix FAKE + * @date 2023-09-11 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS_CONFIGURATION + * @prefix TIDUM * - * @brief Header for the driver for the DMA module for the fake AFE - * driver + * @brief Configuration for the TI dummy analog front-end * */ -#ifndef FOXBMS__DEBUG_DEFAULT_AFE_DMA_H_ -#define FOXBMS__DEBUG_DEFAULT_AFE_DMA_H_ +#ifndef FOXBMS__TI_DUMMY_H_ +#define FOXBMS__TI_DUMMY_H_ /*========== Includes =======================================================*/ +#include "fstd_types.h" + /* clang-format off */ -#include "afe_dma.h" +#include "ti_afe.h" /* clang-format on */ #include @@ -68,9 +69,20 @@ /*========== Extern Constant and Variable Declarations ======================*/ /*========== Extern Function Prototypes =====================================*/ +extern STD_RETURN_TYPE_e TIDUM_Measure(void); +extern STD_RETURN_TYPE_e TIDUM_Initialize(void); +extern STD_RETURN_TYPE_e TIDUM_RequestEepromRead(uint8_t string); +extern STD_RETURN_TYPE_e TIDUM_RequestEepromWrite(uint8_t string); +extern STD_RETURN_TYPE_e TIDUM_RequestTemperatureRead(uint8_t string); +extern STD_RETURN_TYPE_e TIDUM_RequestBalancingFeedbackRead(uint8_t string); +extern STD_RETURN_TYPE_e TIDUM_RequestOpenWireCheck(uint8_t string); +extern STD_RETURN_TYPE_e TIDUM_StartMeasurement(void); +extern bool TIDUM_IsFirstMeasurementCycleFinished(void); +extern STD_RETURN_TYPE_e TIDUM_RequestIoRead(uint8_t string); +extern STD_RETURN_TYPE_e TIDUM_RequestIoWrite(uint8_t string); /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST #endif -#endif /* FOXBMS__DEBUG_DEFAULT_AFE_DMA_H_ */ +#endif /* FOXBMS__TI_DUMMY_H_ */ diff --git a/src/app/driver/afe/ti/dummy/ti_dummy.json b/src/app/driver/afe/ti/dummy/ti_dummy.json new file mode 100644 index 00000000..fcbdc6ac --- /dev/null +++ b/src/app/driver/afe/ti/dummy/ti_dummy.json @@ -0,0 +1,9 @@ +{ + "include": [ + ".", + "api", + "../api", + "../common", + "../../api" + ] +} diff --git a/src/app/driver/afe/ti/dummy/wscript b/src/app/driver/afe/ti/dummy/wscript new file mode 100644 index 00000000..9a6171e7 --- /dev/null +++ b/src/app/driver/afe/ti/dummy/wscript @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Build Script: ./src/app/driver/afe/ti/dummy""" + +import os + + +def build(bld): + """builds the AFE driver library for TI dummy""" + source = [ + os.path.join("ti_dummy.c"), + os.path.join("api", "ti_dummy_afe.c"), + ] + includes = [ + os.path.join("..", "..", "..", "config"), + os.path.join("..", "..", "..", "dma"), + os.path.join("..", "..", "..", "io"), + os.path.join("..", "..", "..", "mcu"), + os.path.join("..", "..", "..", "rtc"), + os.path.join("..", "..", "..", "spi"), + os.path.join("..", "..", "..", "ts"), + os.path.join("..", "..", "..", "ts", "api"), + os.path.join("..", "..", "..", "..", "application", "config"), + os.path.join("..", "..", "..", "..", "engine", "config"), + os.path.join("..", "..", "..", "..", "engine", "database"), + os.path.join("..", "..", "..", "..", "engine", "diag"), + os.path.join("..", "..", "..", "..", "main", "include"), + os.path.join("..", "..", "..", "..", "task", "config"), + os.path.join("..", "..", "..", "..", "task", "config"), + os.path.join("..", "..", "..", "..", "task", "ftask"), + os.path.join("..", "..", "..", "..", "task", "os"), + ] + includes.extend(bld.env.INCLUDES_AFE) + includes.extend(bld.env.INCLUDES_RTOS) + use = [ + f"{bld.env.APPNAME.lower()}-afe-ti-api", + f"{bld.env.APPNAME.lower()}-afe-ti-common", + ] + cflags = bld.env.CFLAGS_FOXBMS + target = f"{bld.env.APPNAME.lower()}-afe-driver" + bld.stlib( + source=source, + includes=includes, + use=use, + cflags=cflags, + target=target, + ) diff --git a/src/app/driver/afe/ti/wscript b/src/app/driver/afe/ti/wscript new file mode 100644 index 00000000..8dd4235e --- /dev/null +++ b/src/app/driver/afe/ti/wscript @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Build Script: ./src/app/driver/afe/ti""" + + +def build(bld): + """selects the driver library to be build""" + bld.recurse([bld.env.afe_ic, "api", "common"]) diff --git a/src/app/driver/can/can.c b/src/app/driver/can/can.c index a75edb3c..3e3bc741 100644 --- a/src/app/driver/can/can.c +++ b/src/app/driver/can/can.c @@ -43,8 +43,8 @@ * @file can.c * @author foxBMS Team * @date 2019-12-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CAN * @@ -135,6 +135,10 @@ static CAN_STATE_s can_state = { .currentSensorECPresent = {GEN_REPEAT_U(false, GEN_STRIP(BS_NR_OF_STRINGS))}, }; +/** stores the number of CAN_periodicTransmit calls at which the internal + * counter will reset to prevent overflow in CAN_IsPeriodElapsed */ +static uint32_t can_counterResetValue = 0u; + /*========== Extern Constant and Variable Definitions =======================*/ /*========== Static Function Prototypes =====================================*/ @@ -168,6 +172,16 @@ static void CAN_RxInterrupt(canBASE_t *pNode, uint32 messageBox); */ static STD_RETURN_TYPE_e CAN_PeriodicTransmit(void); +/** + * @brief Checks if a configured period CAN message should be transmitted depending + * on the configured message period and message phase. + * @param ticksSinceStart internal counter of a periodically called function + * @param messageIndex index of the message to check in the tx message array + * @return true if phase matches and message should be transmitted, false otherwise +*/ + +static bool CAN_IsMessagePeriodElapsed(uint32_t ticksSinceStart, uint16_t messageIndex); + /** * @brief Checks if the CAN messages come in the specified time window * @details The time delta where a message is expected to be received needs to @@ -225,9 +239,25 @@ static void CAN_ConfigureRxMailboxesForExtendedIdentifiers(void); /** initialize the SPI interface to the CAN transceiver */ static void CAN_InitializeTransceiver(void); +/** + * @brief Calculate Reset Value for internal counter in CAN_PeriodicTransmit + * @details Calculate the least common multiply of message periods in + * can_TxMessages array. All periods will elapse at this time, so the + * counter can safely be reset. + * @return Reset Value for internal counter in CAN_PeriodicTransmit + */ +static uint32_t CAN_CalculateCounterResetValue(void); + /** checks that the configured message period for Tx messages is valid */ static void CAN_ValidateConfiguredTxMessagePeriod(void); +/** checks that the configured message phase for Tx messages is valid */ +static void CAN_ValidateConfiguredTxMessagePhase(void); + +/** checks the struct block for storing and passing on the local + * database table handle for containing no null pointers*/ +static void CAN_CheckDatabaseNullPointer(CAN_SHIM_s canShim); + /** * @brief get pointer CAN node configuration struct from register address * @param pNodeRegister pointer to CAN node hardware register address @@ -547,13 +577,42 @@ static void CAN_InitializeTransceiver(void) { } static void CAN_ValidateConfiguredTxMessagePeriod(void) { - for (uint16_t i = 0u; i < can_txLength; i++) { - if (can_txMessages[i].timing.period == 0u) { + for (uint16_t i = 0u; i < can_txMessagesLength; i++) { + if ((can_txMessages[i].timing.period == 0u) || ((can_txMessages[i].timing.period % CAN_TICK_ms) != 0u)) { + FAS_ASSERT(FAS_TRAP); + } + } +} + +static void CAN_ValidateConfiguredTxMessagePhase(void) { + for (uint16_t i = 0u; i < can_txMessagesLength; i++) { + if ((can_txMessages[i].timing.phase >= can_txMessages[i].timing.period) || + ((can_txMessages[i].timing.phase % CAN_TICK_ms) != 0u)) { FAS_ASSERT(FAS_TRAP); } } } +static void CAN_CheckDatabaseNullPointer(CAN_SHIM_s canShim) { + FAS_ASSERT(canShim.pQueueImd != NULL_PTR); + FAS_ASSERT(canShim.pTableCellVoltage != NULL_PTR); /*!< pointer database table with cell voltages */ + FAS_ASSERT(canShim.pTableCellTemperature != NULL_PTR); /*!< pointer database table with cell temperatures */ + FAS_ASSERT(canShim.pTableCurrentSensor != NULL_PTR); /*!< pointer database table with current sensor measurements */ + FAS_ASSERT(canShim.pTableErrorState != NULL_PTR); /*!< pointer database table with error state variables */ + FAS_ASSERT(canShim.pTableInsulation != NULL_PTR); /*!< pointer database table with insulation monitoring info */ + FAS_ASSERT(canShim.pTableMinMax != NULL_PTR); /*!< pointer database table with min/max values */ + FAS_ASSERT(canShim.pTableMol != NULL_PTR); /*!< pointer database table with MOL flags */ + FAS_ASSERT(canShim.pTableMsl != NULL_PTR); /*!< pointer database table with MSL flags */ + FAS_ASSERT(canShim.pTableOpenWire != NULL_PTR); /*!< pointer database table with open wire status */ + FAS_ASSERT(canShim.pTablePackValues != NULL_PTR); /*!< pointer database table with pack values */ + FAS_ASSERT(canShim.pTableRsl != NULL_PTR); /*!< pointer database table with RSL flags */ + FAS_ASSERT(canShim.pTableSoc != NULL_PTR); /*!< pointer database table with SOC values */ + FAS_ASSERT(canShim.pTableSoe != NULL_PTR); /*!< pointer database table with SOE values */ + FAS_ASSERT(canShim.pTableSof != NULL_PTR); /*!< pointer database table with SOF values */ + FAS_ASSERT(canShim.pTableSoh != NULL_PTR); /*!< pointer database table with SOH values */ + FAS_ASSERT(canShim.pTableStateRequest != NULL_PTR); /*!< pointer database table with state requests */ +} + static CAN_NODE_s *CAN_GetNodeConfigurationStructFromRegisterAddress(canBASE_t *pNodeRegister) { FAS_ASSERT(pNodeRegister != NULL_PTR); CAN_NODE_s *node = NULL_PTR; @@ -625,22 +684,102 @@ static STD_RETURN_TYPE_e CAN_PeriodicTransmit(void) { static uint32_t counterTicks = 0; uint8_t data[CAN_MAX_DLC] = {0}; - for (uint16_t i = 0u; i < can_txLength; i++) { - if (((counterTicks * CAN_TICK_ms) % (can_txMessages[i].timing.period)) == can_txMessages[i].timing.phase) { + CAN_SendMessagesFromQueue(); + + for (uint16_t i = 0u; i < can_txMessagesLength; i++) { + if (CAN_IsMessagePeriodElapsed(counterTicks, i) == true) { if (can_txMessages[i].callbackFunction != NULL_PTR) { can_txMessages[i].callbackFunction( can_txMessages[i].message, data, can_txMessages[i].pMuxId, &can_kShim); - /* CAN messages are currently discarded if all message boxes - * are full. They will not be retransmitted within the next - * call of CAN_PeriodicTransmit() */ - CAN_DataSend( - can_txMessages[i].canNode, can_txMessages[i].message.id, can_txMessages[i].message.idType, data); + if (CAN_DataSend( + can_txMessages[i].canNode, + can_txMessages[i].message.id, + can_txMessages[i].message.idType, + data) != STD_OK) { + /* message was not sent */ + /* store the message */ + CAN_BUFFER_ELEMENT_s unsentMessage = { + .canNode = can_txMessages[i].canNode, + .id = can_txMessages[i].message.id, + .idType = can_txMessages[i].message.idType, + .data = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}; + + for (uint8_t j = 0; j < can_txMessages[i].message.dlc; j++) { + unsentMessage.data[j] = data[j]; + } + + /* add message to queue */ + if (OS_SendToBackOfQueue(ftsk_canTxUnsentMessagesQueue, (void *)&unsentMessage, 0u) == OS_SUCCESS) { + /* Queue is not full */ + (void)DIAG_Handler(DIAG_ID_CAN_TX_QUEUE_FULL, DIAG_EVENT_OK, DIAG_SYSTEM, 0u); + } else { + /* Queue is full */ + (void)DIAG_Handler(DIAG_ID_CAN_TX_QUEUE_FULL, DIAG_EVENT_NOT_OK, DIAG_SYSTEM, 0u); + } + } retVal = STD_OK; } } } + /* check if counter needs to be reset */ counterTicks++; + if (counterTicks == can_counterResetValue) { + counterTicks = 0; + } + + return retVal; +} + +static uint32_t CAN_CalculateCounterResetValue(void) { + /* initialize with first array entry for first iteration */ + uint32_t resetValue = can_txMessages[0].timing.period; + + /* calculate least common multiple (LCM) of the first and second can_TxMessage period. + After that, calculate LCM of the next can_TxMessage period and last iterations LCM + until no more can_TxMessages remain. */ + for (uint8_t i = 1u; i < can_txMessagesLength; i++) { + const uint32_t value1 = resetValue; + const uint32_t value2 = can_txMessages[i].timing.period; + + /* calculate greatest common divisor using Euclid's algorithm */ + /* the algorithm is designed for starting with bigger value, but also + works when starting with smaller value, so just start with value1 */ + + uint32_t result = value1; + uint32_t divisor = value2; + uint32_t tempValue = 0u; + + while (divisor != 0u) { + tempValue = result % divisor; + result = divisor; + divisor = tempValue; + } + + /* calculate least common multiple using the greatest common divisor */ + resetValue = (value1 / result) * value2; + /* AXIVION Routine FaultDetection-DivisionByZero: /: message periods cannot be 0, so result is never 0 */ + /* AXIVION Routine MisraC2012Directive-4.1: /: message periods cannot be 0, so result is never 0 */ + /* AXIVION Routine MisraC2012Directive-4.1: *: only wraps around if periods are too big */ + } + + /* scale down to match internal counter of CAN_PeriodicTransmit */ + resetValue /= CAN_TICK_ms; + return resetValue; +} + +static bool CAN_IsMessagePeriodElapsed(uint32_t ticksSinceStart, uint16_t messageIndex) { + /* AXIVION Routine Generic-MissingParameterAssert: ticksSinceStart: parameter accepts whole range */ + FAS_ASSERT(messageIndex < can_txMessagesLength); + + bool retVal = false; + if (((ticksSinceStart * CAN_TICK_ms) % (can_txMessages[messageIndex].timing.period)) == + can_txMessages[messageIndex].timing.phase) { + /* AXIVION Routine MisraC2012Directive-4.1: *: counter gets reset in periodicTransmit, no wrap around */ + /* AXIVION Routine FaultDetection-DivisionByZero: %: message period is never zero, checked by config */ + /* AXIVION Routine MisraC2012Directive-4.1: %: message period is never zero, checked by config */ + retVal = true; + } return retVal; } @@ -775,7 +914,10 @@ extern void CAN_Initialize(void) { /* PEX pins are used for transceiver configuration -> I2C and port expander * needs to be initialized previously for a successful initialization. */ CAN_InitializeTransceiver(); + can_counterResetValue = CAN_CalculateCounterResetValue(); CAN_ValidateConfiguredTxMessagePeriod(); + CAN_ValidateConfiguredTxMessagePhase(); + CAN_CheckDatabaseNullPointer(can_kShim); } extern STD_RETURN_TYPE_e CAN_DataSend(CAN_NODE_s *pNode, uint32_t id, CAN_IDENTIFIER_TYPE_e idType, uint8 *pData) { @@ -821,6 +963,21 @@ extern STD_RETURN_TYPE_e CAN_DataSend(CAN_NODE_s *pNode, uint32_t id, CAN_IDENTI return result; } +extern void CAN_SendMessagesFromQueue(void) { + CAN_BUFFER_ELEMENT_s message = {NULL_PTR, 0u, CAN_INVALID_TYPE, {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}; + + while (OS_ReceiveFromQueue(ftsk_canTxUnsentMessagesQueue, (void *)&message, 0u) == OS_SUCCESS) { + /* Queue was not empty */ + if (CAN_DataSend(message.canNode, message.id, message.idType, message.data) == STD_NOT_OK) { + /* Message was not sent */ + if (OS_SendToBackOfQueue(ftsk_canTxUnsentMessagesQueue, (void *)&message, 0u) == OS_FAIL) { + /* Queue is full. */ + } + break; + } + } +} + extern void CAN_MainFunction(void) { CAN_CheckCanTiming(); if (can_state.periodicEnable == true) { @@ -833,7 +990,7 @@ extern void CAN_ReadRxBuffer(void) { CAN_BUFFER_ELEMENT_s can_rxBuffer = {NULL_PTR, 0u, CAN_INVALID_TYPE, {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}; while (OS_ReceiveFromQueue(ftsk_canRxQueue, (void *)&can_rxBuffer, 0u) == OS_SUCCESS) { /* data queue was not empty */ - for (uint16_t i = 0u; i < can_rxLength; i++) { + for (uint16_t i = 0u; i < can_rxMessagesLength; i++) { if ((can_rxBuffer.canNode == can_rxMessages[i].canNode) && (can_rxBuffer.id == can_rxMessages[i].message.id) && (can_rxBuffer.idType == can_rxMessages[i].message.idType)) { @@ -890,4 +1047,54 @@ void UNIT_TEST_WEAK_IMPL canMessageNotification(canBASE_t *node, uint32 messageB extern CAN_STATE_s *TEST_CAN_GetCANState(void) { return &can_state; } +extern void TEST_CAN_ValidateConfiguredTxMessagePeriod(void) { + CAN_ValidateConfiguredTxMessagePeriod(); +} +extern void TEST_CAN_ValidateConfiguredTxMessagePhase(void) { + CAN_ValidateConfiguredTxMessagePhase(); +} +extern void TEST_CAN_CheckDatabaseNullPointer(CAN_SHIM_s canShim) { + CAN_CheckDatabaseNullPointer(canShim); +} +extern void TEST_CAN_TxInterrupt(canBASE_t *pNode, uint32 messageBox) { + CAN_TxInterrupt(pNode, messageBox); +} +extern void TEST_CAN_RxInterrupt(canBASE_t *pNode, uint32 messageBox) { + CAN_RxInterrupt(pNode, messageBox); +} +extern STD_RETURN_TYPE_e TEST_CAN_PeriodicTransmit(void) { + return CAN_PeriodicTransmit(); +} +extern uint32_t TEST_CAN_CalculateCounterResetValue(void) { + return CAN_CalculateCounterResetValue(); +} +extern void TEST_CAN_CheckCanTiming(void) { + CAN_CheckCanTiming(); +} +extern bool TEST_CAN_IsMessagePeriodElapsed(uint32_t ticksSinceStart, uint16_t messageIndex) { + return CAN_IsMessagePeriodElapsed(ticksSinceStart, messageIndex); +} +#if BS_CURRENT_SENSOR_PRESENT == true +extern void TEST_CAN_SetCurrentSensorPresent(bool command, uint8_t stringNumber) { + CAN_SetCurrentSensorPresent(command, stringNumber); +} +extern void TEST_CAN_SetCurrentSensorCcPresent(bool command, uint8_t stringNumber) { + CAN_SetCurrentSensorCcPresent(command, stringNumber); +} +extern void TEST_CAN_SetCurrentSensorEcPresent(bool command, uint8_t stringNumber) { + CAN_SetCurrentSensorEcPresent(command, stringNumber); +} +extern void TEST_CAN_CheckCanTimingOfCurrentSensor(void) { + CAN_CheckCanTimingOfCurrentSensor(); +} +#endif /* BS_CURRENT_SENSOR_PRESENT == true */ +extern void TEST_CAN_ConfigureRxMailboxesForExtendedIdentifiers(void) { + CAN_ConfigureRxMailboxesForExtendedIdentifiers(); +} +extern void TEST_CAN_InitializeTransceiver(void) { + CAN_InitializeTransceiver(); +} +extern CAN_NODE_s *TEST_CAN_GetNodeConfigurationStructFromRegisterAddress(canBASE_t *pNodeRegister) { + return CAN_GetNodeConfigurationStructFromRegisterAddress(pNodeRegister); +} #endif diff --git a/src/app/driver/can/can.h b/src/app/driver/can/can.h index 33045b42..bf06236d 100644 --- a/src/app/driver/can/can.h +++ b/src/app/driver/can/can.h @@ -43,8 +43,8 @@ * @file can.h * @author foxBMS Team * @date 2019-12-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CAN * @@ -102,6 +102,11 @@ typedef struct { */ extern STD_RETURN_TYPE_e CAN_DataSend(CAN_NODE_s *pNode, uint32_t id, CAN_IDENTIFIER_TYPE_e idType, uint8 *pData); +/** + * @brief Reads messages from TX Queue and sends them via CAN. +*/ +extern void CAN_SendMessagesFromQueue(void); + /** * @brief Calls the functions to drive the CAN interface. * Makes the CAN timing checks and sends the periodic messages. @@ -155,6 +160,25 @@ extern bool CAN_IsCurrentSensorEcPresent(uint8_t stringNumber); /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST extern CAN_STATE_s *TEST_CAN_GetCANState(void); +extern void TEST_CAN_ValidateConfiguredTxMessagePeriod(void); +extern void TEST_CAN_ValidateConfiguredTxMessagePhase(void); +extern void TEST_CAN_CheckDatabaseNullPointer(CAN_SHIM_s canShim); +extern void TEST_CAN_TxInterrupt(canBASE_t *pNode, uint32 messageBox); +extern void TEST_CAN_RxInterrupt(canBASE_t *pNode, uint32 messageBox); +extern STD_RETURN_TYPE_e TEST_CAN_PeriodicTransmit(void); +extern uint32_t TEST_CAN_CalculateCounterResetValue(void); +extern void TEST_CAN_CheckCanTiming(void); +extern bool TEST_CAN_IsMessagePeriodElapsed(uint32_t ticksSinceStart, uint16_t messageIndex); +#if BS_CURRENT_SENSOR_PRESENT == true +extern void TEST_CAN_SetCurrentSensorPresent(bool command, uint8_t stringNumber); +extern void TEST_CAN_SetCurrentSensorCcPresent(bool command, uint8_t stringNumber); +extern void TEST_CAN_SetCurrentSensorEcPresent(bool command, uint8_t stringNumber); +extern void TEST_CAN_CheckCanTimingOfCurrentSensor(void); +#endif /* BS_CURRENT_SENSOR_PRESENT == true */ +extern void TEST_CAN_ConfigureRxMailboxesForExtendedIdentifiers(void); +extern void TEST_CAN_InitializeTransceiver(void); +extern CAN_NODE_s *TEST_CAN_GetNodeConfigurationStructFromRegisterAddress(canBASE_t *pNodeRegister); +extern STD_RETURN_TYPE_e TEST_CAN_PeriodicTransmit(void); #endif #endif /* FOXBMS__CAN_H_ */ diff --git a/src/app/driver/can/cbs/can_helper.c b/src/app/driver/can/cbs/can_helper.c index e5e8ed8e..f89cee63 100644 --- a/src/app/driver/can/cbs/can_helper.c +++ b/src/app/driver/can/cbs/can_helper.c @@ -43,8 +43,8 @@ * @file can_helper.c * @author foxBMS Team * @date 2021-04-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CAN * diff --git a/src/app/driver/can/cbs/can_helper.h b/src/app/driver/can/cbs/can_helper.h index f0df53c4..1435cbe8 100644 --- a/src/app/driver/can/cbs/can_helper.h +++ b/src/app/driver/can/cbs/can_helper.h @@ -43,8 +43,8 @@ * @file can_helper.h * @author foxBMS Team * @date 2021-04-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CAN * diff --git a/src/app/driver/can/cbs/rx/can_cbs_rx.h b/src/app/driver/can/cbs/rx/can_cbs_rx.h index 3361bb0c..5fcd8d43 100644 --- a/src/app/driver/can/cbs/rx/can_cbs_rx.h +++ b/src/app/driver/can/cbs/rx/can_cbs_rx.h @@ -43,8 +43,8 @@ * @file can_cbs_rx.h * @author foxBMS Team * @date 2021-04-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANRX * @@ -122,6 +122,17 @@ extern uint32_t CANRX_Debug( CAN_MESSAGE_PROPERTIES_s message, const uint8_t *const kpkCanData, const CAN_SHIM_s *const kpkCanShim); + +/** + * @brief can rx callback function for aerosol sensor messages + * @param[in] message contains the message ID, DLC and endianness + * @param[in] kpkCanData payload of can frame + * @param[in] kpkCanShim shim to the database entries + */ +extern uint32_t CANRX_AerosolSensor( + CAN_MESSAGE_PROPERTIES_s message, + const uint8_t *const kpkCanData, + const CAN_SHIM_s *const kpkCanShim); /**@}*/ /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ @@ -140,6 +151,7 @@ extern void TEST_CANRX_TriggerMcuUniqueDieIdMessage(void); extern void TEST_CANRX_TriggerMcuLotNumberMessage(void); extern void TEST_CANRX_TriggerMcuWaferInformationMessage(void); extern void TEST_CANRX_TriggerTimeInfoMessage(void); +extern void TEST_CANRX_TriggerCommitHashMessage(void); extern bool TEST_CANRX_CheckIfBmsSoftwareVersionIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness); extern bool TEST_CANRX_CheckIfMcuUniqueDieIdIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness); @@ -148,12 +160,18 @@ extern bool TEST_CANRX_CheckIfMcuWaferInformationIsRequested(uint64_t messageDat extern bool TEST_CANRX_CheckIfSoftwareResetIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness); extern bool TEST_CANRX_CheckIfFramInitializationIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness); extern bool TEST_CANRX_CheckIfTimeInfoIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness); +extern bool TEST_CANRX_CheckIfCommitHashIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness); extern void TEST_CANRX_ProcessVersionInformationMux(uint64_t messageData, CAN_ENDIANNESS_e endianness); extern void TEST_CANRX_ProcessRtcMux(uint64_t messageData, CAN_ENDIANNESS_e endianness); extern void TEST_CANRX_ProcessSoftwareResetMux(uint64_t messageData, CAN_ENDIANNESS_e endianness); extern void TEST_CANRX_ProcessFramInitializationMux(uint64_t messageData, CAN_ENDIANNESS_e endianness); extern void TEST_CANRX_ProcessTimeInfoMux(uint64_t messageData, CAN_ENDIANNESS_e endianness); + +extern void TEST_CANRX_HandleAerosolSensorErrors(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData); +extern void TEST_CANRX_HandleAerosolSensorStatus(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData); +extern void TEST_CANRX_SetParticulateMatterConcentration(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData); +extern void TEST_CANRX_SetAerosolSensorCrcCheckCode(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData); #endif #endif /* FOXBMS__CAN_CBS_RX_H_ */ diff --git a/src/app/driver/can/cbs/rx/can_cbs_rx_aerosol-sensor.c b/src/app/driver/can/cbs/rx/can_cbs_rx_aerosol-sensor.c new file mode 100644 index 00000000..27770b3a --- /dev/null +++ b/src/app/driver/can/cbs/rx/can_cbs_rx_aerosol-sensor.c @@ -0,0 +1,252 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file can_cbs_rx_aerosol-sensor.c + * @author foxBMS Team + * @date 2023-08-29 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANRX + * + * @brief CAN driver Rx callback implementation + * @details CAN Rx callback for aerosol sensor measurements + */ + +/*========== Includes =======================================================*/ +#include "can_cbs_rx.h" +#include "can_cfg_rx-message-definitions.h" +#include "can_helper.h" +#include "diag.h" + +#include + +/*========== Macros and Definitions =========================================*/ +/* configuration of the aerosol sensor message */ +#define CANRX_PARTICULAR_MATTER_CONCENTRATION_START_BIT (7u) +#define CANRX_PARTICULAR_MATTER_CONCENTRATION_LENGTH (16u) +#define CANRX_AEROSOL_SENSOR_STATUS_START_BIT (34u) +#define CANRX_AEROSOL_SENSOR_STATUS_LENGTH (3u) +#define CANRX_AEROSOL_SENSOR_FAULTS_START_BIT (39u) +#define CANRX_AEROSOL_SENSOR_FAULTS_LENGTH (5u) +#define CANRX_AEROSOL_SENSOR_CRC_CHECK_CODE_START_BIT (63u) +#define CANRX_AEROSOL_SENSOR_CRC_CHECK_CODE_LENGTH (8u) + +/* sensor status cases */ +#define CANRX_AEROSOL_SENSOR_STATUS_NORMAL (0u) +#define CANRX_AEROSOL_SENSOR_STATUS_ALARM (1u) + +/* sensor error cases */ +#define CANRX_AEROSOL_SENSOR_NO_ERROR (0u) +#define CANRX_AEROSOL_SENSOR_PHOTOELECTRIC_ERROR (1u) +#define CANRX_AEROSOL_SENSOR_VOLTAGE_SUPPLY_OVER_VOLTAGE_ERROR (2u) +#define CANRX_AEROSOL_SENSOR_VOLTAGE_SUPPLY_UNDER_VOLTAGE_ERROR (3u) + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ +/** + * @brief Sets error flags in database as received from can message + * @param kpkCanShim const pointer to can shim + * @param signalData data from can message that covers errors + */ +static void CANRX_HandleAerosolSensorErrors(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData); + +/** + * @brief Sets sensor status in database + * @param kpkCanShim const pointer to can shim + * @param signalData data from can message that covers status + */ +static void CANRX_HandleAerosolSensorStatus(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData); + +/** + * @brief Sets current particulate matter measurement value in database + * @param kpkCanShim const pointer to can shim + * @param signalData data from can message that covers particulate matter measurement + */ +static void CANRX_SetParticulateMatterConcentration(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData); + +/** + * @brief Sets CRC check code from sensor in database + * @param kpkCanShim const pointer to can shim + * @param signalData data from can message that covers crc check code + */ +static void CANRX_SetAerosolSensorCrcCheckCode(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData); + +/*========== Static Function Implementations ================================*/ +static void CANRX_HandleAerosolSensorErrors(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData) { + FAS_ASSERT(kpkCanShim != NULL_PTR); + FAS_ASSERT( + (signalData == CANRX_AEROSOL_SENSOR_NO_ERROR) || (signalData == CANRX_AEROSOL_SENSOR_PHOTOELECTRIC_ERROR) || + (signalData == CANRX_AEROSOL_SENSOR_VOLTAGE_SUPPLY_OVER_VOLTAGE_ERROR) || + (signalData == CANRX_AEROSOL_SENSOR_VOLTAGE_SUPPLY_UNDER_VOLTAGE_ERROR)); + switch (signalData) { + case CANRX_AEROSOL_SENSOR_NO_ERROR: /* resets error flags */ + kpkCanShim->pTableAerosolSensor->photoelectricError = false; + kpkCanShim->pTableAerosolSensor->supplyOvervoltageError = false; + kpkCanShim->pTableAerosolSensor->supplyUndervoltageError = false; + break; + case CANRX_AEROSOL_SENSOR_PHOTOELECTRIC_ERROR: /* sets flag for photoelectric device fault */ + kpkCanShim->pTableAerosolSensor->photoelectricError = true; + break; + case CANRX_AEROSOL_SENSOR_VOLTAGE_SUPPLY_OVER_VOLTAGE_ERROR: /* sets flag for voltage supply over voltage */ + kpkCanShim->pTableAerosolSensor->supplyOvervoltageError = true; + break; + case CANRX_AEROSOL_SENSOR_VOLTAGE_SUPPLY_UNDER_VOLTAGE_ERROR: /* sets flag for voltage supply under voltage */ + kpkCanShim->pTableAerosolSensor->supplyUndervoltageError = true; + break; + default: /* LCOV_EXCL_LINE */ + /* undefined value */ /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } +} + +static void CANRX_HandleAerosolSensorStatus(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData) { + FAS_ASSERT(kpkCanShim != NULL_PTR); + FAS_ASSERT((signalData == CANRX_AEROSOL_SENSOR_STATUS_NORMAL) || (signalData == CANRX_AEROSOL_SENSOR_STATUS_ALARM)); + + switch (signalData) { + case CANRX_AEROSOL_SENSOR_STATUS_NORMAL: /* set status to normal */ + kpkCanShim->pTableAerosolSensor->sensorStatus = 0u; + break; + case CANRX_AEROSOL_SENSOR_STATUS_ALARM: /* set status to alarm, update diag */ + kpkCanShim->pTableAerosolSensor->sensorStatus = 1u; + DIAG_Handler(DIAG_ID_AEROSOL_ALERT, DIAG_EVENT_NOT_OK, DIAG_SYSTEM, 0u); + break; + default: /* LCOV_EXCL_LINE */ + /* undefined value */ /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } +} + +static void CANRX_SetParticulateMatterConcentration(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData) { + FAS_ASSERT(kpkCanShim != NULL_PTR); + /* AXIVION Routine Generic-MissingParameterAssert: signalData: parameter accept whole range */ + /* set particulate matter concentration in database */ + kpkCanShim->pTableAerosolSensor->particulateMatterConcentration = signalData; +} + +static void CANRX_SetAerosolSensorCrcCheckCode(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData) { + FAS_ASSERT(kpkCanShim != NULL_PTR); + /* AXIVION Routine Generic-MissingParameterAssert: signalData: parameter accept whole range */ + /* set CRC check code in database */ + uint8_t data = (uint8_t)signalData; + kpkCanShim->pTableAerosolSensor->crcCheckCode = data; +} + +/*========== Extern Function Implementations ================================*/ +extern uint32_t CANRX_AerosolSensor( + CAN_MESSAGE_PROPERTIES_s message, + const uint8_t *const kpkCanData, + const CAN_SHIM_s *const kpkCanShim) { + FAS_ASSERT(message.id == CANRX_AEROSOL_SENSOR_ID); + FAS_ASSERT(message.idType == CANRX_AEROSOL_SENSOR_ID_TYPE); + FAS_ASSERT(message.dlc == CAN_DEFAULT_DLC); + FAS_ASSERT(kpkCanData != NULL_PTR); + FAS_ASSERT(kpkCanShim != NULL_PTR); + + uint64_t messageData = 0u; + uint64_t canSignal = 0u; + + CAN_RxGetMessageDataFromCanData(&messageData, kpkCanData, message.endianness); + + /* Handle error flags */ + CAN_RxGetSignalDataFromMessageData( + messageData, + CANRX_AEROSOL_SENSOR_FAULTS_START_BIT, + CANRX_AEROSOL_SENSOR_FAULTS_LENGTH, + &canSignal, + message.endianness); + uint16_t signalData = (uint16_t)canSignal; + CANRX_HandleAerosolSensorErrors(kpkCanShim, signalData); + + /* Set sensor status */ + CAN_RxGetSignalDataFromMessageData( + messageData, + CANRX_AEROSOL_SENSOR_STATUS_START_BIT, + CANRX_AEROSOL_SENSOR_STATUS_LENGTH, + &canSignal, + message.endianness); + signalData = (uint16_t)canSignal; + CANRX_HandleAerosolSensorStatus(kpkCanShim, signalData); + + /* Set data */ + CAN_RxGetSignalDataFromMessageData( + messageData, + CANRX_PARTICULAR_MATTER_CONCENTRATION_START_BIT, + CANRX_PARTICULAR_MATTER_CONCENTRATION_LENGTH, + &canSignal, + message.endianness); + signalData = (uint16_t)canSignal; + CANRX_SetParticulateMatterConcentration(kpkCanShim, signalData); + + /* Set CRC check code*/ + CAN_RxGetSignalDataFromMessageData( + messageData, + CANRX_AEROSOL_SENSOR_CRC_CHECK_CODE_START_BIT, + CANRX_AEROSOL_SENSOR_CRC_CHECK_CODE_LENGTH, + &canSignal, + message.endianness); + signalData = (uint16_t)canSignal; + CANRX_SetAerosolSensorCrcCheckCode(kpkCanShim, signalData); + + DATA_WRITE_DATA(kpkCanShim->pTableAerosolSensor); + return 0; +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +extern void TEST_CANRX_HandleAerosolSensorErrors(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData) { + CANRX_HandleAerosolSensorErrors(kpkCanShim, signalData); +} +extern void TEST_CANRX_HandleAerosolSensorStatus(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData) { + CANRX_HandleAerosolSensorStatus(kpkCanShim, signalData); +} +extern void TEST_CANRX_SetParticulateMatterConcentration(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData) { + CANRX_SetParticulateMatterConcentration(kpkCanShim, signalData); +} +extern void TEST_CANRX_SetAerosolSensorCrcCheckCode(const CAN_SHIM_s *const kpkCanShim, uint16_t signalData) { + CANRX_SetAerosolSensorCrcCheckCode(kpkCanShim, signalData); +} +#endif diff --git a/src/app/driver/can/cbs/rx/can_cbs_rx_state-request.c b/src/app/driver/can/cbs/rx/can_cbs_rx_bms-state-request.c similarity index 98% rename from src/app/driver/can/cbs/rx/can_cbs_rx_state-request.c rename to src/app/driver/can/cbs/rx/can_cbs_rx_bms-state-request.c index ccaa9443..289092da 100644 --- a/src/app/driver/can/cbs/rx/can_cbs_rx_state-request.c +++ b/src/app/driver/can/cbs/rx/can_cbs_rx_bms-state-request.c @@ -40,11 +40,11 @@ */ /** - * @file can_cbs_rx_state-request.c + * @file can_cbs_rx_bms-state-request.c * @author foxBMS Team * @date 2021-07-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANRX * diff --git a/src/app/driver/can/cbs/rx/can_cbs_rx_current-sensor.c b/src/app/driver/can/cbs/rx/can_cbs_rx_current-sensor.c index c96e93e6..ce87e1dc 100644 --- a/src/app/driver/can/cbs/rx/can_cbs_rx_current-sensor.c +++ b/src/app/driver/can/cbs/rx/can_cbs_rx_current-sensor.c @@ -43,8 +43,8 @@ * @file can_cbs_rx_current-sensor.c * @author foxBMS Team * @date 2021-04-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANRX * diff --git a/src/app/driver/can/cbs/rx/can_cbs_rx_debug.c b/src/app/driver/can/cbs/rx/can_cbs_rx_debug.c index 28410db7..fef09581 100644 --- a/src/app/driver/can/cbs/rx/can_cbs_rx_debug.c +++ b/src/app/driver/can/cbs/rx/can_cbs_rx_debug.c @@ -43,8 +43,8 @@ * @file can_cbs_rx_debug.c * @author foxBMS Team * @date 2021-04-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANRX * @@ -55,7 +55,7 @@ /*========== Includes =======================================================*/ #include "can_cbs_rx.h" #include "can_cbs_tx_debug-response.h" -#include "can_cbs_tx_unsupported-message.h" +#include "can_cbs_tx_debug-unsupported-multiplexer-values.h" #include "can_cfg_rx-message-definitions.h" #include "can_helper.h" #include "fram.h" @@ -99,6 +99,8 @@ #define CANRX_MUX_VERSION_INFO_SIGNAL_GET_MCU_LOT_NUMBER_LENGTH (CANRX_BIT) #define CANRX_MUX_VERSION_INFO_SIGNAL_GET_MCU_WAFER_INFORMATION_START_BIT (11u) #define CANRX_MUX_VERSION_INFO_SIGNAL_GET_MCU_WAFER_INFORMATION_LENGTH (CANRX_BIT) +#define CANRX_MUX_VERSION_INFO_SIGNAL_GET_COMMIT_HASH_START_BIT (12u) +#define CANRX_MUX_VERSION_INFO_SIGNAL_GET_COMMIT_HASH_LENGTH (CANRX_BIT) /** @} */ /** @{ @@ -306,6 +308,19 @@ static bool CANRX_CheckIfMcuWaferInformationIsRequested(uint64_t messageData, CA */ static void CANRX_TriggerMcuWaferInformationMessage(void); +/** + * @brief Check if the commit hash is requested + * @param messageData message data of the CAN message + * @param endianness endianness of the message + * @returns true if the information is requested, false otherwise + */ +static bool CANRX_CheckIfCommitHashIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness); + +/** + * @brief Triggers sending of the commit hash message + */ +static void CANRX_TriggerCommitHashMessage(void); + /** * @brief Check if a software reset is requested * @param messageData message data of the CAN message @@ -576,6 +591,32 @@ static bool CANRX_CheckIfMcuWaferInformationIsRequested(uint64_t messageData, CA return isRequested; } +static void CANRX_TriggerCommitHashMessage(void) { + /* send the debug message containing the MCU wafer information and trap if this does not work */ + if (CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_TRANSMIT_COMMIT_HASH) != STD_OK) { + FAS_ASSERT(FAS_TRAP); + } +} +static bool CANRX_CheckIfCommitHashIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness) { + /* AXIVION Routine Generic-MissingParameterAssert: messageData: parameter accept whole range */ + FAS_ASSERT(endianness == CAN_BIG_ENDIAN); + + bool isRequested = false; + uint64_t signalData = 0u; + + /* get MCU wafer information bit from the CAN message */ + CAN_RxGetSignalDataFromMessageData( + messageData, + CANRX_MUX_VERSION_INFO_SIGNAL_GET_COMMIT_HASH_START_BIT, + CANRX_MUX_VERSION_INFO_SIGNAL_GET_COMMIT_HASH_LENGTH, + &signalData, + endianness); + if (signalData == 1u) { + isRequested = true; + } + return isRequested; +} + static void CANRX_TriggerMcuWaferInformationMessage(void) { /* send the debug message containing the MCU wafer information and trap if this does not work */ if (CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_TRANSMIT_MCU_WAFER_INFORMATION) != STD_OK) { @@ -600,6 +641,9 @@ static void CANRX_ProcessVersionInformationMux(uint64_t messageData, CAN_ENDIANN if (CANRX_CheckIfMcuWaferInformationIsRequested(messageData, endianness) == true) { CANRX_TriggerMcuWaferInformationMessage(); } + if (CANRX_CheckIfCommitHashIsRequested(messageData, endianness) == true) { + CANRX_TriggerCommitHashMessage(); + } } static bool CANRX_CheckIfSoftwareResetIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness) { @@ -775,19 +819,22 @@ extern uint8_t TEST_CANRX_GetYear(uint64_t messageData, CAN_ENDIANNESS_e endiann /* export actions */ extern void TEST_CANRX_TriggerBmsSoftwareVersionMessage(void) { - return CANRX_TriggerBmsSoftwareVersionMessage(); + CANRX_TriggerBmsSoftwareVersionMessage(); } extern void TEST_CANRX_TriggerMcuUniqueDieIdMessage(void) { - return CANRX_TriggerMcuUniqueDieIdMessage(); + CANRX_TriggerMcuUniqueDieIdMessage(); } extern void TEST_CANRX_TriggerMcuLotNumberMessage(void) { - return CANRX_TriggerMcuLotNumberMessage(); + CANRX_TriggerMcuLotNumberMessage(); } extern void TEST_CANRX_TriggerMcuWaferInformationMessage(void) { - return CANRX_TriggerMcuWaferInformationMessage(); + CANRX_TriggerMcuWaferInformationMessage(); } extern void TEST_CANRX_TriggerTimeInfoMessage(void) { - return CANRX_TriggerTimeInfoMessage(); + CANRX_TriggerTimeInfoMessage(); +} +extern void TEST_CANRX_TriggerCommitHashMessage(void) { + CANRX_TriggerCommitHashMessage(); } /* export check if functions */ @@ -812,6 +859,9 @@ extern bool TEST_CANRX_CheckIfFramInitializationIsRequested(uint64_t messageData extern bool TEST_CANRX_CheckIfTimeInfoIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness) { return CANRX_CheckIfTimeInfoIsRequested(messageData, endianness); } +extern bool TEST_CANRX_CheckIfCommitHashIsRequested(uint64_t messageData, CAN_ENDIANNESS_e endianness) { + return CANRX_CheckIfCommitHashIsRequested(messageData, endianness); +} /* export mux processing functions */ extern void TEST_CANRX_ProcessVersionInformationMux(uint64_t messageData, CAN_ENDIANNESS_e endianness) { diff --git a/src/app/driver/can/cbs/rx/can_cbs_rx_imd.c b/src/app/driver/can/cbs/rx/can_cbs_rx_imd-info.c similarity index 98% rename from src/app/driver/can/cbs/rx/can_cbs_rx_imd.c rename to src/app/driver/can/cbs/rx/can_cbs_rx_imd-info.c index 6b4073a9..fb69f056 100644 --- a/src/app/driver/can/cbs/rx/can_cbs_rx_imd.c +++ b/src/app/driver/can/cbs/rx/can_cbs_rx_imd-info.c @@ -40,11 +40,11 @@ */ /** - * @file can_cbs_rx_imd.c + * @file can_cbs_rx_imd-info.c * @author foxBMS Team * @date 2021-04-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANRX * diff --git a/src/app/application/algorithm/state_estimation/soc/debug/soc_debug_cfg.c b/src/app/driver/can/cbs/rx/can_cbs_rx_imd-response.c similarity index 87% rename from src/app/application/algorithm/state_estimation/soc/debug/soc_debug_cfg.c rename to src/app/driver/can/cbs/rx/can_cbs_rx_imd-response.c index 618e76e9..91c44b19 100644 --- a/src/app/application/algorithm/state_estimation/soc/debug/soc_debug_cfg.c +++ b/src/app/driver/can/cbs/rx/can_cbs_rx_imd-response.c @@ -40,20 +40,23 @@ */ /** - * @file soc_debug_cfg.c + * @file can_cbs_rx_imd-response.c * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOC - * - * @brief SOC calculation configuration file + * @date 2021-04-20 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANRX * + * @brief CAN driver Rx callback implementation + * @details CAN Rx callback for IMD messages */ /*========== Includes =======================================================*/ -#include "soc_debug_cfg.h" +#include "can_cbs_rx.h" +#include "can_cfg_rx-message-definitions.h" +#include "can_helper.h" +#include "foxmath.h" #include diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx.h b/src/app/driver/can/cbs/tx/can_cbs_tx.h index 2ba845ad..acdf5ae8 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx.h +++ b/src/app/driver/can/cbs/tx/can_cbs_tx.h @@ -43,8 +43,8 @@ * @file can_cbs_tx.h * @author foxBMS Team * @date 2021-04-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_bms-state-details.c b/src/app/driver/can/cbs/tx/can_cbs_tx_bms-state-details.c new file mode 100644 index 00000000..a2864f66 --- /dev/null +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_bms-state-details.c @@ -0,0 +1,106 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file can_cbs_tx_bms-state-details.c + * @author foxBMS Team + * @date 2021-07-21 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANTX + * + * @brief CAN driver Tx callback implementation + * @details CAN Tx callback for state messages + */ + +/*========== Includes =======================================================*/ +#include "bms.h" +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" +#include "diag.h" +#include "sys_mon.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ +#define CANTX_BIT (1u) + +/** + * Configuration of the signals +*/ +#define CANTX_SIGNAL_TIMING_VIOLATION_100MS_ALGO_TASK_START_BIT (4u) +#define CANTX_SIGNAL_TIMING_VIOLATION_100MS_ALGO_TASK_LENGTH (CANTX_BIT) +#define CANTX_SIGNAL_TIMING_VIOLATION_100MS_TASK_START_BIT (3u) +#define CANTX_SIGNAL_TIMING_VIOLATION_100MS_TASK_LENGTH (CANTX_BIT) +#define CANTX_SIGNAL_TIMING_VIOLATION_10MS_TASK_START_BIT (2u) +#define CANTX_SIGNAL_TIMING_VIOLATION_10MS_TASK_LENGTH (CANTX_BIT) +#define CANTX_SIGNAL_TIMING_VIOLATION_1MS_TASK_START_BIT (1u) +#define CANTX_SIGNAL_TIMING_VIOLATION_1MS_TASK_LENGTH (CANTX_BIT) +#define CANTX_SIGNAL_TIMING_VIOLATION_ENGINE_TASK_START_BIT (0u) +#define CANTX_SIGNAL_TIMING_VIOLATION_ENGINE_TASK_LENGTH (CANTX_BIT) +#define CANTX_SIGNAL_TIMING_VIOLATION_100MS_ALGO_TASK_RECORDED_START_BIT (12u) +#define CANTX_SIGNAL_TIMING_VIOLATION_100MS_ALGO_TASK_RECORDED_LENGTH (CANTX_BIT) +#define CANTX_SIGNAL_TIMING_VIOLATION_100MS_TASK_RECORDED_START_BIT (11u) +#define CANTX_SIGNAL_TIMING_VIOLATION_100MS_TASK_RECORDED_LENGTH (CANTX_BIT) +#define CANTX_SIGNAL_TIMING_VIOLATION_10MS_TASK_RECORDED_START_BIT (10u) +#define CANTX_SIGNAL_TIMING_VIOLATION_10MS_TASK_RECORDED_LENGTH (CANTX_BIT) +#define CANTX_SIGNAL_TIMING_VIOLATION_1MS_TASK_RECORDED_START_BIT (9u) +#define CANTX_SIGNAL_TIMING_VIOLATION_1MS_TASK_RECORDED_LENGTH (CANTX_BIT) +#define CANTX_SIGNAL_TIMING_VIOLATION_ENGINE_TASK_RECORDED_START_BIT (8u) +#define CANTX_SIGNAL_TIMING_VIOLATION_ENGINE_TASK_RECORDED_LENGTH (CANTX_BIT) + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ + +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_state.c b/src/app/driver/can/cbs/tx/can_cbs_tx_bms-state.c similarity index 99% rename from src/app/driver/can/cbs/tx/can_cbs_tx_state.c rename to src/app/driver/can/cbs/tx/can_cbs_tx_bms-state.c index 87ffb8c8..26ff4d01 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_state.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_bms-state.c @@ -40,11 +40,11 @@ */ /** - * @file can_cbs_tx_state.c + * @file can_cbs_tx_bms-state.c * @author foxBMS Team * @date 2021-07-21 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_cell-temperatures.c b/src/app/driver/can/cbs/tx/can_cbs_tx_cell-temperatures.c index 41ba7f34..8c82ce1d 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_cell-temperatures.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_cell-temperatures.c @@ -43,8 +43,8 @@ * @file can_cbs_tx_cell-temperatures.c * @author foxBMS Team * @date 2021-04-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * @@ -154,8 +154,7 @@ static void CANTX_TemperatureSetData( /* Temperature data */ float_t signalData_degC = - (float_t)kpkCanShim->pTableCellTemperature - ->cellTemperature_ddegC[stringNumber][(moduleNumber * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + sensorNumber]; + (float_t)kpkCanShim->pTableCellTemperature->cellTemperature_ddegC[stringNumber][moduleNumber][sensorNumber]; signalData_degC /= UNIT_CONVERSION_FACTOR_10_FLOAT; /* Convert temperature from decidegC to degC */ /* Apply offset and factor, check min/max limits */ CAN_TxPrepareSignalData(&signalData_degC, cellTemperatureSignal); diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_cell-voltages.c b/src/app/driver/can/cbs/tx/can_cbs_tx_cell-voltages.c index f3f04521..71ef3da8 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_cell-voltages.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_cell-voltages.c @@ -43,8 +43,8 @@ * @file can_cbs_tx_cell-voltages.c * @author foxBMS Team * @date 2021-04-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * @@ -115,17 +115,24 @@ static void CANTX_VoltageSetData( CAN_SIGNAL_TYPE_s cellVoltageInvalidFlagSignal, CAN_ENDIANNESS_e endianness, const CAN_SHIM_s *const kpkCanShim) { + /* AXIVION Routine Generic-MissingParameterAssert: muxId: parameter checked in calling function */ + /* AXIVION Routine Generic-MissingParameterAssert: pMessage: passed parameter created from calling function */ + /* AXIVION Routine Generic-MissingParameterAssert: cellVoltageSignal: Assertion done in CAN_TxPrepareSignalData */ + /* AXIVION Routine Generic-MissingParameterAssert: cellVoltageInvalidFlagSignal: Assertion done by caller */ + /* AXIVION Routine Generic-MissingParameterAssert: endianness: parameter checked in calling function */ + /* AXIVION Routine Generic-MissingParameterAssert: kpkCanShim: parameter checked in calling function */ + /* cell index must not be greater than the number of cells */ if (muxId < (BS_NR_OF_CELL_BLOCKS_PER_STRING * BS_NR_OF_STRINGS)) { /* Get string, module and cell number */ - const uint8_t stringNumber = DATA_GetStringNumberFromVoltageIndex(muxId); - const uint8_t moduleNumber = DATA_GetModuleNumberFromVoltageIndex(muxId); - const uint8_t cellNumber = DATA_GetCellNumberFromVoltageIndex(muxId); + const uint8_t stringNumber = DATA_GetStringNumberFromVoltageIndex(muxId); + const uint8_t moduleNumber = DATA_GetModuleNumberFromVoltageIndex(muxId); + const uint8_t cellBlockNumber = DATA_GetCellNumberFromVoltageIndex(muxId); uint32_t signalData_valid = 0u; /* Valid bits data */ - if ((kpkCanShim->pTableCellVoltage->invalidCellVoltage[stringNumber][moduleNumber] & (0x01u << cellNumber)) == - 0u) { + if ((kpkCanShim->pTableCellVoltage->invalidCellVoltage[stringNumber][moduleNumber] & + (0x01u << cellBlockNumber)) == 0u) { signalData_valid = 0u; } else { signalData_valid = 1u; @@ -140,9 +147,7 @@ static void CANTX_VoltageSetData( /*Voltage data */ float_t signalData_mV = - (float_t)(kpkCanShim->pTableCellVoltage - ->cellVoltage_mV[stringNumber] - [(moduleNumber * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + cellNumber]); + (float_t)(kpkCanShim->pTableCellVoltage->cellVoltage_mV[stringNumber][moduleNumber][cellBlockNumber]); /* Apply offset and factor */ CAN_TxPrepareSignalData(&signalData_mV, cellVoltageSignal); /* Set voltage data in CAN frame */ @@ -160,6 +165,7 @@ extern uint32_t CANTX_CellVoltages( FAS_ASSERT(message.id == CANTX_CELL_VOLTAGES_ID); FAS_ASSERT(message.idType == CANTX_CELL_VOLTAGES_ID_TYPE); FAS_ASSERT(message.dlc == CAN_FOXBMS_MESSAGES_DEFAULT_DLC); + FAS_ASSERT((message.endianness == CAN_LITTLE_ENDIAN) || (message.endianness == CAN_BIG_ENDIAN)); FAS_ASSERT(pCanData != NULL_PTR); FAS_ASSERT(pMuxId != NULL_PTR); FAS_ASSERT(kpkCanShim != NULL_PTR); diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.c b/src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.c new file mode 100644 index 00000000..cc2b9190 --- /dev/null +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.c @@ -0,0 +1,104 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file can_cbs_tx_crash-dump.c + * @author foxBMS Team + * @date 2022-11-16 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANTX + * + * @brief CAN + * @details CAN Tx callback for fatal errors. + * These messages are not guaranteed to be sent, rather it is a best + * effort to get information during debugging why a fatal error + * occurred. + */ + +/*========== Includes =======================================================*/ +#include "general.h" + +#include "can_cbs_tx_crash-dump.h" + +#include "can.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" + +#include + +/*========== Macros and Definitions =========================================*/ +/** @{ + * multiplexer setup for the fatal errors message + */ +#define CANTX_FATAL_ERRORS_MESSAGE_MUX_START_BIT (0x7u) +#define CANTX_FATAL_ERRORS_MESSAGE_MUX_LENGTH (8u) +/** @} */ + +#define CANTX_FATAL_ERRORS_MESSAGE_MUX_VALUE_STACK_OVERFLOW (0x00u) + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +extern void CANTX_SendReasonsForFatalErrors(CANTX_FATAL_ERRORS_ACTIONS_e action) { + uint8_t data[] = {GEN_REPEAT_U(0u, GEN_STRIP(CAN_MAX_DLC))}; + switch (action) { + case CANTX_FATAL_ERRORS_ACTIONS_STACK_OVERFLOW: + data[0] = 1u; + (void)CAN_DataSend(CAN_NODE_DEBUG_MESSAGE, CANTX_FATAL_ERRORS_ID, CANTX_FATAL_ERRORS_IDENTIFIER, &data[0]); + break; + default: /* LCOV_EXCL_LINE */ + FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/application/algorithm/state_estimation/soc/none/soc_none_cfg.h b/src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.h similarity index 72% rename from src/app/application/algorithm/state_estimation/soc/none/soc_none_cfg.h rename to src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.h index 816ea055..e0c050e4 100644 --- a/src/app/application/algorithm/state_estimation/soc/none/soc_none_cfg.h +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.h @@ -40,39 +40,43 @@ */ /** - * @file soc_none_cfg.h + * @file can_cbs_tx_crash-dump.h * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOC - * - * @brief Header for SOC configuration + * @date 2022-11-16 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANTX * + * @brief CAN Tx callback functions for transmitting information on fatal + * errors. + * @details TODO */ -#ifndef FOXBMS__SOC_NONE_CFG_H_ -#define FOXBMS__SOC_NONE_CFG_H_ +#ifndef FOXBMS__CAN_CBS_TX_CRASH_DUMP_H_ +#define FOXBMS__CAN_CBS_TX_CRASH_DUMP_H_ /*========== Includes =======================================================*/ -#include - /*========== Macros and Definitions =========================================*/ - -/** - * Cell capacity used for SOC calculation, in this case Ah counting - * Specified once according to data sheet of cell usually. - */ -#define SOX_CELL_CAPACITY (20000.0f) +/** defines which action is performed when #CANTX_SendReasonsForFatalErrors is called */ +typedef enum { + CANTX_FATAL_ERRORS_ACTIONS_STACK_OVERFLOW, +} CANTX_FATAL_ERRORS_ACTIONS_e; /*========== Extern Constant and Variable Declarations ======================*/ /*========== Extern Function Prototypes =====================================*/ +/** + * @brief Tries to send a CAN message in case of fatal error + * @details This function shall be called in the default clause of a received, + * multiplexed message, to tell the sender, that this + * message-multiplexer combination is not supported. + */ +void CANTX_SendReasonsForFatalErrors(CANTX_FATAL_ERRORS_ACTIONS_e action); /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST #endif -#endif /* FOXBMS__SOC_NONE_CFG_H_ */ +#endif /* FOXBMS__CAN_CBS_TX_CRASH_DUMP_H_ */ diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.c b/src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.c index 7284e2ad..bd94d6b3 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.c @@ -43,8 +43,8 @@ * @file can_cbs_tx_debug-response.c * @author foxBMS Team * @date 2019-12-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CANTX * @@ -79,7 +79,7 @@ /*========== Macros and Definitions =========================================*/ /** @{ - * multiplexer setup for the debug message + * multiplexer setup for the debug response message */ #define CANTX_DEBUG_RESPONSE_MESSAGE_MUX_START_BIT (0x7u) #define CANTX_DEBUG_RESPONSE_MESSAGE_MUX_LENGTH (8u) @@ -90,6 +90,7 @@ #define CANTX_DEBUG_RESPONSE_MESSAGE_MUX_VALUE_MCU_LOT_NUMBER (0x02u) #define CANTX_DEBUG_RESPONSE_MESSAGE_MUX_VALUE_MCU_WAFER_INFORMATION (0x03u) #define CANTX_DEBUG_RESPONSE_MESSAGE_MUX_VALUE_RTC_TIME (0x04u) +#define CANTX_DEBUG_RESPONSE_MESSAGE_MUX_VALUE_COMMIT_HASH (0x05u) #define CANTX_DEBUG_RESPONSE_MESSAGE_MUX_VALUE_BOOT_INFORMATION (0x0Fu) /** @{ @@ -179,8 +180,8 @@ /** @{ * Magic data, i.e., bit muster, in the boot message */ -#define CANTX_BOOT_MAGIC_DATA_START (0b11111110111111101111111011111110111111101111111011111110uLL) -#define CANTX_BOOT_MAGIC_DATA_END (0b00000001000000010000000100000001000000010000000100000001uLL) +#define CANTX_BOOT_MAGIC_DATA_START (0xFEFEFEFEFEFEFEuLL) +#define CANTX_BOOT_MAGIC_DATA_END (0x01010101010101uLL) /** @} */ /** @{ @@ -198,6 +199,27 @@ #define CANTX_WAFER_NUMBER_SHIFT_24_BITS (24uLL) /** @} */ +/** @{ + * configuration of the BMS software version information signals for + * multiplexer 'CommitHash' in the 'DebugResponse' message + */ +#define CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_0_START_BIT (15u) +#define CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_1_START_BIT (23u) +#define CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_2_START_BIT (31u) +#define CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_3_START_BIT (39u) +#define CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_4_START_BIT (47u) +#define CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_5_START_BIT (55u) +#define CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_6_START_BIT (63u) +#define CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_LENGTH (8u) +#define CANTX_MUX_COMMIT_HASH_CHAR_0 (0u) +#define CANTX_MUX_COMMIT_HASH_CHAR_1 (1u) +#define CANTX_MUX_COMMIT_HASH_CHAR_2 (2u) +#define CANTX_MUX_COMMIT_HASH_CHAR_3 (3u) +#define CANTX_MUX_COMMIT_HASH_CHAR_4 (4u) +#define CANTX_MUX_COMMIT_HASH_CHAR_5 (5u) +#define CANTX_MUX_COMMIT_HASH_CHAR_6 (6u) +/** @} */ + /*========== Static Constant and Variable Definitions =======================*/ /*========== Extern Constant and Variable Definitions =======================*/ @@ -251,6 +273,12 @@ static STD_RETURN_TYPE_e CANTX_TransmitBootMagicEnd(void); */ static STD_RETURN_TYPE_e CANTX_TransmitRtcTime(void); +/** + * @brief Transmit the commit hash + * @return #STD_OK if transmission successful, otherwise #STD_NOT_OK +*/ +static STD_RETURN_TYPE_e CANTX_TransmitCommitHash(void); + /*========== Static Function Implementations ================================*/ static STD_RETURN_TYPE_e CANTX_TransmitBmsVersionInfo(void) { @@ -272,7 +300,7 @@ static STD_RETURN_TYPE_e CANTX_TransmitBmsVersionInfo(void) { underVersionControl = 1; } - uint64_t message = 0; + uint64_t message = 0u; CAN_TxSetMessageDataWithSignalData( &message, CANTX_DEBUG_RESPONSE_MESSAGE_MUX_START_BIT, @@ -334,7 +362,7 @@ static STD_RETURN_TYPE_e CANTX_TransmitMcuUniqueDieId(void) { /* Read out device register with unique ID */ const uint32_t deviceRegister = systemREG1->DEVID; - uint64_t message = 0; + uint64_t message = 0u; CAN_TxSetMessageDataWithSignalData( &message, CANTX_DEBUG_RESPONSE_MESSAGE_MUX_START_BIT, @@ -360,7 +388,7 @@ static STD_RETURN_TYPE_e CANTX_TransmitMcuLotNumber(void) { /* Read out device register with die ID high */ const uint32_t dieIdHigh = systemREG1->DIEIDH; /* equals the lot number */ - uint64_t message = 0; + uint64_t message = 0u; CAN_TxSetMessageDataWithSignalData( &message, CANTX_DEBUG_RESPONSE_MESSAGE_MUX_START_BIT, @@ -392,7 +420,7 @@ static STD_RETURN_TYPE_e CANTX_TransmitMcuWaferInformation(void) { uint64_t yWaferCoordinate = (dieIdLow & CANTX_WAFER_Y_COORDINATE_BITMASK) >> CANTX_WAFER_Y_COORDINATE_SHIFT_12_BITS; uint64_t waferNumber = (dieIdLow & CANTX_WAFER_NUMBER_BITMASK) >> CANTX_WAFER_NUMBER_SHIFT_24_BITS; - uint64_t message = 0; + uint64_t message = 0u; CAN_TxSetMessageDataWithSignalData( &message, CANTX_DEBUG_RESPONSE_MESSAGE_MUX_START_BIT, @@ -428,7 +456,7 @@ static STD_RETURN_TYPE_e CANTX_TransmitBootMagic(uint64_t messageData) { FAS_ASSERT((messageData == CANTX_BOOT_MAGIC_DATA_START) || (messageData == CANTX_BOOT_MAGIC_DATA_END)); uint8_t data[] = {GEN_REPEAT_U(0u, GEN_STRIP(CAN_MAX_DLC))}; - uint64_t message = 0; + uint64_t message = 0u; CAN_TxSetMessageDataWithSignalData( &message, CANTX_DEBUG_RESPONSE_MESSAGE_MUX_START_BIT, @@ -456,7 +484,7 @@ static STD_RETURN_TYPE_e CANTX_TransmitRtcTime(void) { RTC_TIME_DATA_s currentRtcTime = RTC_GetSystemTimeRtcFormat(); - uint64_t message = 0; + uint64_t message = 0u; CAN_TxSetMessageDataWithSignalData( &message, CANTX_DEBUG_RESPONSE_MESSAGE_MUX_START_BIT, @@ -518,6 +546,74 @@ static STD_RETURN_TYPE_e CANTX_TransmitRtcTime(void) { return successfullyQueued; } +static STD_RETURN_TYPE_e CANTX_TransmitCommitHash(void) { + uint8_t data[] = {GEN_REPEAT_U(0u, GEN_STRIP(CAN_MAX_DLC))}; + uint64_t message = 0u; + + /* set message data with mux value and first seven chars of commit hash*/ + CAN_TxSetMessageDataWithSignalData( + &message, + CANTX_DEBUG_RESPONSE_MESSAGE_MUX_START_BIT, + CANTX_DEBUG_RESPONSE_MESSAGE_MUX_LENGTH, + CANTX_DEBUG_RESPONSE_MESSAGE_MUX_VALUE_COMMIT_HASH, + CAN_BIG_ENDIAN); + uint64_t signalData = (uint64_t)ver_foxbmsVersionInformation.commitHash[CANTX_MUX_COMMIT_HASH_CHAR_0]; + CAN_TxSetMessageDataWithSignalData( + &message, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_0_START_BIT, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_LENGTH, + signalData, + CAN_BIG_ENDIAN); + signalData = (uint64_t)ver_foxbmsVersionInformation.commitHash[CANTX_MUX_COMMIT_HASH_CHAR_1]; + CAN_TxSetMessageDataWithSignalData( + &message, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_1_START_BIT, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_LENGTH, + signalData, + CAN_BIG_ENDIAN); + signalData = (uint64_t)ver_foxbmsVersionInformation.commitHash[CANTX_MUX_COMMIT_HASH_CHAR_2]; + CAN_TxSetMessageDataWithSignalData( + &message, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_2_START_BIT, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_LENGTH, + signalData, + CAN_BIG_ENDIAN); + signalData = (uint64_t)ver_foxbmsVersionInformation.commitHash[CANTX_MUX_COMMIT_HASH_CHAR_3]; + CAN_TxSetMessageDataWithSignalData( + &message, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_3_START_BIT, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_LENGTH, + signalData, + CAN_BIG_ENDIAN); + signalData = (uint64_t)ver_foxbmsVersionInformation.commitHash[CANTX_MUX_COMMIT_HASH_CHAR_4]; + CAN_TxSetMessageDataWithSignalData( + &message, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_4_START_BIT, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_LENGTH, + signalData, + CAN_BIG_ENDIAN); + signalData = (uint64_t)ver_foxbmsVersionInformation.commitHash[CANTX_MUX_COMMIT_HASH_CHAR_5]; + CAN_TxSetMessageDataWithSignalData( + &message, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_5_START_BIT, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_LENGTH, + signalData, + CAN_BIG_ENDIAN); + signalData = (uint64_t)ver_foxbmsVersionInformation.commitHash[CANTX_MUX_COMMIT_HASH_CHAR_6]; + CAN_TxSetMessageDataWithSignalData( + &message, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_6_START_BIT, + CANTX_MUX_COMMIT_HASH_SIGNAL_CHAR_LENGTH, + signalData, + CAN_BIG_ENDIAN); + + CAN_TxSetCanDataWithMessageData(message, &data[0], CAN_BIG_ENDIAN); + STD_RETURN_TYPE_e successfullyQueued = + CAN_DataSend(CAN_NODE_DEBUG_MESSAGE, CANTX_DEBUG_RESPONSE_ID, CANTX_DEBUG_IDENTIFIER, &data[0]); + + return successfullyQueued; +} + /*========== Extern Function Implementations ================================*/ extern STD_RETURN_TYPE_e CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_ACTIONS_e action) { STD_RETURN_TYPE_e successfullyQueued = STD_NOT_OK; @@ -543,12 +639,16 @@ extern STD_RETURN_TYPE_e CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_ACTIONS_e acti case CANTX_DEBUG_RESPONSE_TRANSMIT_RTC_TIME: successfullyQueued = CANTX_TransmitRtcTime(); break; + case CANTX_DEBUG_RESPONSE_TRANSMIT_COMMIT_HASH: + successfullyQueued = CANTX_TransmitCommitHash(); + break; default: FAS_ASSERT(FAS_TRAP); break; /* LCOV_EXCL_LINE */ } return successfullyQueued; } + /*========== Getter for static Variables (Unit Test) ========================*/ /*========== Externalized Static Function Implementations (Unit Test) =======*/ diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.h b/src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.h index f6eee1aa..8cf8c36e 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.h +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.h @@ -43,8 +43,8 @@ * @file can_cbs_tx_debug-response.h * @author foxBMS Team * @date 2022-07-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SOME_GROUP * @prefix CANTX * @@ -73,6 +73,7 @@ typedef enum { CANTX_DEBUG_RESPONSE_TRANSMIT_BOOT_MAGIC_START, CANTX_DEBUG_RESPONSE_TRANSMIT_BOOT_MAGIC_END, CANTX_DEBUG_RESPONSE_TRANSMIT_RTC_TIME, + CANTX_DEBUG_RESPONSE_TRANSMIT_COMMIT_HASH, } CANTX_DEBUG_RESPONSE_ACTIONS_e; /*========== Extern Constant and Variable Declarations ======================*/ diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_unsupported-message.c b/src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.c similarity index 95% rename from src/app/driver/can/cbs/tx/can_cbs_tx_unsupported-message.c rename to src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.c index 79f2378f..4eea1d3e 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_unsupported-message.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.c @@ -40,11 +40,11 @@ */ /** - * @file can_cbs_tx_unsupported-message.c + * @file can_cbs_tx_debug-unsupported-multiplexer-values.c * @author foxBMS Team * @date 2022-11-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * @@ -55,7 +55,7 @@ /*========== Includes =======================================================*/ #include "general.h" -#include "can_cbs_tx_unsupported-message.h" +#include "can_cbs_tx_debug-unsupported-multiplexer-values.h" #include "can.h" #include "can_cfg_tx-message-definitions.h" @@ -83,7 +83,7 @@ extern void CANTX_UnsupportedMultiplexerValue(uint32_t messageId, uint32_t multi /* AXIVION Routine Generic-MissingParameterAssert: messageId: parameter accept whole range */ /* AXIVION Routine Generic-MissingParameterAssert: multiplexerValue: parameter accept whole range */ uint8_t data[] = {GEN_REPEAT_U(0u, GEN_STRIP(CAN_MAX_DLC))}; - uint64_t message = 0; + uint64_t message = 0u; CAN_TxSetMessageDataWithSignalData( &message, CANTX_UNSUPPORTED_MULTIPLEXER_VAL_MESSAGE_SIGNAL_MESSAGE_ID_START_BIT, diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_unsupported-message.h b/src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.h similarity index 91% rename from src/app/driver/can/cbs/tx/can_cbs_tx_unsupported-message.h rename to src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.h index 6acb31c0..da6c3a45 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_unsupported-message.h +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.h @@ -40,11 +40,11 @@ */ /** - * @file can_cbs_tx_unsupported-message.h + * @file can_cbs_tx_debug-unsupported-multiplexer-values.h * @author foxBMS Team * @date 2022-11-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * @@ -52,8 +52,8 @@ * @details CAN Tx callback for unsupported requests */ -#ifndef FOXBMS__CAN_CBS_TX_UNSUPPORTED_MESSAGE_H_ -#define FOXBMS__CAN_CBS_TX_UNSUPPORTED_MESSAGE_H_ +#ifndef FOXBMS__CAN_CBS_TX_DEBUG_UNSUPPORTED_MULTIPLEXER_VALUES_H_ +#define FOXBMS__CAN_CBS_TX_DEBUG_UNSUPPORTED_MULTIPLEXER_VALUES_H_ /*========== Includes =======================================================*/ @@ -83,4 +83,4 @@ void CANTX_UnsupportedMultiplexerValue(uint32_t messageId, uint32_t multiplexerV #ifdef UNITY_UNIT_TEST #endif -#endif /* FOXBMS__CAN_CBS_TX_UNSUPPORTED_MESSAGE_H_ */ +#endif /* FOXBMS__CAN_CBS_TX_DEBUG_UNSUPPORTED_MULTIPLEXER_VALUES_H_ */ diff --git a/src/app/application/algorithm/state_estimation/soc/none/soc_none_cfg.c b/src/app/driver/can/cbs/tx/can_cbs_tx_imd-request.c similarity index 87% rename from src/app/application/algorithm/state_estimation/soc/none/soc_none_cfg.c rename to src/app/driver/can/cbs/tx/can_cbs_tx_imd-request.c index 8f9ef7f2..9e420926 100644 --- a/src/app/application/algorithm/state_estimation/soc/none/soc_none_cfg.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_imd-request.c @@ -40,21 +40,24 @@ */ /** - * @file soc_none_cfg.c + * @file can_cbs_tx_imd-request.c * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOC - * - * @brief SOC calculation configuration file + * @date 2023-06-14 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANTX * + * @brief CAN driver Tx callback implementation + * @details CAN Tx callback for pack value and string value messages */ /*========== Includes =======================================================*/ -#include "soc_none_cfg.h" +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" +#include #include /*========== Macros and Definitions =========================================*/ diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_limit-values.c b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-limits.c similarity index 98% rename from src/app/driver/can/cbs/tx/can_cbs_tx_limit-values.c rename to src/app/driver/can/cbs/tx/can_cbs_tx_pack-limits.c index 7ae0dade..b56ca5a3 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_limit-values.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-limits.c @@ -40,11 +40,11 @@ */ /** - * @file can_cbs_tx_limit-values.c + * @file can_cbs_tx_pack-limits.c * @author foxBMS Team * @date 2021-07-21 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_minimum-maximum-values.c b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-minimum-maximum-values.c similarity index 98% rename from src/app/driver/can/cbs/tx/can_cbs_tx_minimum-maximum-values.c rename to src/app/driver/can/cbs/tx/can_cbs_tx_pack-minimum-maximum-values.c index 3d583cca..2180488d 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_minimum-maximum-values.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-minimum-maximum-values.c @@ -40,11 +40,11 @@ */ /** - * @file can_cbs_tx_minimum-maximum-values.c + * @file can_cbs_tx_pack-minimum-maximum-values.c * @author foxBMS Team * @date 2021-04-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_pack-state-estimation.c b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-state-estimation.c index b0612fb0..33fa621f 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_pack-state-estimation.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-state-estimation.c @@ -43,8 +43,8 @@ * @file can_cbs_tx_pack-state-estimation.c * @author foxBMS Team * @date 2021-07-21 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * @@ -92,21 +92,21 @@ extern uint32_t CANTX_PackStateEstimation( float_t maximumStringSoe_perc = FLT_MIN; uint32_t minimumStringEnergy_Wh = UINT32_MAX; - DATA_READ_DATA(kpkCanShim->pTableSox); + DATA_READ_DATA(kpkCanShim->pTableSoc, kpkCanShim->pTableSoe); /* Check current direction */ if (BMS_GetBatterySystemState() == BMS_CHARGING) { /* If battery system is charging use maximum values */ for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { if (BMS_IsStringClosed(s) == true) { - if (maximumStringSoc_perc < kpkCanShim->pTableSox->maximumSoc_perc[s]) { - maximumStringSoc_perc = kpkCanShim->pTableSox->maximumSoc_perc[s]; + if (maximumStringSoc_perc < kpkCanShim->pTableSoc->maximumSoc_perc[s]) { + maximumStringSoc_perc = kpkCanShim->pTableSoc->maximumSoc_perc[s]; } - if (maximumStringSoe_perc < kpkCanShim->pTableSox->maximumSoe_perc[s]) { - maximumStringSoe_perc = kpkCanShim->pTableSox->maximumSoe_perc[s]; + if (maximumStringSoe_perc < kpkCanShim->pTableSoe->maximumSoe_perc[s]) { + maximumStringSoe_perc = kpkCanShim->pTableSoe->maximumSoe_perc[s]; } - if (minimumStringEnergy_Wh > kpkCanShim->pTableSox->minimumSoe_Wh[s]) { - minimumStringEnergy_Wh = kpkCanShim->pTableSox->minimumSoe_Wh[s]; + if (minimumStringEnergy_Wh > kpkCanShim->pTableSoe->minimumSoe_Wh[s]) { + minimumStringEnergy_Wh = kpkCanShim->pTableSoe->minimumSoe_Wh[s]; } } } @@ -114,14 +114,14 @@ extern uint32_t CANTX_PackStateEstimation( /* If battery system is discharging or at rest use minimum values */ for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { if (BMS_IsStringClosed(s) == true) { - if (minimumStringSoc_perc > kpkCanShim->pTableSox->minimumSoc_perc[s]) { - minimumStringSoc_perc = kpkCanShim->pTableSox->minimumSoc_perc[s]; + if (minimumStringSoc_perc > kpkCanShim->pTableSoc->minimumSoc_perc[s]) { + minimumStringSoc_perc = kpkCanShim->pTableSoc->minimumSoc_perc[s]; } - if (minimumStringSoe_perc > kpkCanShim->pTableSox->minimumSoe_perc[s]) { - minimumStringSoe_perc = kpkCanShim->pTableSox->minimumSoe_perc[s]; + if (minimumStringSoe_perc > kpkCanShim->pTableSoe->minimumSoe_perc[s]) { + minimumStringSoe_perc = kpkCanShim->pTableSoe->minimumSoe_perc[s]; } - if (minimumStringEnergy_Wh > kpkCanShim->pTableSox->minimumSoe_Wh[s]) { - minimumStringEnergy_Wh = kpkCanShim->pTableSox->minimumSoe_Wh[s]; + if (minimumStringEnergy_Wh > kpkCanShim->pTableSoe->minimumSoe_Wh[s]) { + minimumStringEnergy_Wh = kpkCanShim->pTableSoe->minimumSoe_Wh[s]; } } } diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_system-values.c b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p0.c similarity index 99% rename from src/app/driver/can/cbs/tx/can_cbs_tx_system-values.c rename to src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p0.c index 7b07504a..5fae299b 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_system-values.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p0.c @@ -40,11 +40,11 @@ */ /** - * @file can_cbs_tx_system-values.c + * @file can_cbs_tx_pack-values-p0.c * @author foxBMS Team * @date 2021-07-21 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p1.c b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p1.c new file mode 100644 index 00000000..b5939da6 --- /dev/null +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p1.c @@ -0,0 +1,80 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file can_cbs_tx_pack-values-p1.c + * @author foxBMS Team + * @date 2023-05-31 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANTX + * + * @brief CAN driver Tx callback implementation + * @details CAN Tx callback for pack value and string value messages + */ + +/*========== Includes =======================================================*/ +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ +/* configuration of the PackP1 message bits */ +#define CANTX_PACK_P1_INSULATION_RESISTANCE_START_BIT (7u) +#define CANTX_PACK_P1_INSULATION_RESISTANCE_LENGTH (13u) + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/application/algorithm/state_estimation/soe/counting/soe_counting_cfg.c b/src/app/driver/can/cbs/tx/can_cbs_tx_string-minimum-maximum-values.c similarity index 86% rename from src/app/application/algorithm/state_estimation/soe/counting/soe_counting_cfg.c rename to src/app/driver/can/cbs/tx/can_cbs_tx_string-minimum-maximum-values.c index 82b50b8b..1603fe25 100644 --- a/src/app/application/algorithm/state_estimation/soe/counting/soe_counting_cfg.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_string-minimum-maximum-values.c @@ -40,21 +40,25 @@ */ /** - * @file soe_counting_cfg.c + * @file can_cbs_tx_string-minimum-maximum-values.c * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOE - * - * @brief SOE calculation configuration file + * @date 2021-04-20 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANTX * + * @brief CAN driver Tx callback implementation + * @details CAN Tx callback for min/max values */ /*========== Includes =======================================================*/ -#include "soe_counting_cfg.h" +#include "bms.h" +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" +#include #include /*========== Macros and Definitions =========================================*/ diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_string-state-estimation.c b/src/app/driver/can/cbs/tx/can_cbs_tx_string-state-estimation.c index 2947963a..8b750109 100644 --- a/src/app/driver/can/cbs/tx/can_cbs_tx_string-state-estimation.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_string-state-estimation.c @@ -43,8 +43,8 @@ * @file can_cbs_tx_string-state-estimation.c * @author foxBMS Team * @date 2021-07-21 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix CANTX * @@ -99,7 +99,7 @@ extern uint32_t CANTX_StringStateEstimation( CAN_TxSetMessageDataWithSignalData(&messageData, 7u, 4u, data, message.endianness); /* Minimum SOC */ - float_t signalData = kpkCanShim->pTableSox->minimumSoc_perc[stringNumber]; + float_t signalData = kpkCanShim->pTableSoc->minimumSoc_perc[stringNumber]; float_t offset = 0.0f; float_t factor = 4.0f; /* convert from perc to 0.25perc */ signalData = (signalData + offset) * factor; @@ -108,7 +108,7 @@ extern uint32_t CANTX_StringStateEstimation( CAN_TxSetMessageDataWithSignalData(&messageData, 3u, 9u, data, message.endianness); /* Average SOC */ - signalData = kpkCanShim->pTableSox->averageSoc_perc[stringNumber]; + signalData = kpkCanShim->pTableSoc->averageSoc_perc[stringNumber]; offset = 0.0f; factor = 4.0f; /* convert from perc to 0.25perc */ signalData = (signalData + offset) * factor; @@ -117,7 +117,7 @@ extern uint32_t CANTX_StringStateEstimation( CAN_TxSetMessageDataWithSignalData(&messageData, 10u, 9u, data, message.endianness); /* Maximum SOC */ - signalData = kpkCanShim->pTableSox->maximumSoc_perc[stringNumber]; + signalData = kpkCanShim->pTableSoc->maximumSoc_perc[stringNumber]; offset = 0.0f; factor = 4.0f; /* convert from perc to 0.25perc */ signalData = (signalData + offset) * factor; @@ -127,9 +127,9 @@ extern uint32_t CANTX_StringStateEstimation( /* SOE */ if (BMS_CHARGING == BMS_GetCurrentFlowDirection(kpkCanShim->pTablePackValues->stringCurrent_mA[stringNumber])) { - signalData = kpkCanShim->pTableSox->maximumSoe_perc[stringNumber]; + signalData = kpkCanShim->pTableSoe->maximumSoe_perc[stringNumber]; } else { - signalData = kpkCanShim->pTableSox->minimumSoe_perc[stringNumber]; + signalData = kpkCanShim->pTableSoe->minimumSoe_perc[stringNumber]; } offset = 0.0f; factor = 4.0f; /* convert from perc to 0.25perc */ @@ -148,7 +148,7 @@ extern uint32_t CANTX_StringStateEstimation( CAN_TxSetMessageDataWithSignalData(&messageData, 47u, 9u, data, message.endianness); /* String energy */ - signalData = kpkCanShim->pTableSox->minimumSoe_Wh[stringNumber]; + signalData = kpkCanShim->pTableSoe->minimumSoe_Wh[stringNumber]; offset = 0.0f; factor = 0.1f; /* convert from Wh to 10Wh */ signalData = (signalData + offset) * factor; diff --git a/src/app/application/algorithm/state_estimation/soc/counting/soc_counting_cfg.c b/src/app/driver/can/cbs/tx/can_cbs_tx_string-state.c similarity index 86% rename from src/app/application/algorithm/state_estimation/soc/counting/soc_counting_cfg.c rename to src/app/driver/can/cbs/tx/can_cbs_tx_string-state.c index a9bd3a3e..1ff95da7 100644 --- a/src/app/application/algorithm/state_estimation/soc/counting/soc_counting_cfg.c +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_string-state.c @@ -40,21 +40,27 @@ */ /** - * @file soc_counting_cfg.c + * @file can_cbs_tx_string-state.c * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOC - * - * @brief SOC calculation configuration file + * @date 2023-05-31 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANTX * + * @brief CAN driver Tx callback implementation + * @details CAN Tx callback for state messages */ /*========== Includes =======================================================*/ -#include "soc_counting_cfg.h" +#include "bms.h" +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" +#include "diag.h" +#include "sys_mon.h" +#include #include /*========== Macros and Definitions =========================================*/ diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p0.c b/src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p0.c new file mode 100644 index 00000000..ecaebcc5 --- /dev/null +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p0.c @@ -0,0 +1,86 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file can_cbs_tx_string-values-p0.c + * @author foxBMS Team + * @date 2023-05-31 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANTX + * + * @brief CAN driver Tx callback implementation + * @details CAN Tx callback for pack value and string value messages + */ + +/*========== Includes =======================================================*/ +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ +/* configuration of the StringP0 message bits */ +#define CANTX_STRING_P0_MUX_START_BIT (7u) +#define CANTX_STRING_P0_MUX_LENGTH (4u) +#define CANTX_STRING_P0_VOLTAGE_START_BIT (4u) +#define CANTX_STRING_P0_VOLTAGE_LENGTH (17u) +#define CANTX_STRING_P0_CURRENT_START_BIT (19u) +#define CANTX_STRING_P0_CURRENT_LENGTH (18u) +#define CANTX_STRING_P0_POWER_START_BIT (33u) +#define CANTX_STRING_P0_POWER_LENGTH (18u) + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p1.c b/src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p1.c new file mode 100644 index 00000000..13ff5d62 --- /dev/null +++ b/src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p1.c @@ -0,0 +1,82 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file can_cbs_tx_string-values-p1.c + * @author foxBMS Team + * @date 2023-05-31 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVER + * @prefix CANTX + * + * @brief CAN driver Tx callback implementation + * @details CAN Tx callback for pack value and string value messages + */ + +/*========== Includes =======================================================*/ +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" + +#include +#include + +/*========== Macros and Definitions =========================================*/ +/* configuration of the StringP1 message bits */ +#define CANTX_STRING_P1_STRING_MUX_START_BIT (7u) +#define CANTX_STRING_P1_STRING_MUX_LENGTH (4u) +#define CANTX_STRING_P1_ENERGY_COUNTER_START_BIT (15u) +#define CANTX_STRING_P1_ENERGY_COUNTER_LENGTH (32u) + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/driver/checksum/checksum.c b/src/app/driver/checksum/checksum.c index 675c383e..272464e3 100644 --- a/src/app/driver/checksum/checksum.c +++ b/src/app/driver/checksum/checksum.c @@ -43,8 +43,8 @@ * @file checksum.c * @author foxBMS Team * @date 2019-12-03 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TODO * @prefix CHK * diff --git a/src/app/driver/checksum/checksum.h b/src/app/driver/checksum/checksum.h index 91ebfdd4..adb8cb00 100644 --- a/src/app/driver/checksum/checksum.h +++ b/src/app/driver/checksum/checksum.h @@ -43,8 +43,8 @@ * @file checksum.h * @author foxBMS Team * @date 2019-12-03 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TODO * @prefix CHK * diff --git a/src/app/driver/config/can_cfg.c b/src/app/driver/config/can_cfg.c index d7970394..ec051a87 100644 --- a/src/app/driver/config/can_cfg.c +++ b/src/app/driver/config/can_cfg.c @@ -43,8 +43,8 @@ * @file can_cfg.c * @author foxBMS Team * @date 2019-12-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix CAN * @@ -81,39 +81,46 @@ const CAN_NODE_s can_node2Isolated = { /** local copies of database tables */ /**@{*/ -static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; -static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; -static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; -static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; -static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; -static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; +static DATA_BLOCK_SOH_s can_tableSoh = {.header.uniqueId = DATA_BLOCK_ID_SOH}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; + /**@}*/ const CAN_SHIM_s can_kShim = { .pQueueImd = &ftsk_imdCanDataQueue, - .pTableCellVoltage = &can_tableCellVoltages, .pTableCellTemperature = &can_tableTemperatures, - .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCellVoltage = &can_tableCellVoltages, .pTableCurrentSensor = &can_tableCurrentSensor, - .pTableOpenWire = &can_tableOpenWire, - .pTableStateRequest = &can_tableStateRequest, - .pTablePackValues = &can_tablePackValues, - .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableMol = &can_tableMolFlags, .pTableMsl = &can_tableMslFlags, + .pTableOpenWire = &can_tableOpenWire, + .pTablePackValues = &can_tablePackValues, .pTableRsl = &can_tableRslFlags, - .pTableMol = &can_tableMolFlags, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableSof = &can_tableSof, + .pTableSoh = &can_tableSoh, + .pTableStateRequest = &can_tableStateRequest, + .pTableAerosolSensor = &can_tableAerosolSensor, }; /*========== Static Function Prototypes =====================================*/ diff --git a/src/app/driver/config/can_cfg.h b/src/app/driver/config/can_cfg.h index 58d4c084..eaf9e788 100644 --- a/src/app/driver/config/can_cfg.h +++ b/src/app/driver/config/can_cfg.h @@ -43,8 +43,8 @@ * @file can_cfg.h * @author foxBMS Team * @date 2019-12-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CAN * @@ -178,18 +178,21 @@ typedef struct { OS_QUEUE *pQueueImd; /*!< handle of the message queue */ DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage; /*!< database table with cell voltages */ DATA_BLOCK_CELL_TEMPERATURE_s *pTableCellTemperature; /*!< database table with cell temperatures */ - DATA_BLOCK_MIN_MAX_s *pTableMinMax; /*!< database table with min/max values */ DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor; /*!< database table with current sensor measurements */ - DATA_BLOCK_OPEN_WIRE_s *pTableOpenWire; /*!< database table with open wire status */ - DATA_BLOCK_STATE_REQUEST_s *pTableStateRequest; /*!< database table with state requests */ - DATA_BLOCK_PACK_VALUES_s *pTablePackValues; /*!< database table with pack values */ - DATA_BLOCK_SOF_s *pTableSof; /*!< database table with SOF values */ - DATA_BLOCK_SOX_s *pTableSox; /*!< database table with SOC and SOE values */ DATA_BLOCK_ERROR_STATE_s *pTableErrorState; /*!< database table with error state variables */ DATA_BLOCK_INSULATION_MONITORING_s *pTableInsulation; /*!< database table with insulation monitoring info */ + DATA_BLOCK_MIN_MAX_s *pTableMinMax; /*!< database table with min/max values */ + DATA_BLOCK_MOL_FLAG_s *pTableMol; /*!< database table with MOL flags */ DATA_BLOCK_MSL_FLAG_s *pTableMsl; /*!< database table with MSL flags */ + DATA_BLOCK_OPEN_WIRE_s *pTableOpenWire; /*!< database table with open wire status */ + DATA_BLOCK_PACK_VALUES_s *pTablePackValues; /*!< database table with pack values */ DATA_BLOCK_RSL_FLAG_s *pTableRsl; /*!< database table with RSL flags */ - DATA_BLOCK_MOL_FLAG_s *pTableMol; /*!< database table with MOL flags */ + DATA_BLOCK_SOC_s *pTableSoc; /*!< database table with SOC values */ + DATA_BLOCK_SOE_s *pTableSoe; /*!< database table with SOE values */ + DATA_BLOCK_SOF_s *pTableSof; /*!< database table with SOF values */ + DATA_BLOCK_SOH_s *pTableSoh; /*!< database table with SOH values */ + DATA_BLOCK_STATE_REQUEST_s *pTableStateRequest; /*!< database table with state requests */ + DATA_BLOCK_AEROSOL_SENSOR_s *pTableAerosolSensor; /*!< database table with aerosol sensor measurements */ } CAN_SHIM_s; /** definition of a CAN message (without data) */ @@ -258,8 +261,8 @@ extern const CAN_RX_MESSAGE_TYPE_s can_rxMessages[]; /**@}*/ /** array length for transmission CAN0 message definition @{*/ -extern const uint8_t can_txLength; -extern const uint8_t can_rxLength; +extern const uint8_t can_txMessagesLength; +extern const uint8_t can_rxMessagesLength; /**@}*/ /*========== Extern Function Prototypes =====================================*/ diff --git a/src/app/driver/config/can_cfg_rx-message-definitions.h b/src/app/driver/config/can_cfg_rx-message-definitions.h index 73e33029..58f20b71 100644 --- a/src/app/driver/config/can_cfg_rx-message-definitions.h +++ b/src/app/driver/config/can_cfg_rx-message-definitions.h @@ -43,8 +43,8 @@ * @file can_cfg_rx-message-definitions.h * @author foxBMS Team * @date 2022-07-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CANRX * @@ -87,6 +87,17 @@ #define CANRX_DEBUG_ENDIANNESS (CAN_BIG_ENDIAN) /**@}*/ +/** CAN message properties for aerosol sensor. Required properties are: + * - Message ID + * - Identifier type (standard or extended) + * - Expected message period in ms or if asynchronous message + * - Endianness of message data @{*/ +#define CANRX_AEROSOL_SENSOR_ID (0x3C4u) +#define CANRX_AEROSOL_SENSOR_ID_TYPE (CAN_STANDARD_IDENTIFIER_11_BIT) +#define CANRX_AEROSOL_SENSOR_PERIOD_ms (1000u) +#define CANRX_AEROSOL_SENSOR_ENDIANNESS (CAN_BIG_ENDIAN) +/**@}*/ + /** * -------------------------CAUTION------------------------- * The following defines are used by the insulation monitoring device (IMD). @@ -153,6 +164,17 @@ .period = CANRX_DEBUG_PERIOD_ms \ } +#define CANRX_AEROSOL_SENSOR_MESSAGE \ + { \ + .id = CANRX_AEROSOL_SENSOR_ID, \ + .idType = CANRX_AEROSOL_SENSOR_ID_TYPE, \ + .dlc = CAN_DEFAULT_DLC, \ + .endianness = CANRX_AEROSOL_SENSOR_ENDIANNESS, \ + }, \ + { \ + .period = CANRX_AEROSOL_SENSOR_PERIOD_ms \ + } + #define CANRX_IMD_INFO_MESSAGE \ { \ .id = CANRX_IMD_INFO_ID, \ diff --git a/src/app/driver/config/can_cfg_rx.c b/src/app/driver/config/can_cfg_rx.c index 2238818b..dc3d9e90 100644 --- a/src/app/driver/config/can_cfg_rx.c +++ b/src/app/driver/config/can_cfg_rx.c @@ -43,8 +43,8 @@ * @file can_cfg_rx.c * @author foxBMS Team * @date 2019-12-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix CANRX * @@ -86,10 +86,11 @@ const CAN_RX_MESSAGE_TYPE_s can_rxMessages[] = { {CAN_NODE_CURRENT_SENSOR, CANRX_STRING0_CURRENT_COUNTER_MESSAGE, &CANRX_CurrentSensor}, {CAN_NODE_CURRENT_SENSOR, CANRX_STRING0_ENERGY_COUNTER_MESSAGE, &CANRX_CurrentSensor}, {CAN_NODE_DEBUG_MESSAGE, CANRX_DEBUG_MESSAGE, &CANRX_Debug}, + {CAN_NODE_1, CANRX_AEROSOL_SENSOR_MESSAGE, &CANRX_AerosolSensor}, }; /** length of CAN message arrays */ -const uint8_t can_rxLength = sizeof(can_rxMessages) / sizeof(can_rxMessages[0]); +const uint8_t can_rxMessagesLength = sizeof(can_rxMessages) / sizeof(can_rxMessages[0]); /*========== Static Function Prototypes =====================================*/ diff --git a/src/app/driver/config/can_cfg_tx-message-definitions.h b/src/app/driver/config/can_cfg_tx-message-definitions.h index 57747d85..9b7bb8cf 100644 --- a/src/app/driver/config/can_cfg_tx-message-definitions.h +++ b/src/app/driver/config/can_cfg_tx-message-definitions.h @@ -43,8 +43,8 @@ * @file can_cfg_tx-message-definitions.h * @author foxBMS Team * @date 2022-07-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CANTX * @@ -72,6 +72,10 @@ #define CANTX_UNSUPPORTED_MULTIPLEXER_VAL_ID (0x201u) /* check_ids:not-periodic */ #define CANTX_UNSUPPORTED_MULTIPLEXER_IDENTIFIER (CAN_STANDARD_IDENTIFIER_11_BIT) +/** CAN message ID for fatal errors */ +#define CANTX_FATAL_ERRORS_ID (0x0FFu) /* check_ids:not-periodic */ +#define CANTX_FATAL_ERRORS_IDENTIFIER (CAN_STANDARD_IDENTIFIER_11_BIT) + /** CAN message properties for BMS state message. Required properties are: * - Message ID * - Identifier type (standard or extended) diff --git a/src/app/driver/config/can_cfg_tx.c b/src/app/driver/config/can_cfg_tx.c index 59d565f2..4788c037 100644 --- a/src/app/driver/config/can_cfg_tx.c +++ b/src/app/driver/config/can_cfg_tx.c @@ -43,8 +43,8 @@ * @file can_cfg_tx.c * @author foxBMS Team * @date 2019-12-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix CANTX * @@ -100,7 +100,7 @@ const CAN_TX_MESSAGE_TYPE_s can_txMessages[] = { }; /** length of CAN message arrays */ -const uint8_t can_txLength = sizeof(can_txMessages) / sizeof(can_txMessages[0]); +const uint8_t can_txMessagesLength = sizeof(can_txMessages) / sizeof(can_txMessages[0]); /*========== Static Function Prototypes =====================================*/ diff --git a/src/app/driver/config/contactor_cfg.c b/src/app/driver/config/contactor_cfg.c index 4ef0ab43..772d0cf4 100644 --- a/src/app/driver/config/contactor_cfg.c +++ b/src/app/driver/config/contactor_cfg.c @@ -43,8 +43,8 @@ * @file contactor_cfg.c * @author foxBMS Team * @date 2020-02-11 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONF * @prefix CONT * diff --git a/src/app/driver/config/contactor_cfg.h b/src/app/driver/config/contactor_cfg.h index 85ad1010..dbe86243 100644 --- a/src/app/driver/config/contactor_cfg.h +++ b/src/app/driver/config/contactor_cfg.h @@ -43,8 +43,8 @@ * @file contactor_cfg.h * @author foxBMS Team * @date 2020-02-11 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix CONT * diff --git a/src/app/driver/config/dma_cfg.c b/src/app/driver/config/dma_cfg.c index a7fe302a..8d64b4c3 100644 --- a/src/app/driver/config/dma_cfg.c +++ b/src/app/driver/config/dma_cfg.c @@ -43,8 +43,8 @@ * @file dma_cfg.c * @author foxBMS Team * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix DMA * diff --git a/src/app/driver/config/dma_cfg.h b/src/app/driver/config/dma_cfg.h index ace6359e..fcfb6fca 100644 --- a/src/app/driver/config/dma_cfg.h +++ b/src/app/driver/config/dma_cfg.h @@ -43,8 +43,8 @@ * @file dma_cfg.h * @author foxBMS Team * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix DMA * diff --git a/src/app/driver/config/fram_cfg.c b/src/app/driver/config/fram_cfg.c index f73e757b..3d0f35b0 100644 --- a/src/app/driver/config/fram_cfg.c +++ b/src/app/driver/config/fram_cfg.c @@ -43,8 +43,8 @@ * @file fram_cfg.c * @author foxBMS Team * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix FRAM * diff --git a/src/app/driver/config/fram_cfg.h b/src/app/driver/config/fram_cfg.h index 885f401c..e3274f07 100644 --- a/src/app/driver/config/fram_cfg.h +++ b/src/app/driver/config/fram_cfg.h @@ -43,8 +43,8 @@ * @file fram_cfg.h * @author foxBMS Team * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix FRAM * diff --git a/src/app/driver/config/interlock_cfg.h b/src/app/driver/config/interlock_cfg.h index 368c8318..ad71d9b7 100644 --- a/src/app/driver/config/interlock_cfg.h +++ b/src/app/driver/config/interlock_cfg.h @@ -43,8 +43,8 @@ * @file interlock_cfg.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix ILCK * @@ -101,7 +101,7 @@ #define ILCK_FACTOR_IL_LS_CS_1_ohm (0.025f) /** - * @brief ILCK statemachine short time definition in #ILCK_Trigger() calls + * @brief ILCK state machine short time definition in #ILCK_Trigger() calls * until next state/substate is processed */ #define ILCK_STATEMACH_SHORTTIME (1u) diff --git a/src/app/driver/config/nxpfs85xx_cfg.h b/src/app/driver/config/nxpfs85xx_cfg.h index c37ac40d..6205f6a6 100644 --- a/src/app/driver/config/nxpfs85xx_cfg.h +++ b/src/app/driver/config/nxpfs85xx_cfg.h @@ -43,8 +43,8 @@ * @file nxpfs85xx_cfg.h * @author foxBMS Team * @date 2020-03-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix SBC * diff --git a/src/app/driver/config/pex_cfg.c b/src/app/driver/config/pex_cfg.c index 24c28d10..ce12f65d 100644 --- a/src/app/driver/config/pex_cfg.c +++ b/src/app/driver/config/pex_cfg.c @@ -43,8 +43,8 @@ * @file pex_cfg.c * @author foxBMS Team * @date 2021-08-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix PEX * diff --git a/src/app/driver/config/pex_cfg.h b/src/app/driver/config/pex_cfg.h index 59d9c9a8..b0a63a22 100644 --- a/src/app/driver/config/pex_cfg.h +++ b/src/app/driver/config/pex_cfg.h @@ -43,8 +43,8 @@ * @file pex_cfg.h * @author foxBMS Team * @date 2021-08-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix PEX * diff --git a/src/app/driver/config/spi_cfg.c b/src/app/driver/config/spi_cfg.c index a8ff6b12..90ff2385 100644 --- a/src/app/driver/config/spi_cfg.c +++ b/src/app/driver/config/spi_cfg.c @@ -43,8 +43,8 @@ * @file spi_cfg.c * @author foxBMS Team * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix SPI * @@ -85,6 +85,16 @@ * SPIDAT1 register activates the corresponding Chip Select pin. */ +/** SPI data configuration struct for ADI communication */ +static spiDAT1_t spi_kAdiDataConfig[BS_NR_OF_STRINGS] = { + { /* struct is implemented in the TI HAL and uses uppercase true and false */ + .CS_HOLD = TRUE, /* If true, HW chip select kept active between words */ + .WDEL = FALSE, /* Activation of delay between words */ + .DFSEL = SPI_FMT_0, /* Data word format selection */ + /* Hardware chip select is configured automatically depending on configuration in #SPI_INTERFACE_CONFIG_s */ + .CSNR = SPI_HARDWARE_CHIP_SELECT_DISABLE_ALL}, +}; + /** SPI data configuration struct for LTC communication */ static spiDAT1_t spi_kLtcDataConfig[BS_NR_OF_STRINGS] = { { /* struct is implemented in the TI HAL and uses uppercase true and false */ @@ -164,6 +174,20 @@ static spiDAT1_t spi_kSbcDataConfig = { /*========== Extern Constant and Variable Definitions =======================*/ +/** + * SPI interface configuration for ADI communication + * This is a list of structs because of multistring + */ +SPI_INTERFACE_CONFIG_s spi_adiInterface[BS_NR_OF_STRINGS] = { + { + .pConfig = &spi_kAdiDataConfig[0u], + .pNode = spiREG1, + .pGioPort = &(spiREG1->PC3), + .csPin = SPI_ADI_CHIP_SELECT_PIN, + .csType = SPI_CHIP_SELECT_HARDWARE, + }, +}; + /** * SPI interface configuration for LTC communication * This is a list of structs because of multistring diff --git a/src/app/driver/config/spi_cfg.h b/src/app/driver/config/spi_cfg.h index 04e5a260..0ba09a11 100644 --- a/src/app/driver/config/spi_cfg.h +++ b/src/app/driver/config/spi_cfg.h @@ -43,8 +43,8 @@ * @file spi_cfg.h * @author foxBMS Team * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix SPI * @@ -132,6 +132,9 @@ typedef struct { /* INCLUDE MARKER FOR THE DOCUMENTATION; DO NOT MOVE spi-documentation-configuration-stop-include */ /* -------------- SPI Configurations --------------------------------------- */ +/** ADI chip select pin */ +#define SPI_ADI_CHIP_SELECT_PIN (1u) + /** LTC chip select pin */ #define SPI_LTC_CHIP_SELECT_PIN (1u) @@ -153,6 +156,7 @@ typedef struct { /**@}*/ /*========== Extern Constant and Variable Declarations ======================*/ +extern SPI_INTERFACE_CONFIG_s spi_adiInterface[BS_NR_OF_STRINGS]; extern SPI_INTERFACE_CONFIG_s spi_ltcInterface[BS_NR_OF_STRINGS]; extern SPI_INTERFACE_CONFIG_s spi_mxmInterface; extern SPI_INTERFACE_CONFIG_s spi_nxp775InterfaceTx[BS_NR_OF_STRINGS]; diff --git a/src/app/driver/config/sps_cfg.c b/src/app/driver/config/sps_cfg.c index b47d1a68..55dd6656 100644 --- a/src/app/driver/config/sps_cfg.c +++ b/src/app/driver/config/sps_cfg.c @@ -43,8 +43,8 @@ * @file sps_cfg.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONF * @prefix SPS * diff --git a/src/app/driver/config/sps_cfg.h b/src/app/driver/config/sps_cfg.h index ed07464a..d24fd36a 100644 --- a/src/app/driver/config/sps_cfg.h +++ b/src/app/driver/config/sps_cfg.h @@ -43,8 +43,8 @@ * @file sps_cfg.h * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONF * @prefix SPS * diff --git a/src/app/driver/config/tsi_plausibility_cfg.h b/src/app/driver/config/tsi_plausibility_cfg.h index 00425fce..2a9a8aaf 100644 --- a/src/app/driver/config/tsi_plausibility_cfg.h +++ b/src/app/driver/config/tsi_plausibility_cfg.h @@ -43,8 +43,8 @@ * @file tsi_plausibility_cfg.h * @author foxBMS Team * @date 2019-01-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup MODULES * @prefix TSI * diff --git a/src/app/driver/contactor/contactor.c b/src/app/driver/contactor/contactor.c index e76e314b..a506d210 100644 --- a/src/app/driver/contactor/contactor.c +++ b/src/app/driver/contactor/contactor.c @@ -43,8 +43,8 @@ * @file contactor.c * @author foxBMS Team * @date 2020-02-11 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CONT * diff --git a/src/app/driver/contactor/contactor.h b/src/app/driver/contactor/contactor.h index 46589765..8c2dd6d9 100644 --- a/src/app/driver/contactor/contactor.h +++ b/src/app/driver/contactor/contactor.h @@ -43,8 +43,8 @@ * @file contactor.h * @author foxBMS Team * @date 2020-02-11 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CONT * diff --git a/src/app/driver/crc/crc.c b/src/app/driver/crc/crc.c index 8346cf89..244e9942 100644 --- a/src/app/driver/crc/crc.c +++ b/src/app/driver/crc/crc.c @@ -43,8 +43,8 @@ * @file crc.c * @author foxBMS Team * @date 2022-02-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CRC * diff --git a/src/app/driver/crc/crc.h b/src/app/driver/crc/crc.h index 6bd1ea72..58f91e17 100644 --- a/src/app/driver/crc/crc.h +++ b/src/app/driver/crc/crc.h @@ -43,8 +43,8 @@ * @file crc.h * @author foxBMS Team * @date 2022-02-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix CRC * diff --git a/src/app/driver/dma/dma.c b/src/app/driver/dma/dma.c index 3733fb1d..53865852 100644 --- a/src/app/driver/dma/dma.c +++ b/src/app/driver/dma/dma.c @@ -43,8 +43,8 @@ * @file dma.c * @author foxBMS Team * @date 2019-12-12 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix DMA * diff --git a/src/app/driver/dma/dma.h b/src/app/driver/dma/dma.h index ab979ada..4b29d54a 100644 --- a/src/app/driver/dma/dma.h +++ b/src/app/driver/dma/dma.h @@ -43,8 +43,8 @@ * @file dma.h * @author foxBMS Team * @date 2019-12-12 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix DMA * diff --git a/src/app/driver/foxmath/foxmath.c b/src/app/driver/foxmath/foxmath.c index ab274dd7..884dff00 100644 --- a/src/app/driver/foxmath/foxmath.c +++ b/src/app/driver/foxmath/foxmath.c @@ -43,8 +43,8 @@ * @file foxmath.c * @author foxBMS Team * @date 2018-01-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MATH * diff --git a/src/app/driver/foxmath/foxmath.h b/src/app/driver/foxmath/foxmath.h index 68ea558c..7183a371 100644 --- a/src/app/driver/foxmath/foxmath.h +++ b/src/app/driver/foxmath/foxmath.h @@ -43,8 +43,8 @@ * @file foxmath.h * @author foxBMS Team * @date 2018-01-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MATH * diff --git a/src/app/driver/foxmath/utils.h b/src/app/driver/foxmath/utils.h index e8a41894..f4e3f65c 100644 --- a/src/app/driver/foxmath/utils.h +++ b/src/app/driver/foxmath/utils.h @@ -43,8 +43,8 @@ * @file utils.h * @author foxBMS Team * @date 2022-11-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix UTIL * diff --git a/src/app/driver/fram/fram.c b/src/app/driver/fram/fram.c index 9758cada..ab0f4645 100644 --- a/src/app/driver/fram/fram.c +++ b/src/app/driver/fram/fram.c @@ -43,8 +43,8 @@ * @file fram.c * @author foxBMS Team * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix FRAM * diff --git a/src/app/driver/fram/fram.h b/src/app/driver/fram/fram.h index 465f3b6c..57d48582 100644 --- a/src/app/driver/fram/fram.h +++ b/src/app/driver/fram/fram.h @@ -43,8 +43,8 @@ * @file fram.h * @author foxBMS Team * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix FRAM * diff --git a/src/app/driver/htsensor/htsensor.c b/src/app/driver/htsensor/htsensor.c index ec2d7d08..cc089f0b 100644 --- a/src/app/driver/htsensor/htsensor.c +++ b/src/app/driver/htsensor/htsensor.c @@ -43,8 +43,8 @@ * @file htsensor.c * @author foxBMS Team * @date 2021-08-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix HTSEN * @@ -150,8 +150,8 @@ /*========== Static Constant and Variable Definitions =======================*/ #pragma SET_DATA_SECTION(".sharedRAM") -uint8_t i2cReadBuffer[HTSEN_TOTAL_DATA_LENGTH_IN_BYTES] = {0u, 0u, 0u, 0u, 0u, 0u}; -uint8_t i2cWriteBuffer[2u] = {HTSEN_SINGLE_MEAS_MSB, HTSEN_SINGLE_MEAS_LSB}; +static uint8_t htsen_i2cReadBuffer[HTSEN_TOTAL_DATA_LENGTH_IN_BYTES] = {0u, 0u, 0u, 0u, 0u, 0u}; +static uint8_t htsen_i2cWriteBuffer[2u] = {HTSEN_SINGLE_MEAS_MSB, HTSEN_SINGLE_MEAS_LSB}; #pragma SET_DATA_SECTION() /** variable to store the measurement results */ @@ -228,7 +228,7 @@ extern void HTSEN_Trigger(void) { switch (htsenState) { case HTSEN_START_MEAS: /* Trigger a measurement */ - htsenReturnValue = I2C_WriteDma(HTSEN_I2C_INTERFACE, HTSEN_I2C_ADDRESS, 2u, i2cWriteBuffer); + htsenReturnValue = I2C_WriteDma(HTSEN_I2C_INTERFACE, HTSEN_I2C_ADDRESS, 2u, htsen_i2cWriteBuffer); OS_DelayTaskUntil(¤t_time, 2u); if (htsenReturnValue == STD_OK) { htsenState = HTSEN_READ_RESULTS; @@ -237,25 +237,26 @@ extern void HTSEN_Trigger(void) { break; case HTSEN_READ_RESULTS: /* Try to read values */ - htsenReturnValue = - I2C_ReadDma(HTSEN_I2C_INTERFACE, HTSEN_I2C_ADDRESS, HTSEN_TOTAL_DATA_LENGTH_IN_BYTES, i2cReadBuffer); + htsenReturnValue = I2C_ReadDma( + HTSEN_I2C_INTERFACE, HTSEN_I2C_ADDRESS, HTSEN_TOTAL_DATA_LENGTH_IN_BYTES, htsen_i2cReadBuffer); OS_DelayTaskUntil(¤t_time, 2u); if (htsenReturnValue == STD_OK) { /* If sensor acknowledges on I2C bus, results are available */ /* Check if CRC valid */ /* Only take temperature value if CRC valid */ - if (i2cReadBuffer[HTSEN_TEMPERATURE_BYTE_CRC] == - HTSEN_CalculateCrc8(&i2cReadBuffer[HTSEN_TEMPERATURE_MSB], HTSEN_MEASUREMENT_LENGTH_IN_BYTES)) { + if (htsen_i2cReadBuffer[HTSEN_TEMPERATURE_BYTE_CRC] == + HTSEN_CalculateCrc8( + &htsen_i2cReadBuffer[HTSEN_TEMPERATURE_MSB], HTSEN_MEASUREMENT_LENGTH_IN_BYTES)) { htsen_data.temperature_ddegC = HTSEN_ConvertRawTemperature( - (((uint16_t)i2cReadBuffer[HTSEN_TEMPERATURE_MSB]) << HTSEN_BYTE_SHIFT) | - (uint16_t)i2cReadBuffer[HTSEN_TEMPERATURE_LSB]); + (((uint16_t)htsen_i2cReadBuffer[HTSEN_TEMPERATURE_MSB]) << HTSEN_BYTE_SHIFT) | + (uint16_t)htsen_i2cReadBuffer[HTSEN_TEMPERATURE_LSB]); } /* Only take humidity value if CRC valid */ - if (i2cReadBuffer[HTSEN_HUMIDITY_BYTE_CRC] == - HTSEN_CalculateCrc8(&i2cReadBuffer[HTSEN_HUMIDITY_MSB], HTSEN_MEASUREMENT_LENGTH_IN_BYTES)) { + if (htsen_i2cReadBuffer[HTSEN_HUMIDITY_BYTE_CRC] == + HTSEN_CalculateCrc8(&htsen_i2cReadBuffer[HTSEN_HUMIDITY_MSB], HTSEN_MEASUREMENT_LENGTH_IN_BYTES)) { htsen_data.humidity_perc = HTSEN_ConvertRawHumidity( - (((uint16_t)i2cReadBuffer[HTSEN_HUMIDITY_MSB]) << HTSEN_BYTE_SHIFT) | - (uint16_t)i2cReadBuffer[HTSEN_HUMIDITY_LSB]); + (((uint16_t)htsen_i2cReadBuffer[HTSEN_HUMIDITY_MSB]) << HTSEN_BYTE_SHIFT) | + (uint16_t)htsen_i2cReadBuffer[HTSEN_HUMIDITY_LSB]); } DATA_WRITE_DATA(&htsen_data); htsenState = HTSEN_START_MEAS; diff --git a/src/app/driver/htsensor/htsensor.h b/src/app/driver/htsensor/htsensor.h index 8ecae28d..a85d7561 100644 --- a/src/app/driver/htsensor/htsensor.h +++ b/src/app/driver/htsensor/htsensor.h @@ -43,8 +43,8 @@ * @file htsensor.h * @author foxBMS Team * @date 2021-08-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix HTSEN * diff --git a/src/app/driver/i2c/i2c.c b/src/app/driver/i2c/i2c.c index bfa3fba5..d1e9da07 100644 --- a/src/app/driver/i2c/i2c.c +++ b/src/app/driver/i2c/i2c.c @@ -43,8 +43,8 @@ * @file i2c.c * @author foxBMS Team * @date 2021-07-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix I2C * diff --git a/src/app/driver/i2c/i2c.h b/src/app/driver/i2c/i2c.h index 9b82ff2c..1620f706 100644 --- a/src/app/driver/i2c/i2c.h +++ b/src/app/driver/i2c/i2c.h @@ -43,8 +43,8 @@ * @file i2c.h * @author foxBMS Team * @date 2021-07-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix I2C * diff --git a/src/app/driver/imd/bender/ir155/bender_ir155.c b/src/app/driver/imd/bender/ir155/bender_ir155.c index 89780fd4..746b26a6 100644 --- a/src/app/driver/imd/bender/ir155/bender_ir155.c +++ b/src/app/driver/imd/bender/ir155/bender_ir155.c @@ -43,8 +43,8 @@ * @file bender_ir155.c * @author foxBMS Team * @date 2014-02-11 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix IR155 * @@ -67,7 +67,7 @@ /*========== Macros and Definitions =========================================*/ /** - * Dutycycle - resistance table + * Duty cycle - resistance table * for Bender IR155-3204 (Art. No. B91068139) * * dc | resistance/kOhm | description | @@ -136,7 +136,7 @@ static IMD_FSM_STATES_e IR155_MeasureInsulation(DATA_BLOCK_INSULATION_MONITORING } if (ir155_state.timeUntilValidMeasurement_ms == 0u) { - /* If hysteresis is over, reset diag flag and reset grounderror flag */ + /* If hysteresis is over, reset diag flag and reset ground error flag */ /* TODO: How to handle the ground error fault after reset? Do this in diag callback?*/ /* Reset non-volatile ground error flag - Do this in diag callback? */ fram_insulationFlags.groundErrorDetected = false; @@ -180,7 +180,7 @@ static IMD_FSM_STATES_e IR155_MeasureInsulation(DATA_BLOCK_INSULATION_MONITORING if ((ir155_state.measurement.measurementState == IR155_RESISTANCE_MEASUREMENT_UNKNOWN) || (ir155_state.measurement.measurementState == IR155_RESISTANCE_ESTIMATION_UNKNOWN) || (ir155_state.measurement.measurementState == IR155_UNDERVOLTAGE_MEASUREMENT_UNKNOWN) || - (ir155_state.measurement.measurementState == IR155_GROUND_ERROR_MODE_UNKNOWN)) { + (ir155_state.measurement.measurementState == IR155_GROUND_ERROR_STATE_UNKNOWN)) { pTableInsulationMonitoring->dfIsDeviceErrorDetected = true; } else { pTableInsulationMonitoring->dfIsDeviceErrorDetected = false; @@ -189,7 +189,7 @@ static IMD_FSM_STATES_e IR155_MeasureInsulation(DATA_BLOCK_INSULATION_MONITORING /* Check for chassis fault */ pTableInsulationMonitoring->dfIsChassisShortToHvPlus = false; /* This feature is not supported by the device */ pTableInsulationMonitoring->dfIsChassisShortToHvMinus = false; /* This feature is not supported by the device */ - if (ir155_state.measurement.measurementState == IR155_GROUND_ERROR_MODE) { + if (ir155_state.measurement.measurementState == IR155_GROUND_ERROR_STATE) { pTableInsulationMonitoring->dfIsChassisFaultDetected = true; } else { pTableInsulationMonitoring->dfIsDeviceErrorDetected = false; diff --git a/src/app/driver/imd/bender/ir155/bender_ir155.h b/src/app/driver/imd/bender/ir155/bender_ir155.h index a42e0dd4..97ff1f30 100644 --- a/src/app/driver/imd/bender/ir155/bender_ir155.h +++ b/src/app/driver/imd/bender/ir155/bender_ir155.h @@ -43,8 +43,8 @@ * @file bender_ir155.h * @author foxBMS Team * @date 2021-09-06 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix IR155 * diff --git a/src/app/driver/imd/bender/ir155/bender_ir155_helper.c b/src/app/driver/imd/bender/ir155/bender_ir155_helper.c index 8f85fc00..e116add3 100644 --- a/src/app/driver/imd/bender/ir155/bender_ir155_helper.c +++ b/src/app/driver/imd/bender/ir155/bender_ir155_helper.c @@ -43,8 +43,8 @@ * @file bender_ir155_helper.c * @author foxBMS Team * @date 2021-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix IR155 * @@ -95,7 +95,7 @@ /*========== Static Constant and Variable Definitions =======================*/ /*========== Extern Constant and Variable Definitions =======================*/ -extern IR155_STATE_s ir155_state = { +IR155_STATE_s ir155_state = { .ir155Initialized = false, .measurement.isMeasurementValid = false, .measurement.isUndervoltageDetected = false, @@ -119,7 +119,7 @@ extern IR155_STATE_s ir155_state = { static IR155_MEASUREMENT_MODE_e IR155_GetMeasurementMode(float_t frequency_Hz); /** - * @brief Calculate insulation resistance from measured dutycycle. + * @brief Calculate insulation resistance from measured duty cycle. * @details Function check, that passed duty-cycle lies within allowed range. * Otherwise, the calculated resistance will be limited to the next * reasonable value. @@ -150,8 +150,9 @@ static IR155_MEASUREMENT_MODE_e IR155_GetMeasurementMode(float_t frequency_Hz) { (frequency_Hz < IR155_UNDERVOLTAGE_UPPER_FREQUENCY_Hz)) { retVal = IR155_UNDERVOLTAGE_MODE; /* should not be detected as default threshold 0V, EOL Bender configurable! */ } else if ( - (frequency_Hz >= IR155_SPEEDSTART_LOWER_FREQUENCY_Hz) && (frequency_Hz < IR155_SPEEDSTART_UPPER_FREQUENCY_Hz)) { - retVal = IR155_SPEEDSTART_MODE; + (frequency_Hz >= IR155_SPEED_START_LOWER_FREQUENCY_Hz) && + (frequency_Hz < IR155_SPEED_START_UPPER_FREQUENCY_Hz)) { + retVal = IR155_SPEED_START_MODE; } else if ( (frequency_Hz >= IR155_IMD_DEVICE_ERROR_LOWER_FREQUENCY_Hz) && (frequency_Hz < IR155_IMD_DEVICE_ERROR_UPPER_FREQUENCY_Hz)) { @@ -159,7 +160,7 @@ static IR155_MEASUREMENT_MODE_e IR155_GetMeasurementMode(float_t frequency_Hz) { } else if ( (frequency_Hz >= IR155_GROUND_ERROR_LOWER_FREQUENCY_Hz) && (frequency_Hz < IR155_GROUND_ERROR_UPPER_FREQUENCY_Hz)) { - retVal = IR155_GROUNDERROR_MODE; + retVal = IR155_GROUND_ERROR_MODE; } else if (frequency_Hz <= IR155_MINIMUM_FREQUENCY_Hz) { retVal = IR155_SHORT_CLAMP; } else { @@ -204,7 +205,7 @@ void IR155_Initialize(uint8_t triggerTime_ms) { /* Read non-volatile FRAM */ FRAM_ReadData(FRAM_BLOCK_ID_INSULATION_FLAG); - /* Check grounderror flag */ + /* Check ground error flag */ if (fram_insulationFlags.groundErrorDetected == true) { /* GROUND ERROR occurred before shutting down */ ir155_state.timeUntilValidMeasurement_ms = IR155_WAIT_TIME_AFTER_GROUND_ERROR_ms; @@ -288,7 +289,7 @@ IR155_MEASUREMENT_s IR155_GetMeasurementValues(void) { } break; - case IR155_SPEEDSTART_MODE: + case IR155_SPEED_START_MODE: measurementResult.isUndervoltageDetected = false; if (true == IR155_IsDutyCycleWithinInterval( measurementResult.pwmSignal.dutyCycle_perc, @@ -345,7 +346,7 @@ IR155_MEASUREMENT_s IR155_GetMeasurementValues(void) { measurementResult.isMeasurementValid = false; } break; - case IR155_GROUNDERROR_MODE: + case IR155_GROUND_ERROR_MODE: measurementResult.isUndervoltageDetected = false; measurementResult.resistance_kOhm = IR155_MINIMUM_INSULATION_RESISTANCE_kOhm; if (true == IR155_IsDutyCycleWithinInterval( @@ -354,10 +355,10 @@ IR155_MEASUREMENT_s IR155_GetMeasurementValues(void) { IR155_GROUND_ERROR_UPPER_DUTY_CYCLE_LIMIT_perc)) { /* Error detected and verified with duty cycle */ measurementResult.isMeasurementValid = true; - measurementResult.measurementState = IR155_GROUND_ERROR_MODE; + measurementResult.measurementState = IR155_GROUND_ERROR_STATE; } else { /* Error detected but invalid duty cycle */ - measurementResult.measurementState = IR155_GROUND_ERROR_MODE_UNKNOWN; + measurementResult.measurementState = IR155_GROUND_ERROR_STATE_UNKNOWN; measurementResult.isMeasurementValid = false; } break; diff --git a/src/app/driver/imd/bender/ir155/bender_ir155_helper.h b/src/app/driver/imd/bender/ir155/bender_ir155_helper.h index 8b6c5d4d..e2187dee 100644 --- a/src/app/driver/imd/bender/ir155/bender_ir155_helper.h +++ b/src/app/driver/imd/bender/ir155/bender_ir155_helper.h @@ -43,8 +43,8 @@ * @file bender_ir155_helper.h * @author foxBMS Team * @date 2021-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix IR155 * @@ -79,13 +79,13 @@ */ typedef enum IR155_MEASUREMENT_MODE { IR155_NORMAL_MODE, /*!< PWM frequency: 10Hz */ - IR155_SPEEDSTART_MODE, /*!< PWM frequency: 30Hz */ + IR155_SPEED_START_MODE, /*!< PWM frequency: 30Hz */ IR155_UNDERVOLTAGE_MODE, /*!< PWM frequency: 20Hz */ IR155_IMD_ERROR_MODE, /*!< PWM frequency: 40Hz */ - IR155_GROUNDERROR_MODE, /*!< PWM frequency: 50Hz */ + IR155_GROUND_ERROR_MODE, /*!< PWM frequency: 50Hz */ IR155_SHORT_CLAMP, /*!< PWM frequency: 0Hz */ IR155_UNDEFINED_FREQUENCY, /*!< illegal frequency detected*/ - IR155_DUTY_CYCLE_MEASUREMENT, /*!< corrupt signal measurement (e.g. T_on > T_periode,)*/ + IR155_DUTY_CYCLE_MEASUREMENT, /*!< corrupt signal measurement (e.g., T_on > T_period,)*/ IR155_NOSIGNAL, /*!< no signal (e.g. if 100% -> wire break, if 0% -> shortcut to GND */ IR155_UNKNOWN, } IR155_MEASUREMENT_MODE_e; @@ -97,12 +97,12 @@ typedef enum IR155_MEASUREMENT_MODE { typedef enum IR155_MEASUREMENT_STATE { IR155_RESISTANCE_MEASUREMENT, /*!< valid normal measurement working */ IR155_RESISTANCE_MEASUREMENT_UNKNOWN, /*!< normal measurement with undefined duty cycle */ - IR155_RESISTANCE_ESTIMATION, /*!< SPEEDSTART estimation working */ - IR155_RESISTANCE_ESTIMATION_UNKNOWN, /*!< SPEEDSTART estimation with undefined duty cycle */ - IR155_UNDERVOLTAGE_MEASUREMENT, /*!< SPEEDSTART estimation working */ - IR155_UNDERVOLTAGE_MEASUREMENT_UNKNOWN, /*!< SPEEDSTART estimation with undefined duty cycle */ - IR155_GROUND_ERROR_MODE, /*!< ground error detected */ - IR155_GROUND_ERROR_MODE_UNKNOWN, /*!< ground error detected with undefined duty cycle */ + IR155_RESISTANCE_ESTIMATION, /*!< SPEED START estimation working */ + IR155_RESISTANCE_ESTIMATION_UNKNOWN, /*!< SPEED START estimation with undefined duty cycle */ + IR155_UNDERVOLTAGE_MEASUREMENT, /*!< SPEED START estimation working */ + IR155_UNDERVOLTAGE_MEASUREMENT_UNKNOWN, /*!< SPEED START estimation with undefined duty cycle */ + IR155_GROUND_ERROR_STATE, /*!< ground error detected */ + IR155_GROUND_ERROR_STATE_UNKNOWN, /*!< ground error detected with undefined duty cycle */ IR155_IMD_ERROR_MEASUREMENT, /*!< device error detected */ IR155_IMD_ERROR_MEASUREMENT_UNKNOWN, /*!< device error detected with unkown duty cycle*/ IR155_SIGNAL_SHORT, /*!< signal short detected */ @@ -123,7 +123,7 @@ typedef struct { /** IR155 state struct */ typedef struct { - bool ir155Initialized; /*!< flag if IR155 module is initialied */ + bool ir155Initialized; /*!< flag if IR155 module is initialized */ IR155_MEASUREMENT_s measurement; /*!< latest measurement */ uint32_t timeUntilValidMeasurement_ms; /*!< time until valid measurement result is valid */ uint16_t periodTriggerTime_ms; /*!< periodic call time of IR155 module */ diff --git a/src/app/driver/imd/bender/ir155/config/bender_ir155_cfg.h b/src/app/driver/imd/bender/ir155/config/bender_ir155_cfg.h index 6faab4e8..48658c5c 100644 --- a/src/app/driver/imd/bender/ir155/config/bender_ir155_cfg.h +++ b/src/app/driver/imd/bender/ir155/config/bender_ir155_cfg.h @@ -43,8 +43,8 @@ * @file bender_ir155_cfg.h * @author foxBMS Team * @date 2021-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix IR155 * @@ -106,7 +106,7 @@ /** 30 Hz -> Speed start measurement. Insulation measurement (only good/bad * evaluation), starts directly after power on ? 2 s; PWM 5...10 % (good) and * 90...95 % (bad) */ -#define IR155_SPEEDSTART_FREQUENCY_Hz (30.0f) +#define IR155_SPEED_START_FREQUENCY_Hz (30.0f) /** 40 Hz -> Device error */ #define IR155_IMD_DEVICE_ERROR_FREQUENCY_Hz (40.0f) @@ -129,8 +129,8 @@ #define IR155_UNDERVOLTAGE_UPPER_FREQUENCY_Hz (IR155_UNDERVOLTAGE_FREQUENCY_Hz + IR155_MEASUREMENT_INTERVAL_RANGE_Hz) #define IR155_UNDERVOLTAGE_LOWER_FREQUENCY_Hz (IR155_UNDERVOLTAGE_FREQUENCY_Hz - IR155_MEASUREMENT_INTERVAL_RANGE_Hz) -#define IR155_SPEEDSTART_UPPER_FREQUENCY_Hz (IR155_SPEEDSTART_FREQUENCY_Hz + IR155_MEASUREMENT_INTERVAL_RANGE_Hz) -#define IR155_SPEEDSTART_LOWER_FREQUENCY_Hz (IR155_SPEEDSTART_FREQUENCY_Hz - IR155_MEASUREMENT_INTERVAL_RANGE_Hz) +#define IR155_SPEED_START_UPPER_FREQUENCY_Hz (IR155_SPEED_START_FREQUENCY_Hz + IR155_MEASUREMENT_INTERVAL_RANGE_Hz) +#define IR155_SPEED_START_LOWER_FREQUENCY_Hz (IR155_SPEED_START_FREQUENCY_Hz - IR155_MEASUREMENT_INTERVAL_RANGE_Hz) #define IR155_IMD_DEVICE_ERROR_UPPER_FREQUENCY_Hz \ (IR155_IMD_DEVICE_ERROR_FREQUENCY_Hz + IR155_MEASUREMENT_INTERVAL_RANGE_Hz) diff --git a/src/app/driver/imd/bender/iso165c/bender_iso165c.c b/src/app/driver/imd/bender/iso165c/bender_iso165c.c index 25dab659..574da918 100644 --- a/src/app/driver/imd/bender/iso165c/bender_iso165c.c +++ b/src/app/driver/imd/bender/iso165c/bender_iso165c.c @@ -43,8 +43,8 @@ * @file bender_iso165c.c * @author foxBMS Team * @date 2019-04-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix I165C * @@ -413,8 +413,8 @@ static void I165C_SetMeasurementMode(uint8_t mode); /** * @brief Check measurement mode - * @param[in] canMessage IMD_Info to be checked, sent by the iso165c - * @param[in] mode IMD measurement mode (activated or deactivated) + * @param[in] canMessage IMD_Info to be checked, sent by the iso165c + * @param[in] mode IMD measurement mode (activated or deactivated) * @return true, if measurement mode matches, otherwise false */ static bool I165C_CheckMeasurementMode(CAN_BUFFER_ELEMENT_s canMessage, uint8_t mode); @@ -1438,11 +1438,11 @@ static IMD_FSM_STATES_e I165C_Disable(void) { I165C_FSM_SHORT_TIME); } else { i165c_disableState.receptionTries++; - /* Issue: 621 */ + /* Issue: #621 */ } } else { i165c_disableState.receptionTriesMessage++; - /* Issue: 621 */ + /* Issue: #621 */ } break; diff --git a/src/app/driver/imd/bender/iso165c/bender_iso165c.h b/src/app/driver/imd/bender/iso165c/bender_iso165c.h index ea7efe21..3638b7f3 100644 --- a/src/app/driver/imd/bender/iso165c/bender_iso165c.h +++ b/src/app/driver/imd/bender/iso165c/bender_iso165c.h @@ -43,8 +43,8 @@ * @file bender_iso165c.h * @author foxBMS Team * @date 2019-04-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix I165C * diff --git a/src/app/driver/imd/bender/iso165c/config/bender_iso165c_cfg.c b/src/app/driver/imd/bender/iso165c/config/bender_iso165c_cfg.c deleted file mode 100644 index b6b25ded..00000000 --- a/src/app/driver/imd/bender/iso165c/config/bender_iso165c_cfg.c +++ /dev/null @@ -1,74 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file bender_iso165c_cfg.c - * @author foxBMS Team - * @date 2021-03-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup DRIVERS_CONFIGURATION - * @prefix I165C - * - * @brief Configuration for the insulation monitoring - * - */ - -/*========== Includes =======================================================*/ -#include "bender_iso165c_cfg.h" - -#include - -/*========== Macros and Definitions =========================================*/ - -/*========== Static Constant and Variable Definitions =======================*/ - -/*========== Extern Constant and Variable Definitions =======================*/ - -/*========== Static Function Prototypes =====================================*/ - -/*========== Static Function Implementations ================================*/ - -/*========== Extern Function Implementations ================================*/ - -/*========== Externalized Static Function Implementations (Unit Test) =======*/ -#ifdef UNITY_UNIT_TEST -#endif diff --git a/src/app/driver/imd/bender/iso165c/config/bender_iso165c_cfg.h b/src/app/driver/imd/bender/iso165c/config/bender_iso165c_cfg.h index 6afeb3ef..d71f5270 100644 --- a/src/app/driver/imd/bender/iso165c/config/bender_iso165c_cfg.h +++ b/src/app/driver/imd/bender/iso165c/config/bender_iso165c_cfg.h @@ -43,8 +43,8 @@ * @file bender_iso165c_cfg.h * @author foxBMS Team * @date 2021-03-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix I165C * diff --git a/src/app/driver/imd/bender/iso165c/wscript b/src/app/driver/imd/bender/iso165c/wscript index bb2a7ba8..7d208e6c 100644 --- a/src/app/driver/imd/bender/iso165c/wscript +++ b/src/app/driver/imd/bender/iso165c/wscript @@ -48,7 +48,6 @@ import os def build(bld): """Builds the Bender iso165C and iso165C-1 monitoring device""" source = [ - os.path.join("config", "bender_iso165c_cfg.c"), os.path.join("bender_iso165c.c"), ] includes = [ diff --git a/src/app/driver/imd/imd.c b/src/app/driver/imd/imd.c index 0a2c165d..c5e7d5f2 100644 --- a/src/app/driver/imd/imd.c +++ b/src/app/driver/imd/imd.c @@ -43,8 +43,8 @@ * @file imd.c * @author foxBMS Team * @date 2021-11-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix IMD * @@ -315,8 +315,8 @@ static void IMD_SetState( if ((pImdState->currentState == nextState) && (pImdState->currentSubstate == nextSubstate)) { /* Next state and next substate equal to current state and substate: nothing to do */ - pImdState->nextState = IMD_FSM_STATE_DUMMY; /* no state transistion required -> reset */ - pImdState->nextSubstate = IMD_FSM_SUBSTATE_DUMMY; /* no substate transistion required -> reset */ + pImdState->nextState = IMD_FSM_STATE_DUMMY; /* no state transition required -> reset */ + pImdState->nextSubstate = IMD_FSM_SUBSTATE_DUMMY; /* no substate transition required -> reset */ earlyExit = true; } @@ -327,8 +327,8 @@ static void IMD_SetState( pImdState->currentState = nextState; pImdState->previousSubstate = pImdState->currentSubstate; pImdState->currentSubstate = IMD_FSM_SUBSTATE_ENTRY; /* Use entry state after a top level state change */ - pImdState->nextState = IMD_FSM_STATE_DUMMY; /* no state transistion required -> reset */ - pImdState->nextSubstate = IMD_FSM_SUBSTATE_DUMMY; /* no substate transistion required -> reset */ + pImdState->nextState = IMD_FSM_STATE_DUMMY; /* no state transition required -> reset */ + pImdState->nextSubstate = IMD_FSM_SUBSTATE_DUMMY; /* no substate transition required -> reset */ } else if (pImdState->currentSubstate != nextSubstate) { /* Only the next substate is different, switch to it */ IMD_SetSubstate(pImdState, nextSubstate, idleTime); diff --git a/src/app/driver/imd/imd.h b/src/app/driver/imd/imd.h index c72d0e4f..a41ed223 100644 --- a/src/app/driver/imd/imd.h +++ b/src/app/driver/imd/imd.h @@ -43,8 +43,8 @@ * @file imd.h * @author foxBMS Team * @date 2020-11-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix IMD * @@ -73,15 +73,15 @@ /** Minimum required insulation resistance - Warning threshold */ #define IMD_WARNING_THRESHOLD_INSULATION_RESISTANCE_kOhm (750u) -/** Possible return values when state requests are made to the IMD statemachine */ +/** Possible return values when state requests are made to the IMD state machine */ typedef enum { IMD_REQUEST_OK, /*!< request was successful */ IMD_REQUEST_PENDING, /*!< requested to be executed */ IMD_ILLEGAL_REQUEST, /*!< Request can not be executed */ - IMD_ALREADY_INITIALIZED, /*!< IMD statemachine already initialized */ + IMD_ALREADY_INITIALIZED, /*!< IMD state machine already initialized */ } IMD_RETURN_TYPE_e; -/** State requests for the IMD statemachine */ +/** State requests for the IMD state machine */ typedef enum { IMD_STATE_INITIALIZE_REQUEST, /*!< request for initialization */ IMD_STATE_SWITCH_ON_REQUEST, /*!< request to switch on IMD device */ @@ -97,7 +97,7 @@ typedef enum { IMD_FSM_STATE_INITIALIZATION, /*!< initializing the state machine */ IMD_FSM_STATE_IMD_ENABLE, /*!< switch on IMD */ IMD_FSM_STATE_SHUTDOWN, /*!< shut down state of IMD state machine */ - IMD_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ + IMD_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ IMD_FSM_STATE_ERROR, /*!< state for error processing */ } IMD_FSM_STATES_e; @@ -105,7 +105,7 @@ typedef enum { /*========== Extern Function Prototypes =====================================*/ /** - * @brief Request initialization of IMD statemachine + * @brief Request initialization of IMD state machine * @return Always #IMD_REQUEST_OK */ extern IMD_RETURN_TYPE_e IMD_RequestInitialization(void); @@ -125,7 +125,7 @@ extern IMD_RETURN_TYPE_e IMD_RequestMeasurementStop(void); /** * @brief Gets the initialization state. * @details This function is used for getting the IMD initialization state. - * @return true if statemachine initialized, otherwise false + * @return true if state machine initialized, otherwise false */ extern bool IMD_GetInitializationState(void); @@ -144,7 +144,7 @@ extern STD_RETURN_TYPE_e IMD_Trigger(void); * @details This function needs to be implemented in the dedicated driver. This * function initializes the required SW modules and peripherals but * does not start the actual IMD measurement. - * @return #IMD_FSM_STATE_INITIALIZATION if initialization not fininished and + * @return #IMD_FSM_STATE_INITIALIZATION if initialization not finished and * another call is required. #IMD_FSM_STATE_IMD_ENABLE if * initialization is finished and #IMD_FSM_STATE_ERROR if an error is * detected that prohibits a working IMD driver. @@ -155,7 +155,7 @@ extern IMD_FSM_STATES_e IMD_ProcessInitializationState(void); * @brief Processes the IMD enable state * @details This function needs to be implemented in the dedicated driver. This * function enables the actual IMD device to start the insulation - * measurement. Functionality need to be fullfilled after one call. + * measurement. Functionality need to be fulfilled after one call. * @return #IMD_FSM_STATE_RUNNING if startup has been completed. Returns #IMD_FSM_STATE_ERROR if an error is * detected that prohibits a working IMD driver. */ @@ -177,7 +177,7 @@ extern IMD_FSM_STATES_e IMD_ProcessRunningState(DATA_BLOCK_INSULATION_MONITORING * @details This function needs to be implemented in the dedicated driver. This * function disables the actual IMD device to stop the insulation * measurement. - * @return #IMD_FSM_STATE_SHUTDOWN if shutdown state is not fininished and + * @return #IMD_FSM_STATE_SHUTDOWN if shutdown state is not finished and * another call is required. #IMD_FSM_STATE_IMD_ENABLE if shut down * has been completed and #IMD_FSM_STATE_ERROR if an error is detected * that prohibits a working IMD driver. diff --git a/src/app/driver/imd/none/no-imd.c b/src/app/driver/imd/none/no-imd.c index 59411f73..dc397233 100644 --- a/src/app/driver/imd/none/no-imd.c +++ b/src/app/driver/imd/none/no-imd.c @@ -43,8 +43,8 @@ * @file no-imd.c * @author foxBMS Team * @date 2020-11-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix NOIMD * diff --git a/src/app/driver/imd/none/no-imd.h b/src/app/driver/imd/none/no-imd.h index 7d92a021..285fb5ef 100644 --- a/src/app/driver/imd/none/no-imd.h +++ b/src/app/driver/imd/none/no-imd.h @@ -43,8 +43,8 @@ * @file no-imd.h * @author foxBMS Team * @date 2020-11-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix NONE * diff --git a/src/app/driver/interlock/interlock.c b/src/app/driver/interlock/interlock.c index 0d4752fb..2a42902d 100644 --- a/src/app/driver/interlock/interlock.c +++ b/src/app/driver/interlock/interlock.c @@ -43,8 +43,8 @@ * @file interlock.c * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix ILCK * diff --git a/src/app/driver/interlock/interlock.h b/src/app/driver/interlock/interlock.h index 1522b350..3c163a00 100644 --- a/src/app/driver/interlock/interlock.h +++ b/src/app/driver/interlock/interlock.h @@ -43,8 +43,8 @@ * @file interlock.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix ILCK * @@ -68,7 +68,7 @@ typedef enum { /* Init-Sequence */ ILCK_STATEMACHINE_UNINITIALIZED, /*!< Uninitialized state */ - ILCK_STATEMACHINE_INITIALIZED, /*!< statemachine initialized */ + ILCK_STATEMACHINE_INITIALIZED, /*!< state machine initialized */ ILCK_STATEMACHINE_UNDEFINED, /*!< undefined state */ } ILCK_STATEMACH_e; @@ -80,7 +80,7 @@ typedef enum { } ILCK_STATEMACH_SUB_e; /** - * State requests for the ILCK statemachine + * State requests for the ILCK state machine */ typedef enum { ILCK_STATE_INITIALIZATION_REQUEST, @@ -88,7 +88,7 @@ typedef enum { } ILCK_STATE_REQUEST_e; /** - * Possible return values when state requests are made to the ILCK statemachine + * Possible return values when state requests are made to the ILCK state machine */ typedef enum { ILCK_OK, /*!< ILCK --> ok */ @@ -103,19 +103,14 @@ typedef enum { */ typedef struct { uint16_t timer; /*!< time in ms before the state machine processes the next state, e.g. in counts of 1ms */ - ILCK_STATE_REQUEST_e - statereq; /*!< current state request made to the state machine */ - ILCK_STATEMACH_e - state; /*!< state of Driver State Machine */ - ILCK_STATEMACH_SUB_e - substate; /*!< current substate of the state machine */ - ILCK_STATEMACH_e - laststate; /*!< previous state of the state machine */ - ILCK_STATEMACH_SUB_e - lastsubstate; /*!< previous substate of the state machine */ - uint32_t ErrRequestCounter; /*!< counts the number of illegal requests to the LTC state machine */ - uint8_t triggerentry; /*!< counter for re-entrance protection (function running flag) */ - uint8_t counter; /*!< general purpose counter */ + ILCK_STATE_REQUEST_e statereq; /*!< current state request made to the state machine */ + ILCK_STATEMACH_e state; /*!< state of Driver State Machine */ + ILCK_STATEMACH_SUB_e substate; /*!< current substate of the state machine */ + ILCK_STATEMACH_e laststate; /*!< previous state of the state machine */ + ILCK_STATEMACH_SUB_e lastsubstate; /*!< previous substate of the state machine */ + uint32_t ErrRequestCounter; /*!< counts the number of illegal requests to the LTC state machine */ + uint8_t triggerentry; /*!< counter for re-entrance protection (function running flag) */ + uint8_t counter; /*!< general purpose counter */ } ILCK_STATE_s; /*========== Extern Constant and Variable Declarations ======================*/ diff --git a/src/app/driver/io/io.c b/src/app/driver/io/io.c index ed47ba08..f6f0f7b7 100644 --- a/src/app/driver/io/io.c +++ b/src/app/driver/io/io.c @@ -43,8 +43,8 @@ * @file io.c * @author foxBMS Team * @date 2020-06-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix IO * diff --git a/src/app/driver/io/io.h b/src/app/driver/io/io.h index dd9c154f..c661738e 100644 --- a/src/app/driver/io/io.h +++ b/src/app/driver/io/io.h @@ -43,8 +43,8 @@ * @file io.h * @author foxBMS Team * @date 2020-03-19 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix IO * diff --git a/src/app/driver/led/led.c b/src/app/driver/led/led.c index 7f6a215f..dbfa37a9 100644 --- a/src/app/driver/led/led.c +++ b/src/app/driver/led/led.c @@ -43,8 +43,8 @@ * @file led.c * @author foxBMS Team * @date 2021-09-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix LED * diff --git a/src/app/driver/led/led.h b/src/app/driver/led/led.h index 3fea148f..ab7d3ac2 100644 --- a/src/app/driver/led/led.h +++ b/src/app/driver/led/led.h @@ -43,8 +43,8 @@ * @file led.h * @author foxBMS Team * @date 2021-09-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix LED * diff --git a/src/app/driver/mcu/mcu.c b/src/app/driver/mcu/mcu.c index c1389a7e..05c4a841 100644 --- a/src/app/driver/mcu/mcu.c +++ b/src/app/driver/mcu/mcu.c @@ -43,8 +43,8 @@ * @file mcu.c * @author foxBMS Team * @date 2019-02-19 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MCU * diff --git a/src/app/driver/mcu/mcu.h b/src/app/driver/mcu/mcu.h index 6fa3b881..5541eb6a 100644 --- a/src/app/driver/mcu/mcu.h +++ b/src/app/driver/mcu/mcu.h @@ -43,8 +43,8 @@ * @file mcu.h * @author foxBMS Team * @date 2019-02-19 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MCU * diff --git a/src/app/driver/meas/meas.c b/src/app/driver/meas/meas.c index 771261d8..37080a4f 100644 --- a/src/app/driver/meas/meas.c +++ b/src/app/driver/meas/meas.c @@ -43,8 +43,8 @@ * @file meas.c * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MEAS * diff --git a/src/app/driver/meas/meas.h b/src/app/driver/meas/meas.h index 5b100ee7..bc2a9716 100644 --- a/src/app/driver/meas/meas.h +++ b/src/app/driver/meas/meas.h @@ -43,8 +43,8 @@ * @file meas.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix MEAS * diff --git a/src/app/driver/pex/pex.c b/src/app/driver/pex/pex.c index 0266a794..8687cefb 100644 --- a/src/app/driver/pex/pex.c +++ b/src/app/driver/pex/pex.c @@ -43,8 +43,8 @@ * @file pex.c * @author foxBMS Team * @date 2021-08-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix PEX * diff --git a/src/app/driver/pex/pex.h b/src/app/driver/pex/pex.h index 5050ed2f..7977785c 100644 --- a/src/app/driver/pex/pex.h +++ b/src/app/driver/pex/pex.h @@ -43,8 +43,8 @@ * @file pex.h * @author foxBMS Team * @date 2021-08-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix PEX * diff --git a/src/app/driver/pwm/pwm.c b/src/app/driver/pwm/pwm.c index 5c47e6ff..1e70bacc 100644 --- a/src/app/driver/pwm/pwm.c +++ b/src/app/driver/pwm/pwm.c @@ -43,8 +43,8 @@ * @file pwm.c * @author foxBMS Team * @date 2021-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix PWM * diff --git a/src/app/driver/pwm/pwm.h b/src/app/driver/pwm/pwm.h index 41ceceb8..c21da2fc 100644 --- a/src/app/driver/pwm/pwm.h +++ b/src/app/driver/pwm/pwm.h @@ -43,8 +43,8 @@ * @file pwm.h * @author foxBMS Team * @date 2021-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix PWM * diff --git a/src/app/driver/rtc/rtc.c b/src/app/driver/rtc/rtc.c index 8afbfc80..61001394 100644 --- a/src/app/driver/rtc/rtc.c +++ b/src/app/driver/rtc/rtc.c @@ -43,8 +43,8 @@ * @file rtc.c * @author foxBMS Team * @date 2021-02-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix RTC * @@ -119,7 +119,7 @@ static RTC_TIME_DATA_s RTC_tmFormatToRtcFormat(struct tm timeTmFormat); * @param rtcTime RTC time to write to the IC */ static void RTC_WriteTime(RTC_TIME_DATA_s rtcTime) { - /* AXIVION Routine Generic-MissingParameterAssert: time: parameter accepts whole range */ + /* AXIVION Routine Generic-MissingParameterAssert: rtcTime: parameter accepts whole range */ STD_RETURN_TYPE_e retValI2c = STD_OK; STD_RETURN_TYPE_e retVal = STD_OK; diff --git a/src/app/driver/rtc/rtc.h b/src/app/driver/rtc/rtc.h index bf876f49..fdd9be13 100644 --- a/src/app/driver/rtc/rtc.h +++ b/src/app/driver/rtc/rtc.h @@ -43,8 +43,8 @@ * @file rtc.h * @author foxBMS Team * @date 2021-02-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix RTC * @@ -105,7 +105,7 @@ typedef struct { /* Power management configuration value to switch to battery voltage and monitor battery voltage */ -#define RTC_CTRL3_PWRMNG_DIRECTSWITCH_LOWDETECTIONENABLE_MODE (0b011u) +#define RTC_CTRL3_PWRMNG_DIRECTSWITCH_LOWDETECTIONENABLE_MODE (0x03u) /* Defines for the RTC CLKOUT_ctl register */ /**@{*/ diff --git a/src/app/driver/sbc/nxpfs85xx.c b/src/app/driver/sbc/nxpfs85xx.c index 7e5dd326..dcc4ec64 100644 --- a/src/app/driver/sbc/nxpfs85xx.c +++ b/src/app/driver/sbc/nxpfs85xx.c @@ -43,12 +43,12 @@ * @file nxpfs85xx.c * @author foxBMS Team * @date 2020-03-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS - * @prefix SBC + * @prefix FS85 * - * @brief Driver for the SBC module + * @brief Driver for the FS85xx module * * @details It must always be used when creating new c source files. * @@ -65,20 +65,23 @@ #include "fstd_types.h" #include "fsystem.h" #include "io.h" -#include "masterinfo.h" +#include "master_info.h" #include "mcu.h" +#include "sbc_fs8x_communication.h" +#include "spi.h" #include /*========== Macros and Definitions =========================================*/ /*========== Static Constant and Variable Definitions =======================*/ +/** Initialization phases during startup of FS85xx IC*/ typedef enum { - SBC_UNINITIALIZED, - SBC_FIN_TEST, - SBC_RSTB_ASSERTION_TEST, - SBC_INITIALIZED, -} SBC_INIT_PHASE_e; + FS85_UNINITIALIZED, + FS85_FIN_TEST, + FS85_RSTB_ASSERTION_TEST, + FS85_INITIALIZED, +} FS85_INIT_PHASE_e; /*========== Extern Constant and Variable Definitions =======================*/ FS85_STATE_s fs85xx_mcuSupervisor = { @@ -93,8 +96,8 @@ FS85_STATE_s fs85xx_mcuSupervisor = { .mainRegister = {0}, .fsRegister = {0}, .nvram.entry = FRAM_BLOCK_ID_SBC_INIT_STATE, - .nvram.data = &fram_sbcInit, - .mode = SBC_NORMAL_MODE, /* default value */ + .nvram.pData = &fram_sbcInit, + .mode = FS85_NORMAL_MODE, /* default value */ }; /*========== Static Function Prototypes =====================================*/ @@ -103,21 +106,21 @@ FS85_STATE_s fs85xx_mcuSupervisor = { * @details If actual register value equals expected value #STD_OK is * returned if this is not the case this indicates an error and * #STD_NOT_OK is returned. - * @param[in] registerValue actual register value of interest - * @param[in] expectedRegisterValue expected register value + * @param registerValue actual register value of interest + * @param expectedRegisterValue expected register value * @return #STD_OK if register value equals expected, else #STD_NOT_OK */ -static STD_RETURN_TYPE_e SBC_CheckRegisterValues(uint32_t registerValue, uint32_t expectedRegisterValue); +static STD_RETURN_TYPE_e FS85_CheckRegisterValues(uint32_t registerValue, uint32_t expectedRegisterValue); /** * @brief Updates fail safe register values * @details Updates fail safe register value of passed SBC instance * with new values * @param[in,out] pFsRegister pointer to fail-safe registers - * @param[in] registerAddress address of register that is updated - * @param[in] registerValue register value + * @param registerAddress address of register that is updated + * @param registerValue register value */ -static void SBC_UpdateFailSafeRegister( +static void FS85_UpdateFailSafeRegister( FS85_FS_REGISTER_s *pFsRegister, uint32_t registerAddress, uint32_t registerValue); @@ -127,10 +130,10 @@ static void SBC_UpdateFailSafeRegister( * @details Updates main register value of passed SBC instance with new * values * @param[in,out] pMainRegister pointer to main registers - * @param[in] registerAddress address of register that is updated - * @param[in] registerValue register value + * @param registerAddress address of register that is updated + * @param registerValue register value */ -static void SBC_UpdateMainRegister( +static void FS85_UpdateMainRegister( FS85_MAIN_REGISTERS_s *pMainRegister, uint32_t registerAddress, uint32_t registerValue); @@ -140,11 +143,11 @@ static void SBC_UpdateMainRegister( * @details Updates register value of passed SBC instance with new * values * @param[in,out] pInstance SBC instance that is updated - * @param[in] isFailSafe true if fail-safe register, false if main register - * @param[in] registerAddress address of register that is updated - * @param[in] registerValue register value + * @param isFailSafe true if fail-safe register, false if main register + * @param registerAddress address of register that is updated + * @param registerValue register value */ -static void SBC_UpdateRegister( +static void FS85_UpdateRegister( FS85_STATE_s *pInstance, bool isFailSafe, uint32_t registerAddress, @@ -155,23 +158,23 @@ static void SBC_UpdateRegister( * @details Reads SBC register value from registerAddress and updates * register in SBC state variable if reading was successful * @param[in,out] pInstance SBC instance that is updated - * @param[in] isFailSafe true if fail-safe register, false if main + * @param isFailSafe true if fail-safe register, false if main * register - * @param[in] registerAddress address of register that is read from + * @param registerAddress address of register that is read from * @return #STD_OK if reading was successful, otherwise #STD_NOT_OK */ -static STD_RETURN_TYPE_e SBC_ReadBackRegister(FS85_STATE_s *pInstance, bool isFailSafe, uint8_t registerAddress); +static STD_RETURN_TYPE_e FS85_ReadBackRegister(FS85_STATE_s *pInstance, bool isFailSafe, uint8_t registerAddress); /** * @brief Write to fail-safe register * @details Writes to fail-safe register (can be done during FS_INIT phase * only) * @param[in] pInstance SBC instance that is updated - * @param[in] registerAddress address of register - * @param[in] registerValue value that is written into register + * @param registerAddress address of register + * @param registerValue value that is written into register * @return #STD_OK if writing was successful, other #STD_NOT_OK */ -static STD_RETURN_TYPE_e SBC_WriteRegisterFsInit( +static STD_RETURN_TYPE_e FS85_WriteRegisterFsInit( FS85_STATE_s *pInstance, uint8_t registerAddress, uint16_t registerValue); @@ -182,11 +185,11 @@ static STD_RETURN_TYPE_e SBC_WriteRegisterFsInit( * phase only), reads back if write process was successful and * afterwards updates register value of passed SBC instance * @param[in,out] pInstance SBC instance that is updated - * @param[in] registerAddress address of register - * @param[in] registerValue value that is written into register + * @param registerAddress address of register + * @param registerValue value that is written into register * @return #STD_OK if writing was successful, other #STD_NOT_OK */ -static STD_RETURN_TYPE_e SBC_WriteBackRegisterFsInit( +static STD_RETURN_TYPE_e FS85_WriteBackRegisterFsInit( FS85_STATE_s *pInstance, uint8_t registerAddress, uint16_t registerValue); @@ -197,18 +200,25 @@ static STD_RETURN_TYPE_e SBC_WriteBackRegisterFsInit( * successful and afterwards updates register value of passed * SBC instance * @param[in,out] pInstance SBC instance that is updated - * @param[in] registerAddress address of register - * @param[in] isFailSafe true if fail-safe register, false if main register - * @param[in] registerValue value that is written into register + * @param registerAddress address of register + * @param isFailSafe true if fail-safe register, false if main register + * @param registerValue value that is written into register * @return #STD_OK if writing was successful, other #STD_NOT_OK */ -static STD_RETURN_TYPE_e SBC_ClearRegisterFlags( +static STD_RETURN_TYPE_e FS85_ClearRegisterFlags( FS85_STATE_s *pInstance, uint8_t registerAddress, bool isFailSafe, uint16_t registerValue); -static STD_RETURN_TYPE_e SBC_ReadBackAllRegisters(FS85_STATE_s *pInstance); +/** + * @brief Clears flags in register + * @details Reads all registers updates the register values of passed + * SBC instance + * @param[in,out] pInstance SBC instance that is updated + * @return #STD_OK if readout was successful, otherwise #STD_NOT_OK + */ +static STD_RETURN_TYPE_e FS85_ReadBackAllRegisters(FS85_STATE_s *pInstance); /** * @brief Perform RSTB safety path check @@ -219,7 +229,7 @@ static STD_RETURN_TYPE_e SBC_ReadBackAllRegisters(FS85_STATE_s *pInstance); * @param[in,out] pInstance SBC instance for which the RSTB path is checked * @return #STD_OK if path check was successful, other #STD_NOT_OK */ -static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance); +static STD_RETURN_TYPE_e FS85_PerformPathCheckRstb(FS85_STATE_s *pInstance); /** * @brief Perform FS0B safety path check @@ -229,10 +239,17 @@ static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance); * operation. * @param[in,out] pInstance SBC instance for which the FS0B path is checked */ -static STD_RETURN_TYPE_e SBC_PerformPathCheckFs0b(FS85_STATE_s *pInstance); +static STD_RETURN_TYPE_e FS85_PerformPathCheckFs0b(FS85_STATE_s *pInstance); + +/** + * @brief Sends SBC to Standby Mode + * @details Sets GOTOSTBY Bit on SBC via SPI. + * @param pInstance SBC Instance to send to Standby +*/ +static STD_RETURN_TYPE_e FS85_GoToStandby(FS85_STATE_s *pInstance); /*========== Static Function Implementations ================================*/ -static STD_RETURN_TYPE_e SBC_CheckRegisterValues(uint32_t registerValue, uint32_t expectedRegisterValue) { +static STD_RETURN_TYPE_e FS85_CheckRegisterValues(uint32_t registerValue, uint32_t expectedRegisterValue) { /* AXIVION Routine Generic-MissingParameterAssert: registerValue: parameter accepts whole range */ /* AXIVION Routine Generic-MissingParameterAssert: expectedRegisterValue: parameter accepts whole range */ STD_RETURN_TYPE_e retval = STD_OK; @@ -242,7 +259,7 @@ static STD_RETURN_TYPE_e SBC_CheckRegisterValues(uint32_t registerValue, uint32_ return retval; } -static void SBC_UpdateFailSafeRegister( +static void FS85_UpdateFailSafeRegister( FS85_FS_REGISTER_s *pFsRegister, uint32_t registerAddress, uint32_t registerValue) { @@ -304,7 +321,7 @@ static void SBC_UpdateFailSafeRegister( } } -static void SBC_UpdateMainRegister( +static void FS85_UpdateMainRegister( FS85_MAIN_REGISTERS_s *pMainRegister, uint32_t registerAddress, uint32_t registerValue) { @@ -363,7 +380,7 @@ static void SBC_UpdateMainRegister( } } -static void SBC_UpdateRegister( +static void FS85_UpdateRegister( FS85_STATE_s *pInstance, bool isFailSafe, uint32_t registerAddress, @@ -375,13 +392,13 @@ static void SBC_UpdateRegister( /* Check if fail-safe or main register needs to be updated */ if (isFailSafe == true) { /* Update fail-safe register */ - SBC_UpdateFailSafeRegister(&(pInstance->fsRegister), registerAddress, registerValue); + FS85_UpdateFailSafeRegister(&(pInstance->fsRegister), registerAddress, registerValue); } else { /* Update main register */ - SBC_UpdateMainRegister(&(pInstance->mainRegister), registerAddress, registerValue); + FS85_UpdateMainRegister(&(pInstance->mainRegister), registerAddress, registerValue); } } -static STD_RETURN_TYPE_e SBC_ReadBackRegister(FS85_STATE_s *pInstance, bool isFailSafe, uint8_t registerAddress) { +static STD_RETURN_TYPE_e FS85_ReadBackRegister(FS85_STATE_s *pInstance, bool isFailSafe, uint8_t registerAddress) { FAS_ASSERT(pInstance != NULL_PTR); FAS_ASSERT((isFailSafe == true) || (isFailSafe == false)); /* AXIVION Routine Generic-MissingParameterAssert: registerAddress: parameter accepts whole range */ @@ -395,13 +412,13 @@ static STD_RETURN_TYPE_e SBC_ReadBackRegister(FS85_STATE_s *pInstance, bool isFa FS8x_ReadRegister(pInstance->pSpiInterface, &(pInstance->configValues), isFailSafe, registerAddress, &rxTemp)) { retval = STD_NOT_OK; } else { - SBC_UpdateRegister(pInstance, isFailSafe, registerAddress, rxTemp.readData); + FS85_UpdateRegister(pInstance, isFailSafe, registerAddress, rxTemp.readData); retval = STD_OK; } return retval; } -static STD_RETURN_TYPE_e SBC_WriteRegisterFsInit( +static STD_RETURN_TYPE_e FS85_WriteRegisterFsInit( FS85_STATE_s *pInstance, uint8_t registerAddress, uint16_t registerValue) { @@ -423,7 +440,7 @@ static STD_RETURN_TYPE_e SBC_WriteRegisterFsInit( return retval; } -static STD_RETURN_TYPE_e SBC_WriteBackRegisterFsInit( +static STD_RETURN_TYPE_e FS85_WriteBackRegisterFsInit( FS85_STATE_s *pInstance, uint8_t registerAddress, uint16_t registerValue) { @@ -448,7 +465,7 @@ static STD_RETURN_TYPE_e SBC_WriteBackRegisterFsInit( } else { if (rxTemp.readData == registerValue) { /* Written register value equals read value */ - SBC_UpdateRegister(pInstance, true, registerAddress, rxTemp.readData); + FS85_UpdateRegister(pInstance, true, registerAddress, rxTemp.readData); } else { retval |= STD_NOT_OK; } @@ -457,7 +474,7 @@ static STD_RETURN_TYPE_e SBC_WriteBackRegisterFsInit( return retval; } -static STD_RETURN_TYPE_e SBC_ClearRegisterFlags( +static STD_RETURN_TYPE_e FS85_ClearRegisterFlags( FS85_STATE_s *pInstance, uint8_t registerAddress, bool isFailSafe, @@ -487,7 +504,7 @@ static STD_RETURN_TYPE_e SBC_ClearRegisterFlags( /* Check if all flags have been cleared: '1' is written to registers to clear respective flags */ if ((rxTemp.readData & registerValue) == 0u) { /* Written register value equals read value */ - SBC_UpdateRegister(pInstance, isFailSafe, registerAddress, rxTemp.readData); + FS85_UpdateRegister(pInstance, isFailSafe, registerAddress, rxTemp.readData); } else { retval |= STD_NOT_OK; } @@ -496,6 +513,20 @@ static STD_RETURN_TYPE_e SBC_ClearRegisterFlags( return retval; } +static STD_RETURN_TYPE_e FS85_GoToStandby(FS85_STATE_s *pInstance) { + FAS_ASSERT(pInstance != NULL_PTR); + + STD_RETURN_TYPE_e retVal = STD_NOT_OK; + + if (fs8xStatusOk == + FS8x_WriteRegister( + pInstance->pSpiInterface, &(pInstance->configValues), false, FS8X_M_MODE_ADDR, FS8X_M_GOTOSTBY_MASK)) { + retVal = STD_OK; + } + + return retVal; +} + /*========== Extern Function Implementations ================================*/ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { FAS_ASSERT(pInstance != NULL_PTR); @@ -560,37 +591,37 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { /* --------------------- First: Verify --------------------------------- */ /** 1.: Verify LBIST and ABIST1 */ - if (STD_OK != SBC_ReadBackRegister(pInstance, true, FS8X_FS_DIAG_SAFETY_ADDR)) { + if (STD_OK != FS85_ReadBackRegister(pInstance, true, FS8X_FS_DIAG_SAFETY_ADDR)) { retval = STD_NOT_OK; } registerMask = (FS8X_FS_LBIST_OK_MASK | FS8X_FS_ABIST1_OK_MASK); expRegisterValue = (FS8X_FS_LBIST_OK_PASS | FS8X_FS_ABIST1_OK_PASS); - if (STD_OK != SBC_CheckRegisterValues((pInstance->fsRegister.diag_safety & registerMask), expRegisterValue)) { + if (STD_OK != FS85_CheckRegisterValues((pInstance->fsRegister.diag_safety & registerMask), expRegisterValue)) { retval = STD_NOT_OK; } /** Read FS STATES register */ - if (STD_OK != SBC_ReadBackRegister(pInstance, true, FS8X_FS_STATES_ADDR)) { + if (STD_OK != FS85_ReadBackRegister(pInstance, true, FS8X_FS_STATES_ADDR)) { retval = STD_NOT_OK; } /** 2.: Check if debug mode is active */ registerMask = FS8X_FS_DBG_MODE_MASK; expRegisterValue = FS8X_FS_DBG_MODE_NO_DEBUG; - if (STD_OK != SBC_CheckRegisterValues((pInstance->fsRegister.states & registerMask), expRegisterValue)) { + if (STD_OK != FS85_CheckRegisterValues((pInstance->fsRegister.states & registerMask), expRegisterValue)) { /* Debug mode active: this can only be the case if debugger connected */ MINFO_SetDebugProbeConnectionState(MINFO_DEBUG_PROBE_CONNECTED); - pInstance->mode = SBC_DEBUG_MODE; + pInstance->mode = FS85_DEBUG_MODE; } else { /* Debug mode not active: no debugger connected */ MINFO_SetDebugProbeConnectionState(MINFO_DEBUG_PROBE_NOT_CONNECTED); - pInstance->mode = SBC_NORMAL_MODE; + pInstance->mode = FS85_NORMAL_MODE; } /** 3.: Verify that no OPT CRC error */ registerMask = FS8X_FS_OTP_CORRUPT_MASK; expRegisterValue = FS8X_FS_OTP_CORRUPT_NO_ERROR; - if (STD_OK != SBC_CheckRegisterValues((pInstance->fsRegister.states & registerMask), expRegisterValue)) { + if (STD_OK != FS85_CheckRegisterValues((pInstance->fsRegister.states & registerMask), expRegisterValue)) { retval = STD_NOT_OK; } @@ -599,20 +630,20 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { * Specific configurations can only be done in FS_INIT state */ registerMask = FS8X_FS_FSM_STATE_MASK; expRegisterValue = FS8X_FS_FSM_STATE_INIT_FS; - if (STD_OK != SBC_CheckRegisterValues((pInstance->fsRegister.states & registerMask), expRegisterValue)) { + if (STD_OK != FS85_CheckRegisterValues((pInstance->fsRegister.states & registerMask), expRegisterValue)) { /* SBC not in FS_INIT state -> request FS_INIT state */ /* Write FS_STATE request */ registerValue = FS8X_FS_GO_TO_INITFS_GO_BACK_TO_INIT_FS; - if (STD_OK != SBC_WriteRegisterFsInit(pInstance, FS8X_FS_SAFE_IOS_ADDR, registerValue)) { + if (STD_OK != FS85_WriteRegisterFsInit(pInstance, FS8X_FS_SAFE_IOS_ADDR, registerValue)) { retval = STD_NOT_OK; } else { /* Check if SBC now in FS_STATE */ - if (STD_OK != SBC_ReadBackRegister(pInstance, true, FS8X_FS_STATES_ADDR)) { + if (STD_OK != FS85_ReadBackRegister(pInstance, true, FS8X_FS_STATES_ADDR)) { retval = STD_NOT_OK; } else { /* Read register now check if SBC in FS_INIT state */ if (STD_OK != - SBC_CheckRegisterValues((pInstance->fsRegister.states & registerMask), expRegisterValue)) { + FS85_CheckRegisterValues((pInstance->fsRegister.states & registerMask), expRegisterValue)) { /* SBC not in FS_INIT state -> error */ retval = STD_NOT_OK; } @@ -667,7 +698,7 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { registerValue |= FS8X_FS_I_VMON4_ABIST2_VMON4_BIST; /* Write register */ - if (STD_OK != SBC_WriteBackRegisterFsInit(pInstance, FS8X_FS_I_OVUV_SAFE_REACTION1_ADDR, registerValue)) { + if (STD_OK != FS85_WriteBackRegisterFsInit(pInstance, FS8X_FS_I_OVUV_SAFE_REACTION1_ADDR, registerValue)) { retval = STD_NOT_OK; } @@ -692,7 +723,7 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { registerValue |= FS8X_FS_I_VMON4_UV_FS_IMPACT_NO_EFFECT; /* Write register */ - if (STD_OK != SBC_WriteBackRegisterFsInit(pInstance, FS8X_FS_I_OVUV_SAFE_REACTION2_ADDR, registerValue)) { + if (STD_OK != FS85_WriteBackRegisterFsInit(pInstance, FS8X_FS_I_OVUV_SAFE_REACTION2_ADDR, registerValue)) { retval = STD_NOT_OK; } @@ -719,7 +750,7 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { registerValue |= FS8X_FS_WDW_RECOVERY_128MS; /* Write register */ - if (STD_OK != SBC_WriteBackRegisterFsInit(pInstance, FS8X_FS_WD_WINDOW_ADDR, registerValue)) { + if (STD_OK != FS85_WriteBackRegisterFsInit(pInstance, FS8X_FS_WD_WINDOW_ADDR, registerValue)) { retval = STD_NOT_OK; } @@ -757,7 +788,7 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { registerValue |= FS8X_FS_I_FLT_ERR_CNT_1; /* Write register */ - if (STD_OK != SBC_WriteRegisterFsInit(pInstance, FS8X_FS_I_FSSM_ADDR, registerValue)) { + if (STD_OK != FS85_WriteRegisterFsInit(pInstance, FS8X_FS_I_FSSM_ADDR, registerValue)) { retval = STD_NOT_OK; } @@ -805,26 +836,26 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { registerValue |= FS8X_FS_I_ERRMON_FS_IMPACT_FS0B; /* Write register */ - if (STD_OK != SBC_WriteRegisterFsInit(pInstance, FS8X_FS_I_SAFE_INPUTS_ADDR, registerValue)) { + if (STD_OK != FS85_WriteRegisterFsInit(pInstance, FS8X_FS_I_SAFE_INPUTS_ADDR, registerValue)) { retval = STD_NOT_OK; } /* -------------------- Third: Execute --------------------------------- */ /** 1.: Close INIT_FS by sending the first good WD refresh */ - if (STD_OK != SBC_TriggerWatchdog(pInstance)) { + if (STD_OK != FS85_TriggerWatchdog(pInstance)) { retval = STD_NOT_OK; } /** 2.: Execute ABIST2 and verify it is pass */ /** ABIST2 is executed automatically after closing of INIT_FS, duration: 1.2ms max */ MCU_Delay_us(1200u); - if (STD_OK != SBC_ReadBackRegister(pInstance, true, FS8X_FS_DIAG_SAFETY_ADDR)) { + if (STD_OK != FS85_ReadBackRegister(pInstance, true, FS8X_FS_DIAG_SAFETY_ADDR)) { retval = STD_NOT_OK; } registerMask = FS8X_FS_ABIST2_OK_MASK; expRegisterValue = FS8X_FS_ABIST2_OK_MASK; - if (STD_OK != SBC_CheckRegisterValues((pInstance->fsRegister.diag_safety & registerMask), expRegisterValue)) { + if (STD_OK != FS85_CheckRegisterValues((pInstance->fsRegister.diag_safety & registerMask), expRegisterValue)) { retval = STD_NOT_OK; } @@ -838,7 +869,7 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { (FS8X_FS_SPI_FS_CLK_WRONG_NUMBER_OF_CLOCK_CYCLES | FS8X_FS_SPI_FS_REQ_SPI_VIOLATION | FS8X_FS_SPI_FS_CRC_ERROR_DETECTED); registerValue |= (FS8X_FS_I2C_FS_CRC_ERROR_DETECTED | FS8X_FS_I2C_FS_REQ_I2C_VIOLATION); - if (STD_OK != SBC_ClearRegisterFlags(pInstance, FS8X_FS_DIAG_SAFETY_ADDR, true, registerValue)) { + if (STD_OK != FS85_ClearRegisterFlags(pInstance, FS8X_FS_DIAG_SAFETY_ADDR, true, registerValue)) { retval = STD_NOT_OK; } @@ -854,14 +885,14 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { FS8X_FS_VMON1_OV_OVERVOLTAGE_REPORTED | FS8X_FS_VMON1_UV_UNDERVOLTAGE_REPORTED); registerValue |= FS8X_FS_FS_DIG_REF_OV_OVERVOLTAGE_REPORTED; registerValue |= FS8X_FS_FS_OSC_DRIFT_OSCILLATOR_DRIFT; - if (STD_OK != SBC_ClearRegisterFlags(pInstance, FS8X_FS_OVUVREG_STATUS_ADDR, true, registerValue)) { + if (STD_OK != FS85_ClearRegisterFlags(pInstance, FS8X_FS_OVUVREG_STATUS_ADDR, true, registerValue)) { retval = STD_NOT_OK; } /** Clear flags FLAG1 register */ registerValue = FS8X_M_VBOSUVH_EVENT_OCCURRED; registerValue |= FS8X_M_VBOOSTUVH_EVENT_OCCURRED; - if (STD_OK != SBC_ClearRegisterFlags(pInstance, FS8X_M_FLAG1_ADDR, false, registerValue)) { + if (STD_OK != FS85_ClearRegisterFlags(pInstance, FS8X_M_FLAG1_ADDR, false, registerValue)) { retval = STD_NOT_OK; } @@ -870,23 +901,53 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance) { registerValue |= (FS8X_M_VPREUVL_EVENT_OCCURRED | FS8X_M_VPREUVH_EVENT_OCCURRED | FS8X_M_VSUPUVL_EVENT_OCCURRED | FS8X_M_VSUPUVH_EVENT_OCCURRED | FS8X_M_WK2FLG_EVENT_OCCURRED); - if (STD_OK != SBC_ClearRegisterFlags(pInstance, FS8X_M_FLAG2_ADDR, false, registerValue)) { + if (STD_OK != FS85_ClearRegisterFlags(pInstance, FS8X_M_FLAG2_ADDR, false, registerValue)) { retval = STD_NOT_OK; } /** Read out all registers for debug purpose */ - if (STD_OK != SBC_ReadBackAllRegisters(pInstance)) { + if (STD_OK != FS85_ReadBackAllRegisters(pInstance)) { retval = STD_OK; } return retval; } +extern bool FS85_CheckIgnitionSignal(FS85_STATE_s *pInstance) { + FAS_ASSERT(pInstance != NULL_PTR); + + /* Default state */ + bool ignitionSignalDetected = true; + /* variables for storing current and previous wake1 signal levels */ + static uint16_t wake1Level = 0u; + static uint16_t oldWake1Level = 0u; + + /* Read wake1 signal level */ + fs8x_rx_frame_t rxTemp = {.deviceStatus = 0u, .readData = 0u}; + if (fs8xStatusOk == + FS8x_ReadRegister(pInstance->pSpiInterface, &(pInstance->configValues), false, FS8X_M_FLAG2_ADDR, &rxTemp)) { + wake1Level = rxTemp.readData & FS8X_M_WK1RT_WAKE1_HIGH; + } + + /* Check for falling edge in wake1 signal */ + if ((oldWake1Level != wake1Level) && (wake1Level == 0u)) { + if (STD_OK != FS85_GoToStandby(pInstance)) { + /* error in switch to standby mode, reset ole level to try again */ + wake1Level = oldWake1Level; + } else { + ignitionSignalDetected = false; + } + } + /* update old level for edge detection */ + oldWake1Level = wake1Level; + return ignitionSignalDetected; +} + extern STD_RETURN_TYPE_e FS85_InitializeNumberOfRequiredWatchdogRefreshes( FS85_STATE_s *pInstance, - uint8_t *requiredWatchdogRefreshes) { + uint8_t *pRequiredWatchdogRefreshes) { FAS_ASSERT(pInstance != NULL_PTR); - FAS_ASSERT(requiredWatchdogRefreshes != NULL_PTR); + FAS_ASSERT(pRequiredWatchdogRefreshes != NULL_PTR); STD_RETURN_TYPE_e retval = STD_OK; @@ -898,13 +959,13 @@ extern STD_RETURN_TYPE_e FS85_InitializeNumberOfRequiredWatchdogRefreshes( * the watchdog refresh counter is reset to '0'. */ /** Read out FS_I_WD_CFG register to get watchdog refresh counter limit and value */ - if (STD_OK != SBC_ReadBackRegister(pInstance, true, FS8X_FS_I_WD_CFG_ADDR)) { + if (STD_OK != FS85_ReadBackRegister(pInstance, true, FS8X_FS_I_WD_CFG_ADDR)) { retval = STD_NOT_OK; } /** Get refresh counter value */ - uint8_t watchdogRefreshLimit = 0; - uint8_t watchdogRefreshCounter = FS8x_BO_GET_REG_VALUE( + uint8_t watchdogRefreshLimit = 0u; + uint16_t watchdogRefreshCounter = FS8x_BO_GET_REG_VALUE( pInstance->fsRegister.iWatchdogConfiguration, FS8X_FS_I_WD_RFR_CNT_MASK, FS8X_FS_I_WD_RFR_CNT_SHIFT); /** Get refresh counter limit register value */ @@ -934,7 +995,7 @@ extern STD_RETURN_TYPE_e FS85_InitializeNumberOfRequiredWatchdogRefreshes( } /** Get number of required watchdog refreshes to clear fault error counter to 0 */ - *requiredWatchdogRefreshes = faultCounter + (watchdogRefreshLimit - watchdogRefreshCounter); + *pRequiredWatchdogRefreshes = faultCounter + (watchdogRefreshLimit - watchdogRefreshCounter); return retval; } @@ -960,12 +1021,12 @@ extern STD_RETURN_TYPE_e FS85_SafetyPathChecks(FS85_STATE_s *pInstance) { STD_RETURN_TYPE_e retval = STD_OK; /* Perform RSTB path check (repeat steps 1 to 4 after RSTB is released) */ - if (STD_OK != SBC_PerformPathCheckRstb(pInstance)) { + if (STD_OK != FS85_PerformPathCheckRstb(pInstance)) { retval = STD_NOT_OK; } /* FS0B pin can not be released in debug mode */ - if (pInstance->mode != SBC_DEBUG_MODE) { + if (pInstance->mode != FS85_DEBUG_MODE) { /* Release FS0B pin */ if (fs8xStatusOk != FS8x_FS0B_Release(pInstance->pSpiInterface, &(pInstance->configValues))) { retval = STD_NOT_OK; @@ -973,19 +1034,21 @@ extern STD_RETURN_TYPE_e FS85_SafetyPathChecks(FS85_STATE_s *pInstance) { } /* Perform FS0B safety path check */ - if (STD_OK != SBC_PerformPathCheckFs0b(pInstance)) { + if (STD_OK != FS85_PerformPathCheckFs0b(pInstance)) { retval = STD_NOT_OK; } /* Init finished successfully if retval still okay */ if (retval == STD_OK) { - pInstance->nvram.data->phase = (uint8_t)SBC_INITIALIZED; - FRAM_WriteData(pInstance->nvram.entry); + pInstance->nvram.pData->phase = (uint8_t)FS85_INITIALIZED; + (void)FRAM_WriteData(pInstance->nvram.entry); } return retval; } /* AXIVION Next Codeline Style CodingStyle-Naming.Function: The name is pre-defined by the driver provided by NXP. */ +/* AXIVION Next Construct Style CodingStyle-Naming.Parameter: The name is pre-defined by the driver provided by NXP. */ +/* AXIVION Next Construct Style MisraC2012-2.7: The API is pre-defined by the driver provided by NXP. */ extern UNIT_TEST_WEAK_IMPL fs8x_status_t MCU_SPI_TransferData( SPI_INTERFACE_CONFIG_s *pSpiInterface, uint8_t *txFrame, @@ -996,23 +1059,23 @@ extern UNIT_TEST_WEAK_IMPL fs8x_status_t MCU_SPI_TransferData( FAS_ASSERT(rxFrame != NULL_PTR); /* AXIVION Routine Generic-MissingParameterAssert: frameLengthBytes: parameter accepts whole range */ - uint16_t sbc_txBuffer[FS8x_COMM_FRAME_SIZE]; - uint16_t sbc_rxBuffer[FS8x_COMM_FRAME_SIZE]; - fs8x_status_t spiCommunicationState = fs8xStatusError; + uint16_t fs85_txBuffer[FS8x_COMM_FRAME_SIZE] = {0u, 0u, 0u, 0u}; + uint16_t fs85_rxBuffer[FS8x_COMM_FRAME_SIZE] = {0u, 0u, 0u, 0u}; + fs8x_status_t spiCommunicationState = fs8xStatusError; /* Copy TX data in TX array, reset RX array */ for (uint8_t i = 0u; i < FS8x_COMM_FRAME_SIZE; i++) { - sbc_txBuffer[FS8x_COMM_FRAME_SIZE - 1u - i] = (uint16_t)txFrame[i]; /* txFrame[0] will be sent last */ - sbc_rxBuffer[i] = 0; + fs85_txBuffer[FS8x_COMM_FRAME_SIZE - 1u - i] = (uint16_t)txFrame[i]; /* txFrame[0] will be sent last */ + fs85_rxBuffer[i] = 0; } STD_RETURN_TYPE_e spiRetval = - SPI_TransmitReceiveData(pSpiInterface, sbc_txBuffer, sbc_rxBuffer, FS8x_COMM_FRAME_SIZE); + SPI_TransmitReceiveData(pSpiInterface, fs85_txBuffer, fs85_rxBuffer, FS8x_COMM_FRAME_SIZE); if (spiRetval == STD_OK) { /* No error flag set - copy RX data in RX array */ for (uint8_t i = 0u; i < FS8x_COMM_FRAME_SIZE; i++) { - rxFrame[i] = (uint8_t)sbc_rxBuffer[FS8x_COMM_FRAME_SIZE - 1u - i]; + rxFrame[i] = (uint8_t)fs85_rxBuffer[FS8x_COMM_FRAME_SIZE - 1u - i]; } spiCommunicationState = fs8xStatusOk; } @@ -1020,31 +1083,32 @@ extern UNIT_TEST_WEAK_IMPL fs8x_status_t MCU_SPI_TransferData( return spiCommunicationState; } -extern STD_RETURN_TYPE_e SBC_TriggerWatchdog(FS85_STATE_s *pInstance) { +extern STD_RETURN_TYPE_e FS85_TriggerWatchdog(FS85_STATE_s *pInstance) { FAS_ASSERT(pInstance != NULL_PTR); STD_RETURN_TYPE_e retval = STD_NOT_OK; if (fs8xStatusOk == FS8x_WD_Refresh(pInstance->pSpiInterface, &(pInstance->configValues))) { /* Check GRL_FLAGS register if watchdog refresh was valid */ - if (STD_OK == SBC_ReadBackRegister(pInstance, true, FS8X_FS_GRL_FLAGS_ADDR)) { + if (STD_OK == FS85_ReadBackRegister(pInstance, true, FS8X_FS_GRL_FLAGS_ADDR)) { uint16_t registerMask = FS8X_FS_FS_WD_G_MASK; uint16_t expRegisterValue = FS8X_FS_FS_WD_G_GOOD_WD_REFRESH; - if (STD_OK == SBC_CheckRegisterValues((pInstance->fsRegister.grl_flags & registerMask), expRegisterValue)) { + if (STD_OK == + FS85_CheckRegisterValues((pInstance->fsRegister.grl_flags & registerMask), expRegisterValue)) { /* GOOD watchdog refresh */ retval = STD_OK; } else { /* BAD watchdog refresh: get reason */ - if (STD_OK == SBC_ReadBackRegister(pInstance, true, FS8X_FS_DIAG_SAFETY_ADDR)) { + if (STD_OK == FS85_ReadBackRegister(pInstance, true, FS8X_FS_DIAG_SAFETY_ADDR)) { registerMask = FS8X_FS_BAD_WD_TIMING_MASK; expRegisterValue = FS8X_FS_BAD_WD_TIMING_BAD_WD_REFRESH; - if (STD_OK == - SBC_CheckRegisterValues((pInstance->fsRegister.diag_safety & registerMask), expRegisterValue)) { + if (STD_OK == FS85_CheckRegisterValues( + (pInstance->fsRegister.diag_safety & registerMask), expRegisterValue)) { /* TODO: Notify someone: bad watchdog refresh was caused by wrong window or in timeout */ } registerMask = FS8X_FS_BAD_WD_DATA_MASK; expRegisterValue = FS8X_FS_BAD_WD_DATA_BAD_WD_REFRESH; - if (STD_OK == - SBC_CheckRegisterValues((pInstance->fsRegister.diag_safety & registerMask), expRegisterValue)) { + if (STD_OK == FS85_CheckRegisterValues( + (pInstance->fsRegister.diag_safety & registerMask), expRegisterValue)) { /* TODO: Notify someone: bad watchdog refresh was caused by error in data */ } } @@ -1054,49 +1118,49 @@ extern STD_RETURN_TYPE_e SBC_TriggerWatchdog(FS85_STATE_s *pInstance) { return retval; } -static STD_RETURN_TYPE_e SBC_ReadBackAllRegisters(FS85_STATE_s *pInstance) { +static STD_RETURN_TYPE_e FS85_ReadBackAllRegisters(FS85_STATE_s *pInstance) { FAS_ASSERT(pInstance != NULL_PTR); STD_RETURN_TYPE_e retval = STD_OK; /* Read all fail-safe registers */ - SBC_ReadBackRegister(pInstance, true, FS8X_FS_GRL_FLAGS_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_I_OVUV_SAFE_REACTION1_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_I_OVUV_SAFE_REACTION2_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_I_WD_CFG_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_I_SAFE_INPUTS_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_I_FSSM_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_I_SVS_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_WD_WINDOW_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_WD_SEED_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_WD_ANSWER_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_OVUVREG_STATUS_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_RELEASE_FS0B_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_SAFE_IOS_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_DIAG_SAFETY_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_INTB_MASK_ADDR); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_STATES_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_GRL_FLAGS_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_I_OVUV_SAFE_REACTION1_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_I_OVUV_SAFE_REACTION2_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_I_WD_CFG_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_I_SAFE_INPUTS_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_I_FSSM_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_I_SVS_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_WD_WINDOW_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_WD_SEED_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_WD_ANSWER_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_OVUVREG_STATUS_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_RELEASE_FS0B_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_SAFE_IOS_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_DIAG_SAFETY_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_INTB_MASK_ADDR); + (void)FS85_ReadBackRegister(pInstance, true, FS8X_FS_STATES_ADDR); /* Read main registers */ - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_FLAG_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_MODE_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_REG_CTRL1_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_REG_CTRL2_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_AMUX_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_CLOCK_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_INT_MASK1_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_INT_MASK2_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_FLAG1_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_FLAG2_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_VMON_REGX_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_LVB1_SVS_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_MEMORY0_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_MEMORY1_ADDR); - SBC_ReadBackRegister(pInstance, FALSE, FS8X_M_DEVICEID_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_FLAG_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_MODE_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_REG_CTRL1_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_REG_CTRL2_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_AMUX_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_CLOCK_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_INT_MASK1_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_INT_MASK2_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_FLAG1_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_FLAG2_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_VMON_REGX_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_LVB1_SVS_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_MEMORY0_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_MEMORY1_ADDR); + (void)FS85_ReadBackRegister(pInstance, FALSE, FS8X_M_DEVICEID_ADDR); return retval; } -static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance) { +static STD_RETURN_TYPE_e FS85_PerformPathCheckRstb(FS85_STATE_s *pInstance) { FAS_ASSERT(pInstance != NULL_PTR); STD_RETURN_TYPE_e retval = STD_OK; @@ -1110,7 +1174,7 @@ static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance) { if (pInstance->fin.finUsed == true) { /** Write to NVRAM to determine after reset and if short-circuit * between RSTB and FIN present what exactly caused the reset. */ - pInstance->nvram.data->phase = (uint8_t)SBC_FIN_TEST; + pInstance->nvram.pData->phase = (uint8_t)FS85_FIN_TEST; FRAM_WriteData(pInstance->nvram.entry); /** MCU SBC is connected to ECLK1 -> privilege mode is required to access register */ @@ -1133,8 +1197,8 @@ static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance) { /** FIN state okay, no short circuit. Update also in nvram struct */ DIAG_Handler(DIAG_ID_SBC_FIN_STATE, DIAG_EVENT_OK, DIAG_SYSTEM, 0); - pInstance->fin.finState = STD_OK; - pInstance->nvram.data->finState = STD_OK; + pInstance->fin.finState = STD_OK; + pInstance->nvram.pData->finState = STD_OK; /** Continue with RSTB assertion test */ test_assertionRSTB = false; @@ -1146,35 +1210,35 @@ static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance) { /** Last reset reason was external reset via nRST pin (EXT_RESET) Readout FRAM to determine in which state the SBC was prior to reset */ FRAM_ReadData(pInstance->nvram.entry); - if ((SBC_INIT_PHASE_e)pInstance->nvram.data->phase == SBC_FIN_TEST) { + if ((FS85_INIT_PHASE_e)pInstance->nvram.pData->phase == FS85_FIN_TEST) { /** Short-circuit between FIN and RSTB: Do not apply CLK on FIN */ /** Update nvram FIN state */ - pInstance->nvram.data->finState = STD_NOT_OK; + pInstance->nvram.pData->finState = STD_NOT_OK; /** FIN state not okay, but still in SBC init phase after power-cycle * continue now with RSTB assertion */ test_assertionRSTB = false; - } else if ((SBC_INIT_PHASE_e)pInstance->nvram.data->phase == SBC_RSTB_ASSERTION_TEST) { + } else if ((FS85_INIT_PHASE_e)pInstance->nvram.pData->phase == FS85_RSTB_ASSERTION_TEST) { /** Reset was triggered by SPI RSTB assertion test -> continue with SBC init phase */ test_assertionRSTB = false; /** Diagnosis of the RSTB pin/event is available by reading the FS_SAFE_IOs register: * RSTB_EVENT bit reports an activation of RSTB pin. */ - SBC_ReadBackRegister(pInstance, true, FS8X_FS_SAFE_IOS_ADDR); + FS85_ReadBackRegister(pInstance, true, FS8X_FS_SAFE_IOS_ADDR); /** Check RSTB_EVENT if RSTB has been activated */ if (STD_OK == - SBC_CheckRegisterValues( + FS85_CheckRegisterValues( (pInstance->fsRegister.safeIos & FS8X_FS_RSTB_EVENT_MASK), FS8X_FS_RSTB_EVENT_RESET_OCCURRED)) { /** RSTB pin should be sensed high and no RSTB short to high */ uint16_t mask = (FS8X_FS_RSTB_DIAG_MASK | FS8X_FS_RSTB_SNS_MASK | FS8X_FS_RSTB_DRV_MASK); uint16_t expRegisterValue = (FS8X_FS_RSTB_DIAG_NO_FAILURE | FS8X_FS_RSTB_SNS_PAD_SENSED_HIGH | FS8X_FS_RSTB_DRV_COMMAND_SENSED_HIGH); - if (STD_OK != SBC_CheckRegisterValues((pInstance->fsRegister.safeIos & mask), expRegisterValue)) { + if (STD_OK != FS85_CheckRegisterValues((pInstance->fsRegister.safeIos & mask), expRegisterValue)) { retval = STD_NOT_OK; } /** Reset RSTB_EVENT flag */ - SBC_WriteBackRegisterFsInit(pInstance, FS8X_FS_SAFE_IOS_ADDR, FS8X_FS_RSTB_EVENT_RESET_OCCURRED); + FS85_WriteBackRegisterFsInit(pInstance, FS8X_FS_SAFE_IOS_ADDR, FS8X_FS_RSTB_EVENT_RESET_OCCURRED); /** Update diag flag */ DIAG_Handler(DIAG_ID_SBC_RSTB_STATE, DIAG_EVENT_OK, DIAG_SYSTEM, 0); } else { @@ -1190,7 +1254,7 @@ static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance) { } /** Copy FIN state info from nvram variable into local state variable. This restores lost data from rest or updates local FIN state if short-circuit between FIN and RSTB has been detected */ - pInstance->fin.finState = pInstance->nvram.data->finState; + pInstance->fin.finState = pInstance->nvram.pData->finState; if (pInstance->fin.finState == STD_OK) { DIAG_Handler(DIAG_ID_SBC_FIN_STATE, DIAG_EVENT_OK, DIAG_SYSTEM, 0); } else { @@ -1201,7 +1265,7 @@ static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance) { * power-cycle. Everything okay. Read FIN state from NVRAM and continue with normal operation */ FRAM_ReadData(pInstance->nvram.entry); test_assertionRSTB = false; - pInstance->fin.finState = pInstance->nvram.data->finState; + pInstance->fin.finState = pInstance->nvram.pData->finState; if (pInstance->fin.finState == STD_OK) { DIAG_Handler(DIAG_ID_SBC_FIN_STATE, DIAG_EVENT_OK, DIAG_SYSTEM, 0); } else { @@ -1212,13 +1276,13 @@ static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance) { /** Verify the hardware connection between the MCU reset pin and the FS85 reset pin */ if (test_assertionRSTB == true) { /** Write to NVRAM to determine after reset and if RSTB was asserted correctly */ - pInstance->nvram.data->phase = (uint8_t)SBC_RSTB_ASSERTION_TEST; + pInstance->nvram.pData->phase = (uint8_t)FS85_RSTB_ASSERTION_TEST; FRAM_WriteData(pInstance->nvram.entry); - SBC_ReadBackRegister(pInstance, true, FS8X_FS_STATES_ADDR); + FS85_ReadBackRegister(pInstance, true, FS8X_FS_STATES_ADDR); uint16_t registerValue = FS8X_FS_RSTB_REQ_RSTB_ASSERTION; - SBC_WriteRegisterFsInit(pInstance, FS8X_FS_SAFE_IOS_ADDR, registerValue); + FS85_WriteRegisterFsInit(pInstance, FS8X_FS_SAFE_IOS_ADDR, registerValue); while (true) { ; @@ -1229,7 +1293,7 @@ static STD_RETURN_TYPE_e SBC_PerformPathCheckRstb(FS85_STATE_s *pInstance) { return retval; } -static STD_RETURN_TYPE_e SBC_PerformPathCheckFs0b(FS85_STATE_s *pInstance) { +static STD_RETURN_TYPE_e FS85_PerformPathCheckFs0b(FS85_STATE_s *pInstance) { FAS_ASSERT(pInstance != NULL_PTR); STD_RETURN_TYPE_e retval = STD_OK; @@ -1239,30 +1303,62 @@ static STD_RETURN_TYPE_e SBC_PerformPathCheckFs0b(FS85_STATE_s *pInstance) { /*========== Externalized Static Function Implementations (Unit Test) =======*/ #ifdef UNITY_UNIT_TEST -extern STD_RETURN_TYPE_e TEST_SBC_CheckRegisterValues(uint32_t registerValue, uint32_t expectedRegisterValue) { - return SBC_CheckRegisterValues(registerValue, expectedRegisterValue); +extern STD_RETURN_TYPE_e TEST_FS85_CheckRegisterValues(uint32_t registerValue, uint32_t expectedRegisterValue) { + return FS85_CheckRegisterValues(registerValue, expectedRegisterValue); } - -extern void TEST_SBC_UpdateRegister( +extern void TEST_FS85_UpdateRegister( FS85_STATE_s *pInstance, bool isFailSafe, uint32_t registerAddress, uint32_t registerValue) { - return SBC_UpdateRegister(pInstance, isFailSafe, registerAddress, registerValue); + FS85_UpdateRegister(pInstance, isFailSafe, registerAddress, registerValue); } - -extern void TEST_SBC_UpdateFailSafeRegister( +extern void TEST_FS85_UpdateFailSafeRegister( FS85_FS_REGISTER_s *pFsRegister, uint32_t registerAddress, uint32_t registerValue) { - return SBC_UpdateFailSafeRegister(pFsRegister, registerAddress, registerValue); + FS85_UpdateFailSafeRegister(pFsRegister, registerAddress, registerValue); } -extern void TEST_SBC_UpdateMainRegister( +extern void TEST_FS85_UpdateMainRegister( FS85_MAIN_REGISTERS_s *pMainRegister, uint32_t registerAddress, uint32_t registerValue) { - return SBC_UpdateMainRegister(pMainRegister, registerAddress, registerValue); + FS85_UpdateMainRegister(pMainRegister, registerAddress, registerValue); +} +extern STD_RETURN_TYPE_e TEST_FS85_ReadBackRegister(FS85_STATE_s *pInstance, bool isFailSafe, uint8_t registerAddress) { + return FS85_ReadBackRegister(pInstance, isFailSafe, registerAddress); +} +extern STD_RETURN_TYPE_e TEST_FS85_WriteRegisterFsInit( + FS85_STATE_s *pInstance, + uint8_t registerAddress, + uint16_t registerValue) { + return FS85_WriteRegisterFsInit(pInstance, registerAddress, registerValue); +} +extern STD_RETURN_TYPE_e TEST_FS85_WriteBackRegisterFsInit( + FS85_STATE_s *pInstance, + uint8_t registerAddress, + uint16_t registerValue) { + return FS85_WriteBackRegisterFsInit(pInstance, registerAddress, registerValue); +} +extern STD_RETURN_TYPE_e TEST_FS85_ClearRegisterFlags( + FS85_STATE_s *pInstance, + uint8_t registerAddress, + bool isFailSafe, + uint16_t registerValue) { + return FS85_ClearRegisterFlags(pInstance, registerAddress, isFailSafe, registerValue); +} +extern STD_RETURN_TYPE_e TEST_FS85_ReadBackAllRegisters(FS85_STATE_s *pInstance) { + return FS85_ReadBackAllRegisters(pInstance); +} +extern STD_RETURN_TYPE_e TEST_FS85_PerformPathCheckRstb(FS85_STATE_s *pInstance) { + return FS85_PerformPathCheckRstb(pInstance); +} +extern STD_RETURN_TYPE_e TEST_FS85_PerformPathCheckFs0b(FS85_STATE_s *pInstance) { + return FS85_PerformPathCheckFs0b(pInstance); +} +extern STD_RETURN_TYPE_e TEST_FS85_GoToStandby(FS85_STATE_s *pInstance) { + return FS85_GoToStandby(pInstance); } #endif diff --git a/src/app/driver/sbc/nxpfs85xx.h b/src/app/driver/sbc/nxpfs85xx.h index 55ae4f87..e170a0fc 100644 --- a/src/app/driver/sbc/nxpfs85xx.h +++ b/src/app/driver/sbc/nxpfs85xx.h @@ -43,8 +43,8 @@ * @file nxpfs85xx.h * @author foxBMS Team * @date 2020-03-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix FS85 * @@ -59,11 +59,8 @@ /*========== Includes =======================================================*/ #include "fram_cfg.h" -#include "nxpfs85xx_cfg.h" #include "sbc_fs8x.h" -#include "sbc_fs8x_communication.h" -#include "spi.h" #include @@ -110,8 +107,8 @@ typedef struct { } FS85_MAIN_REGISTERS_s; typedef enum { - SBC_NORMAL_MODE, - SBC_DEBUG_MODE, + FS85_NORMAL_MODE, + FS85_DEBUG_MODE, } FS85_OPERATION_MODE_e; /** struct for FIN configuration */ @@ -124,11 +121,11 @@ typedef struct { /** stores a pointer to the persistent entry in the FRAM */ typedef struct { - FRAM_BLOCK_ID_e entry; /*!< FRAM ID of persistent SBC entry in FRAM */ - FRAM_SBC_INIT_s *data; /*!< pointer to SBC entry in FRAM module */ + FRAM_BLOCK_ID_e entry; /*!< FRAM ID of persistent SBC entry in FRAM */ + FRAM_SBC_INIT_s *pData; /*!< pointer to SBC entry in FRAM module */ } FS85_NVRAM_INFO_s; -/** state struct to create SBC instance */ +/** state struct to create FS85xx instance */ typedef struct { SPI_INTERFACE_CONFIG_s *pSpiInterface; /*< pointer to used SPI interface configuration */ fs8x_drv_data_t configValues; /*!< configuration of used communication interface */ @@ -160,14 +157,14 @@ extern STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance); * fault error counter * @param[in,out] pInstance SBC instance that is * initialized - * @param[out] requiredWatchdogRefreshes number of required good + * @param[out] pRequiredWatchdogRefreshes number of required good * watchdog refreshes * @return #STD_OK if required watchdog refreshes were calculated * successfully, otherwise #STD_NOT_OK */ extern STD_RETURN_TYPE_e FS85_InitializeNumberOfRequiredWatchdogRefreshes( FS85_STATE_s *pInstance, - uint8_t *requiredWatchdogRefreshes); + uint8_t *pRequiredWatchdogRefreshes); /** * @brief Checks if fault error counter is zero @@ -196,24 +193,51 @@ extern STD_RETURN_TYPE_e FS85_SafetyPathChecks(FS85_STATE_s *pInstance); * @return #STD_OK if watchdog has been triggered successfully, * otherwise #STD_NOT_OK */ -extern STD_RETURN_TYPE_e SBC_TriggerWatchdog(FS85_STATE_s *pInstance); +extern STD_RETURN_TYPE_e FS85_TriggerWatchdog(FS85_STATE_s *pInstance); + +/** + * @brief Check WAKE1 Signal at SBC + * @details Checks ignition signal at WAKE1 pin of SBC. If falling + * edge is detected, send SBC to Standby. + * @param[in,out] pInstance SBC instance where WAKE1 is checked + * @return true if ignition signal is detected, otherwise false + */ +extern bool FS85_CheckIgnitionSignal(FS85_STATE_s *pInstance); /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST -extern STD_RETURN_TYPE_e TEST_SBC_CheckRegisterValues(uint32_t registerValue, uint32_t expectedRegisterValue); -extern void TEST_SBC_UpdateRegister( +extern STD_RETURN_TYPE_e TEST_FS85_CheckRegisterValues(uint32_t registerValue, uint32_t expectedRegisterValue); +extern void TEST_FS85_UpdateRegister( FS85_STATE_s *pInstance, bool isFailSafe, uint32_t registerAddress, uint32_t registerValue); -extern void TEST_SBC_UpdateFailSafeRegister( +extern void TEST_FS85_UpdateFailSafeRegister( FS85_FS_REGISTER_s *pFsRegister, uint32_t registerAddress, uint32_t registerValue); -extern void TEST_SBC_UpdateMainRegister( +extern void TEST_FS85_UpdateMainRegister( FS85_MAIN_REGISTERS_s *pMainRegister, uint32_t registerAddress, uint32_t registerValue); +extern STD_RETURN_TYPE_e TEST_FS85_ReadBackRegister(FS85_STATE_s *pInstance, bool isFailSafe, uint8_t registerAddress); +extern STD_RETURN_TYPE_e TEST_FS85_WriteRegisterFsInit( + FS85_STATE_s *pInstance, + uint8_t registerAddress, + uint16_t registerValue); +extern STD_RETURN_TYPE_e TEST_FS85_WriteBackRegisterFsInit( + FS85_STATE_s *pInstance, + uint8_t registerAddress, + uint16_t registerValue); +extern STD_RETURN_TYPE_e TEST_FS85_ClearRegisterFlags( + FS85_STATE_s *pInstance, + uint8_t registerAddress, + bool isFailSafe, + uint16_t registerValue); +extern STD_RETURN_TYPE_e TEST_FS85_ReadBackAllRegisters(FS85_STATE_s *pInstance); +extern STD_RETURN_TYPE_e TEST_FS85_PerformPathCheckRstb(FS85_STATE_s *pInstance); +extern STD_RETURN_TYPE_e TEST_FS85_PerformPathCheckFs0b(FS85_STATE_s *pInstance); +extern STD_RETURN_TYPE_e TEST_FS85_GoToStandby(FS85_STATE_s *pInstance); #endif #endif /* FOXBMS__NXPFS85XX_H_ */ diff --git a/src/app/driver/sbc/sbc.c b/src/app/driver/sbc/sbc.c index d244ec10..3f497da2 100644 --- a/src/app/driver/sbc/sbc.c +++ b/src/app/driver/sbc/sbc.c @@ -43,8 +43,8 @@ * @file sbc.c * @author foxBMS Team * @date 2020-07-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix SBC * @@ -82,13 +82,14 @@ SBC_STATE_s sbc_stateMcuSupervisor = { .substate = SBC_ENTRY, .lastState = SBC_STATEMACHINE_UNINITIALIZED, .lastSubstate = SBC_ENTRY, - .illegalRequestsCounter = 0u, /*!< counts the number of illegal requests to the SBC state machine */ - .retryCounter = 0u, /*!< counter to retry subsystem initialization if fails */ - .requestWatchdogTrigger = 0u, /*!< correct value set during init process */ - .triggerEntry = 0u, /*!< counter for re-entrance protection (function running flag) */ - .pFs85xxInstance = &fs85xx_mcuSupervisor, /*!< pointer to FS85xx instance */ - .watchdogState = SBC_PERIODIC_WATCHDOG_DEACTIVATED, - .watchdogPeriod_10ms = 10u, + .illegalRequestsCounter = 0u, /*!< counts the number of illegal requests to the SBC state machine */ + .retryCounter = 0u, /*!< counter to retry subsystem initialization if fails */ + .requestWatchdogTrigger = 0u, /*!< correct value set during init process */ + .triggerEntry = 0u, /*!< counter for re-entrance protection (function running flag) */ + .pFs85xxInstance = &fs85xx_mcuSupervisor, /*!< pointer to FS85xx instance */ + .watchdogState = SBC_PERIODIC_WATCHDOG_DEACTIVATED, + .watchdogPeriod_10ms = 10u, + .useIgnitionForPowerDown = true, }; /*========== Static Function Prototypes =====================================*/ @@ -129,8 +130,7 @@ static SBC_CHECK_REENTRANCE_e SBC_CheckReEntrance(SBC_STATE_s *pInstance); * machine. It resets the value from stateRequest to * #SBC_STATE_NO_REQUEST * @param[in,out] pInstance - * @return retVal current state request, taken from - * #SYS_STATE_REQUEST_e + * @return current state request, taken from #SBC_STATE_REQUEST_e */ static SBC_STATE_REQUEST_e SBC_TransferStateRequest(SBC_STATE_s *pInstance); @@ -139,11 +139,20 @@ static SBC_STATE_REQUEST_e SBC_TransferStateRequest(SBC_STATE_s *pInstance); * @details This function checks whether the watchdog timer elapses, * and triggers the watchdog in that case. * @param[in,out] pInstance - * @return retVal current state request, taken from + * @return true if watchdog has been triggered, false otherwise * #SYS_STATE_REQUEST_e */ static bool SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance); +/** + * @brief Handle ignition/clamp 15 signal. + * @details Checks ignition signal (clamp 15) and put BMS in shutdown + * mode if ignition signal is not detected anymore. + * @param[in,out] pInstance SBC instance where ignition signal is connected + * @return true if ignition signal is detected, false otherwise + */ +static bool SBC_IsIgnitionSignalDetected(SBC_STATE_s *pInstance); + /*========== Static Function Implementations ================================*/ static void SBC_SaveLastStates(SBC_STATE_s *pInstance) { FAS_ASSERT(pInstance != NULL_PTR); @@ -219,7 +228,7 @@ static bool SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance) { if (pInstance->watchdogTrigger > 0u) { pInstance->watchdogTrigger--; if (pInstance->watchdogTrigger == 0u) { - if (STD_OK != SBC_TriggerWatchdog(pInstance->pFs85xxInstance)) { + if (STD_OK != FS85_TriggerWatchdog(pInstance->pFs85xxInstance)) { /* TODO: Do what if triggering of watchdog fails? */ } else { watchdogHasBeenTriggered = true; @@ -234,6 +243,12 @@ static bool SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance) { return watchdogHasBeenTriggered; } +static bool SBC_IsIgnitionSignalDetected(SBC_STATE_s *pInstance) { + FAS_ASSERT(pInstance != NULL_PTR); + + return FS85_CheckIgnitionSignal(pInstance->pFs85xxInstance); +} + /*========== Extern Function Implementations ================================*/ extern SBC_RETURN_TYPE_e SBC_SetStateRequest(SBC_STATE_s *pInstance, SBC_STATE_REQUEST_e stateRequest) { FAS_ASSERT(pInstance != NULL_PTR); @@ -381,6 +396,10 @@ extern void SBC_Trigger(SBC_STATE_s *pInstance) { case SBC_STATEMACHINE_RUNNING: SBC_SaveLastStates(pInstance); pInstance->timer = SBC_STATEMACHINE_LONGTIME; + if (pInstance->useIgnitionForPowerDown == true) { + /* Return value is currently discarded, shutdown handling needs to be implemented */ + (void)SBC_IsIgnitionSignalDetected(pInstance); + } break; /****************************ERROR*************************************/ @@ -399,7 +418,20 @@ extern void SBC_Trigger(SBC_STATE_s *pInstance) { /*========== Externalized Static Function Implementations (Unit Test) =======*/ #ifdef UNITY_UNIT_TEST +extern void TEST_SBC_SaveLastStates(SBC_STATE_s *pInstance) { + SBC_SaveLastStates(pInstance); +} +extern SBC_RETURN_TYPE_e TEST_SBC_CheckStateRequest(SBC_STATE_s *pInstance, SBC_STATE_REQUEST_e stateRequest) { + return SBC_CheckStateRequest(pInstance, stateRequest); +} + +extern SBC_CHECK_REENTRANCE_e TEST_SBC_CheckReEntrance(SBC_STATE_s *pInstance) { + return TEST_SBC_CheckReEntrance(pInstance); +} extern bool TEST_SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance) { return SBC_TriggerWatchdogIfRequired(pInstance); } +extern bool TEST_SBC_IsIgnitionSignalDetected(SBC_STATE_s *pInstance) { + return SBC_IsIgnitionSignalDetected(pInstance); +} #endif diff --git a/src/app/driver/sbc/sbc.h b/src/app/driver/sbc/sbc.h index dede8a34..ad30bc44 100644 --- a/src/app/driver/sbc/sbc.h +++ b/src/app/driver/sbc/sbc.h @@ -43,8 +43,8 @@ * @file sbc.h * @author foxBMS Team * @date 2020-07-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix SBC * @@ -168,6 +168,7 @@ typedef struct { SBC_PERIODIC_WATCHDOG_STATE_e watchdogState; /*!< state if periodic watchdog trigger is required or not */ FS85_STATE_s *pFs85xxInstance; /*!< pointer to FS85xx instance */ uint16_t watchdogPeriod_10ms; /*!< watchdog trigger frequency in 10ms */ + bool useIgnitionForPowerDown; /*!< configures whether ignition signal is used for power down requests */ } SBC_STATE_s; /*========== Extern Constant and Variable Declarations ======================*/ @@ -212,6 +213,7 @@ extern void SBC_Trigger(SBC_STATE_s *pInstance); /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST extern bool TEST_SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance); +extern bool TEST_SBC_IsIgnitionSignalDetected(SBC_STATE_s *pInstance); #endif #endif /* FOXBMS__SBC_H_ */ diff --git a/src/app/driver/spi/spi.c b/src/app/driver/spi/spi.c index 553592da..8f614192 100644 --- a/src/app/driver/spi/spi.c +++ b/src/app/driver/spi/spi.c @@ -43,8 +43,8 @@ * @file spi.c * @author foxBMS Team * @date 2019-12-12 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix SPI * @@ -137,6 +137,7 @@ static uint8_t SPI_GetChipSelectPin(SPI_CHIP_SELECT_TYPE_e chipSelectType, uint3 } static void SPI_InitializeChipSelects(void) { for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + spi_adiInterface[s].pConfig->CSNR = SPI_GetChipSelectPin(spi_adiInterface[s].csType, spi_adiInterface[s].csPin); spi_ltcInterface[s].pConfig->CSNR = SPI_GetChipSelectPin(spi_ltcInterface[s].csType, spi_ltcInterface[s].csPin); spi_nxp775InterfaceTx[s].pConfig->CSNR = SPI_GetChipSelectPin(spi_nxp775InterfaceTx[s].csType, spi_nxp775InterfaceTx[s].csPin); @@ -577,7 +578,7 @@ extern uint8_t SPI_GetSpiIndex(spiBASE_t *pNode) { /*========== Externalized Static Function Implementations (Unit Test) =======*/ #ifdef UNITY_UNIT_TEST extern void TEST_SPI_InitializeChipSelects(void) { - return SPI_InitializeChipSelects(); + SPI_InitializeChipSelects(); } extern uint8_t TEST_SPI_GetChipSelectPin(SPI_CHIP_SELECT_TYPE_e csType, uint32_t csPin) { return SPI_GetChipSelectPin(csType, csPin); diff --git a/src/app/driver/spi/spi.h b/src/app/driver/spi/spi.h index 4e94339a..eeaf8c18 100644 --- a/src/app/driver/spi/spi.h +++ b/src/app/driver/spi/spi.h @@ -43,8 +43,8 @@ * @file spi.h * @author foxBMS Team * @date 2019-12-12 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix SPI * diff --git a/src/app/driver/spi/spi_cfg-helper.h b/src/app/driver/spi/spi_cfg-helper.h index 3cf9af0c..c5c2a930 100644 --- a/src/app/driver/spi/spi_cfg-helper.h +++ b/src/app/driver/spi/spi_cfg-helper.h @@ -43,8 +43,8 @@ * @file spi_cfg-helper.h * @author foxBMS Team * @date 2021-12-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS_CONFIGURATION * @prefix SPI * diff --git a/src/app/driver/sps/sps.c b/src/app/driver/sps/sps.c index a9a6b05f..83b77dbd 100644 --- a/src/app/driver/sps/sps.c +++ b/src/app/driver/sps/sps.c @@ -43,8 +43,8 @@ * @file sps.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix SPS * diff --git a/src/app/driver/sps/sps.h b/src/app/driver/sps/sps.h index 4c538a2e..d65154ef 100644 --- a/src/app/driver/sps/sps.h +++ b/src/app/driver/sps/sps.h @@ -43,8 +43,8 @@ * @file sps.h * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix SPS * diff --git a/src/app/driver/sps/sps_types.h b/src/app/driver/sps/sps_types.h index 4e7d407f..d742bc9b 100644 --- a/src/app/driver/sps/sps_types.h +++ b/src/app/driver/sps/sps_types.h @@ -43,8 +43,8 @@ * @file sps_types.h * @author foxBMS Team * @date 2020-12-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVERS * @prefix SPS * diff --git a/src/app/driver/ts/api/tsi.h b/src/app/driver/ts/api/tsi.h index fba76a34..58e6af16 100644 --- a/src/app/driver/ts/api/tsi.h +++ b/src/app/driver/ts/api/tsi.h @@ -43,8 +43,8 @@ * @file tsi.h * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix TSI * diff --git a/src/app/driver/ts/api/tsi_limits.c b/src/app/driver/ts/api/tsi_limits.c index 550c16d7..3141ae34 100644 --- a/src/app/driver/ts/api/tsi_limits.c +++ b/src/app/driver/ts/api/tsi_limits.c @@ -43,8 +43,8 @@ * @file tsi_limits.c * @author foxBMS Team * @date 2021-01-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DRIVER * @prefix TSI * diff --git a/src/app/driver/ts/beta.c b/src/app/driver/ts/beta.c index 79d563e1..14b1fa4d 100644 --- a/src/app/driver/ts/beta.c +++ b/src/app/driver/ts/beta.c @@ -43,8 +43,8 @@ * @file beta.c * @author foxBMS Team * @date 2020-01-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix BETA * diff --git a/src/app/driver/ts/beta.h b/src/app/driver/ts/beta.h index 512f4873..1e23f515 100644 --- a/src/app/driver/ts/beta.h +++ b/src/app/driver/ts/beta.h @@ -43,8 +43,8 @@ * @file beta.h * @author foxBMS Team * @date 2020-01-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix BETA * diff --git a/src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.c b/src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.c index c9fa6070..41c24390 100644 --- a/src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.c +++ b/src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.c @@ -43,8 +43,8 @@ * @file epcos_b57251v5103j060.c * @author foxBMS Team * @date 2018-10-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.h b/src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.h index 00d90448..0ade5de5 100644 --- a/src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.h +++ b/src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.h @@ -43,8 +43,8 @@ * @file epcos_b57251v5103j060.h * @author foxBMS Team * @date 2018-10-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/epcos/b57251v5103j060/lookup-table/epcos_b57251v5103j060_lookup-table.c b/src/app/driver/ts/epcos/b57251v5103j060/lookup-table/epcos_b57251v5103j060_lookup-table.c index 599dfb0f..f2b92700 100644 --- a/src/app/driver/ts/epcos/b57251v5103j060/lookup-table/epcos_b57251v5103j060_lookup-table.c +++ b/src/app/driver/ts/epcos/b57251v5103j060/lookup-table/epcos_b57251v5103j060_lookup-table.c @@ -43,8 +43,8 @@ * @file epcos_b57251v5103j060_lookup-table.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/epcos/b57251v5103j060/polynomial/epcos_b57251v5103j060_polynomial.c b/src/app/driver/ts/epcos/b57251v5103j060/polynomial/epcos_b57251v5103j060_polynomial.c index e89612ba..a1677081 100644 --- a/src/app/driver/ts/epcos/b57251v5103j060/polynomial/epcos_b57251v5103j060_polynomial.c +++ b/src/app/driver/ts/epcos/b57251v5103j060/polynomial/epcos_b57251v5103j060_polynomial.c @@ -43,8 +43,8 @@ * @file epcos_b57251v5103j060_polynomial.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.c b/src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.c index 32e834a4..16d34036 100644 --- a/src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.c +++ b/src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.c @@ -43,8 +43,8 @@ * @file epcos_b57861s0103f045.c * @author foxBMS Team * @date 2018-10-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.h b/src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.h index 3b06acbc..0a995fc3 100644 --- a/src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.h +++ b/src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.h @@ -43,8 +43,8 @@ * @file epcos_b57861s0103f045.h * @author foxBMS Team * @date 2018-10-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/epcos/b57861s0103f045/lookup-table/epcos_b57861s0103f045_lookup-table.c b/src/app/driver/ts/epcos/b57861s0103f045/lookup-table/epcos_b57861s0103f045_lookup-table.c index 19eedabb..a8da9a1c 100644 --- a/src/app/driver/ts/epcos/b57861s0103f045/lookup-table/epcos_b57861s0103f045_lookup-table.c +++ b/src/app/driver/ts/epcos/b57861s0103f045/lookup-table/epcos_b57861s0103f045_lookup-table.c @@ -43,8 +43,8 @@ * @file epcos_b57861s0103f045_lookup-table.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/epcos/b57861s0103f045/polynomial/epcos_b57861s0103f045_polynomial.c b/src/app/driver/ts/epcos/b57861s0103f045/polynomial/epcos_b57861s0103f045_polynomial.c index ca37b2a8..a595b00f 100644 --- a/src/app/driver/ts/epcos/b57861s0103f045/polynomial/epcos_b57861s0103f045_polynomial.c +++ b/src/app/driver/ts/epcos/b57861s0103f045/polynomial/epcos_b57861s0103f045_polynomial.c @@ -43,8 +43,8 @@ * @file epcos_b57861s0103f045_polynomial.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/fake/none/fake_none.c b/src/app/driver/ts/fake/none/fake_none.c index 9ea18d20..9526a7ce 100644 --- a/src/app/driver/ts/fake/none/fake_none.c +++ b/src/app/driver/ts/fake/none/fake_none.c @@ -43,8 +43,8 @@ * @file fake_none.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/fake/none/fake_none.h b/src/app/driver/ts/fake/none/fake_none.h index 786e81d4..4049407a 100644 --- a/src/app/driver/ts/fake/none/fake_none.h +++ b/src/app/driver/ts/fake/none/fake_none.h @@ -43,8 +43,8 @@ * @file fake_none.h * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/fake/none/lookup-table/fake_none_lookup-table.c b/src/app/driver/ts/fake/none/lookup-table/fake_none_lookup-table.c index 70957367..d8f957b6 100644 --- a/src/app/driver/ts/fake/none/lookup-table/fake_none_lookup-table.c +++ b/src/app/driver/ts/fake/none/lookup-table/fake_none_lookup-table.c @@ -43,8 +43,8 @@ * @file fake_none_lookup-table.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/fake/none/polynomial/fake_none_polynomial.c b/src/app/driver/ts/fake/none/polynomial/fake_none_polynomial.c index 08c99a9d..5533fa42 100644 --- a/src/app/driver/ts/fake/none/polynomial/fake_none_polynomial.c +++ b/src/app/driver/ts/fake/none/polynomial/fake_none_polynomial.c @@ -43,8 +43,8 @@ * @file fake_none_polynomial.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/murata/ncu15xh103f6sxx/lookup-table/murata_ncu15xh103f6sxx_lookup-table.c b/src/app/driver/ts/murata/ncxxxxh103/lookup-table/murata_ncxxxxh103_lookup-table.c similarity index 95% rename from src/app/driver/ts/murata/ncu15xh103f6sxx/lookup-table/murata_ncu15xh103f6sxx_lookup-table.c rename to src/app/driver/ts/murata/ncxxxxh103/lookup-table/murata_ncxxxxh103_lookup-table.c index 692887a3..2438ca14 100644 --- a/src/app/driver/ts/murata/ncu15xh103f6sxx/lookup-table/murata_ncu15xh103f6sxx_lookup-table.c +++ b/src/app/driver/ts/murata/ncxxxxh103/lookup-table/murata_ncxxxxh103_lookup-table.c @@ -40,11 +40,11 @@ */ /** - * @file murata_ncu15xh103f6sxx_lookup-table.c + * @file murata_ncxxxxh103_lookup-table.c * @author foxBMS Team * @date 2022-10-12 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * @@ -53,7 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "murata_ncu15xh103f6sxx.h" +#include "murata_ncxxxxh103.h" #include "tsi.h" #include diff --git a/src/app/driver/ts/murata/ncu15xh103f6sxx/murata_ncu15xh103f6sxx.c b/src/app/driver/ts/murata/ncxxxxh103/murata_ncxxxxh103.c similarity index 65% rename from src/app/driver/ts/murata/ncu15xh103f6sxx/murata_ncu15xh103f6sxx.c rename to src/app/driver/ts/murata/ncxxxxh103/murata_ncxxxxh103.c index 62a85eb0..d5330cbf 100644 --- a/src/app/driver/ts/murata/ncu15xh103f6sxx/murata_ncu15xh103f6sxx.c +++ b/src/app/driver/ts/murata/ncxxxxh103/murata_ncxxxxh103.c @@ -40,11 +40,11 @@ */ /** - * @file murata_ncu15xh103f6sxx.c + * @file murata_ncxxxxh103.c * @author foxBMS Team * @date 2022-10-12 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * @@ -53,7 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "murata_ncu15xh103f6sxx.h" +#include "murata_ncxxxxh103.h" #include "fassert.h" #include "foxmath.h" @@ -68,7 +68,7 @@ /*========== Static Constant and Variable Definitions =======================*/ /** LUT filled from higher resistance to lower resistance - datasheet: RO3E - Aug. 3, 2018 */ -static const TS_TEMPERATURE_SENSOR_LUT_s ts_ncu15xh103f6sxxLut[] = { +static const TS_TEMPERATURE_SENSOR_LUT_s ts_ncxxxxh103Lut[] = { {-400, 195652.0f}, {-350, 148171.0f}, {-300, 113347.0f}, {-250, 87559.0f}, {-200, 68237.0f}, {-150, 53650.0f}, {-100, 42506.0f}, {-50, 33892.0f}, {0, 27219.0f}, {50, 22021.0f}, {100, 17926.0f}, {150, 14674.0f}, {200, 12081.0f}, {250, 10000.0f}, {300, 8315.0f}, {350, 6948.0f}, {400, 5834.0f}, {450, 4917.0f}, @@ -79,7 +79,7 @@ static const TS_TEMPERATURE_SENSOR_LUT_s ts_ncu15xh103f6sxxLut[] = { }; /** size of the #ts_ntcle317e4103sbaLut LUT */ -static const uint16_t ts_ncu15xh103f6sxxLutSize = sizeof(ts_ncu15xh103f6sxxLut) / sizeof(TS_TEMPERATURE_SENSOR_LUT_s); +static const uint16_t ts_ncxxxxh103LutSize = sizeof(ts_ncxxxxh103Lut) / sizeof(TS_TEMPERATURE_SENSOR_LUT_s); /*========== Extern Constant and Variable Definitions =======================*/ /** @@ -92,17 +92,17 @@ static const uint16_t ts_ncu15xh103f6sxxLutSize = sizeof(ts_ncu15xh103f6sxxLut) * different R_ntc values are used for the calculation. * @{ */ -#if defined(TS_MURATA_NCU15XH103F6SXX_POSITION_IN_RESISTOR_DIVIDER_IS_R_1) && \ - (TS_MURATA_NCU15XH103F6SXX_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == true) -#define TS_MURATA_NCU15XH103F6SXX_ADC_VOLTAGE_V_MAX_V \ - ((float_t)((TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ncu15xh103f6sxxLut[ts_ncu15xh103f6sxxLutSize-1u].resistance_Ohm) / (ts_ncu15xh103f6sxxLut[ts_ncu15xh103f6sxxLutSize-1u].resistance_Ohm+TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) -#define TS_MURATA_NCU15XH103F6SXX_ADC_VOLTAGE_V_MIN_V \ - ((float_t)((TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ncu15xh103f6sxxLut[0u].resistance_Ohm) / (ts_ncu15xh103f6sxxLut[0u].resistance_Ohm+TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) -#else /* TS_MURATA_NCU15XH103F6SXX_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 is false */ -#define TS_MURATA_NCU15XH103F6SXX_ADC_VOLTAGE_V_MIN_V \ - ((float_t)((TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ncu15xh103f6sxxLut[ts_ncu15xh103f6sxxLutSize-1u].resistance_Ohm) / (ts_ncu15xh103f6sxxLut[ts_ncu15xh103f6sxxLutSize-1u].resistance_Ohm+TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) -#define TS_MURATA_NCU15XH103F6SXX_ADC_VOLTAGE_V_MAX_V \ - ((float_t)((TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ncu15xh103f6sxxLut[0u].resistance_Ohm) / (ts_ncu15xh103f6sxxLut[0u].resistance_Ohm+TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) +#if defined(TS_MURATA_NCXXXXH103_POSITION_IN_RESISTOR_DIVIDER_IS_R_1) && \ + (TS_MURATA_NCXXXXH103_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == true) +#define TS_MURATA_NCXXXXH103_ADC_VOLTAGE_V_MAX_V \ + ((float_t)((TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ncxxxxh103Lut[ts_ncxxxxh103LutSize-1u].resistance_Ohm) / (ts_ncxxxxh103Lut[ts_ncxxxxh103LutSize-1u].resistance_Ohm+TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) +#define TS_MURATA_NCXXXXH103_ADC_VOLTAGE_V_MIN_V \ + ((float_t)((TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ncxxxxh103Lut[0u].resistance_Ohm) / (ts_ncxxxxh103Lut[0u].resistance_Ohm+TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) +#else /* TS_MURATA_NCXXXXH103_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 is false */ +#define TS_MURATA_NCXXXXH103_ADC_VOLTAGE_V_MIN_V \ + ((float_t)((TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ncxxxxh103Lut[ts_ncxxxxh103LutSize-1u].resistance_Ohm) / (ts_ncxxxxh103Lut[ts_ncxxxxh103LutSize-1u].resistance_Ohm+TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) +#define TS_MURATA_NCXXXXH103_ADC_VOLTAGE_V_MAX_V \ + ((float_t)((TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ncxxxxh103Lut[0u].resistance_Ohm) / (ts_ncxxxxh103Lut[0u].resistance_Ohm+TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) #endif /**@}*/ @@ -117,32 +117,31 @@ extern int16_t TS_Mur00GetTemperatureFromLut(uint16_t adcVoltage_mV) { float_t adcVoltage_V = (float_t)adcVoltage_mV / TS_SCALING_FACTOR_1V_IN_MV_FLOAT; /* Convert mV to V */ /* Check for valid ADC measurements to prevent undefined behavior */ - if (adcVoltage_V > TS_MURATA_NCU15XH103F6SXX_ADC_VOLTAGE_V_MAX_V) { + if (adcVoltage_V > TS_MURATA_NCXXXXH103_ADC_VOLTAGE_V_MAX_V) { /* Invalid measured ADC voltage -> sensor out of operating range or disconnected/shorted */ temperature_ddegC = INT16_MIN; - } else if (adcVoltage_V < TS_MURATA_NCU15XH103F6SXX_ADC_VOLTAGE_V_MIN_V) { + } else if (adcVoltage_V < TS_MURATA_NCXXXXH103_ADC_VOLTAGE_V_MIN_V) { /* Invalid measured ADC voltage -> sensor out of operating range or shorted/disconnected */ temperature_ddegC = INT16_MAX; } else { /* Calculate NTC resistance based on measured ADC voltage */ -#if defined(TS_MURATA_NCU15XH103F6SXX_POSITION_IN_RESISTOR_DIVIDER_IS_R_1) && \ - (TS_MURATA_NCU15XH103F6SXX_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == true) +#if defined(TS_MURATA_NCXXXXH103_POSITION_IN_RESISTOR_DIVIDER_IS_R_1) && \ + (TS_MURATA_NCXXXXH103_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == true) /* R_1 = R_2 * ( ( V_supply / V_adc ) - 1 ) */ - const float_t resistance_Ohm = - TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm * - ((TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V / adcVoltage_V) - 1); -#else /* TS_MURATA_NCU15XH103F6SXX_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 is false */ + const float_t resistance_Ohm = TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm * + ((TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V / adcVoltage_V) - 1); +#else /* TS_MURATA_NCXXXXH103_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 is false */ /* formula: R_2 = R_1 * ( V_2 / ( V_supply - V_adc ) ) */ const float_t resistance_Ohm = - TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm * - (adcVoltage_V / (TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V - adcVoltage_V)); -#endif /* TS_MURATA_NCU15XH103F6SXX_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 */ + TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm * + (adcVoltage_V / (TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V - adcVoltage_V)); +#endif /* TS_MURATA_NCXXXXH103_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 */ /* Variables for interpolating LUT value */ uint16_t between_high = 0; uint16_t between_low = 0; - for (uint16_t i = 0u; i < ts_ncu15xh103f6sxxLutSize; i++) { - if (resistance_Ohm < ts_ncu15xh103f6sxxLut[i].resistance_Ohm) { + for (uint16_t i = 0u; i < ts_ncxxxxh103LutSize; i++) { + if (resistance_Ohm < ts_ncxxxxh103Lut[i].resistance_Ohm) { between_low = i + 1u; between_high = i; } @@ -150,12 +149,12 @@ extern int16_t TS_Mur00GetTemperatureFromLut(uint16_t adcVoltage_mV) { /* Interpolate between LUT values, but do not extrapolate LUT! */ if (!(((between_high == 0u) && (between_low == 0u)) || /* measured resistance > maximum LUT resistance */ - (between_low >= ts_ncu15xh103f6sxxLutSize))) { /* measured resistance < minimum LUT resistance */ + (between_low >= ts_ncxxxxh103LutSize))) { /* measured resistance < minimum LUT resistance */ temperature_ddegC = (int16_t)MATH_LinearInterpolation( - ts_ncu15xh103f6sxxLut[between_low].resistance_Ohm, - (float_t)ts_ncu15xh103f6sxxLut[between_low].temperature_ddegC, - ts_ncu15xh103f6sxxLut[between_high].resistance_Ohm, - (float_t)ts_ncu15xh103f6sxxLut[between_high].temperature_ddegC, + ts_ncxxxxh103Lut[between_low].resistance_Ohm, + (float_t)ts_ncxxxxh103Lut[between_low].temperature_ddegC, + ts_ncxxxxh103Lut[between_high].resistance_Ohm, + (float_t)ts_ncxxxxh103Lut[between_high].temperature_ddegC, resistance_Ohm); } } diff --git a/src/app/driver/ts/murata/ncu15xh103f6sxx/murata_ncu15xh103f6sxx.h b/src/app/driver/ts/murata/ncxxxxh103/murata_ncxxxxh103.h similarity index 89% rename from src/app/driver/ts/murata/ncu15xh103f6sxx/murata_ncu15xh103f6sxx.h rename to src/app/driver/ts/murata/ncxxxxh103/murata_ncxxxxh103.h index 6ff86406..043a9486 100644 --- a/src/app/driver/ts/murata/ncu15xh103f6sxx/murata_ncu15xh103f6sxx.h +++ b/src/app/driver/ts/murata/ncxxxxh103/murata_ncxxxxh103.h @@ -40,11 +40,11 @@ */ /** - * @file murata_ncu15xh103f6sxx.h + * @file murata_ncxxxxh103.h * @author foxBMS Team * @date 2022-10-12 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * @@ -71,8 +71,8 @@ * GND */ -#ifndef FOXBMS__MURATA_NCU15XH103F6SXX_H_ -#define FOXBMS__MURATA_NCU15XH103F6SXX_H_ +#ifndef FOXBMS__MURATA_NCXXXXH103_H_ +#define FOXBMS__MURATA_NCXXXXH103_H_ /*========== Includes =======================================================*/ @@ -87,16 +87,16 @@ * false: NTC is positioned below the voltage tap for the ADC voltage. * This equals resistor R_2 in the above circuit diagram */ -#define TS_MURATA_NCU15XH103F6SXX_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 (false) +#define TS_MURATA_NCXXXXH103_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 (false) /** Resistor divider supply voltage in volt */ -#define TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V (3.3f) +#define TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V (3.3f) /** * Resistance value of the other resistor (not the NTC) in the resistor * divider in Ohm. */ -#define TS_MURATA_NCU15XH103F6SXX_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm (10000.0f) +#define TS_MURATA_NCXXXXH103_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm (10000.0f) /*========== Extern Constant and Variable Declarations ======================*/ /** @@ -121,4 +121,4 @@ extern int16_t TS_Mur00GetTemperatureFromPolynomial(uint16_t adcVoltage_mV); #ifdef UNITY_UNIT_TEST #endif -#endif /* FOXBMS__MURATA_NCU15XH103F6SXX_H_ */ +#endif /* FOXBMS__MURATA_NCXXXXH103_H_ */ diff --git a/src/app/driver/ts/murata/ncu15xh103f6sxx/polynomial/murata_ncu15xh103f6sxx_polynomial.c b/src/app/driver/ts/murata/ncxxxxh103/polynomial/murata_ncxxxxh103_polynomial.c similarity index 95% rename from src/app/driver/ts/murata/ncu15xh103f6sxx/polynomial/murata_ncu15xh103f6sxx_polynomial.c rename to src/app/driver/ts/murata/ncxxxxh103/polynomial/murata_ncxxxxh103_polynomial.c index 9f307068..fb4632e0 100644 --- a/src/app/driver/ts/murata/ncu15xh103f6sxx/polynomial/murata_ncu15xh103f6sxx_polynomial.c +++ b/src/app/driver/ts/murata/ncxxxxh103/polynomial/murata_ncxxxxh103_polynomial.c @@ -40,11 +40,11 @@ */ /** - * @file murata_ncu15xh103f6sxx_polynomial.c + * @file murata_ncxxxxh103_polynomial.c * @author foxBMS Team * @date 2022-12-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * @@ -53,7 +53,7 @@ */ /*========== Includes =======================================================*/ -#include "murata_ncu15xh103f6sxx.h" +#include "murata_ncxxxxh103.h" #include "tsi.h" #include diff --git a/src/app/driver/ts/temperature_sensor_defs.h b/src/app/driver/ts/temperature_sensor_defs.h index efac39ea..f5da14b4 100644 --- a/src/app/driver/ts/temperature_sensor_defs.h +++ b/src/app/driver/ts/temperature_sensor_defs.h @@ -43,8 +43,8 @@ * @file temperature_sensor_defs.h * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/vishay/ntcalug01a103g/lookup-table/vishay_ntcalug01a103g_lookup-table.c b/src/app/driver/ts/vishay/ntcalug01a103g/lookup-table/vishay_ntcalug01a103g_lookup-table.c index 5877744e..5ca7ffc7 100644 --- a/src/app/driver/ts/vishay/ntcalug01a103g/lookup-table/vishay_ntcalug01a103g_lookup-table.c +++ b/src/app/driver/ts/vishay/ntcalug01a103g/lookup-table/vishay_ntcalug01a103g_lookup-table.c @@ -43,8 +43,8 @@ * @file vishay_ntcalug01a103g_lookup-table.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/vishay/ntcalug01a103g/polynomial/vishay_ntcalug01a103g_polynomial.c b/src/app/driver/ts/vishay/ntcalug01a103g/polynomial/vishay_ntcalug01a103g_polynomial.c index e2def190..50b83c2e 100644 --- a/src/app/driver/ts/vishay/ntcalug01a103g/polynomial/vishay_ntcalug01a103g_polynomial.c +++ b/src/app/driver/ts/vishay/ntcalug01a103g/polynomial/vishay_ntcalug01a103g_polynomial.c @@ -43,8 +43,8 @@ * @file vishay_ntcalug01a103g_polynomial.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.c b/src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.c index c324165e..008a3b42 100644 --- a/src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.c +++ b/src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.c @@ -43,8 +43,8 @@ * @file vishay_ntcalug01a103g.c * @author foxBMS Team * @date 2018-10-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.h b/src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.h index b3c0f873..7b252ec4 100644 --- a/src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.h +++ b/src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.h @@ -43,8 +43,8 @@ * @file vishay_ntcalug01a103g.h * @author foxBMS Team * @date 2018-10-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/vishay_ntcle317e4103sba_lookup-table.c b/src/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/vishay_ntcle317e4103sba_lookup-table.c index 3b889474..585c1715 100644 --- a/src/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/vishay_ntcle317e4103sba_lookup-table.c +++ b/src/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/vishay_ntcle317e4103sba_lookup-table.c @@ -43,8 +43,8 @@ * @file vishay_ntcle317e4103sba_lookup-table.c * @author foxBMS Team * @date 2021-11-03 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.c b/src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.c index 977b3933..d53ee2c6 100644 --- a/src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.c +++ b/src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.c @@ -43,8 +43,8 @@ * @file vishay_ntcle317e4103sba.c * @author foxBMS Team * @date 2021-11-03 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.h b/src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.h index ffe952df..ea8e9729 100644 --- a/src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.h +++ b/src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.h @@ -43,8 +43,8 @@ * @file vishay_ntcle317e4103sba.h * @author foxBMS Team * @date 2021-10-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TEMPERATURE_SENSORS * @prefix TS * diff --git a/src/app/driver/afe/nxp/mc33775a/config/nxp_afe_dma_cfg.c b/src/app/driver/ts/vishay/ntcle413e2103f102l/lookup-table/vishay_ntcle413e2103f102l_lookup-table.c similarity index 86% rename from src/app/driver/afe/nxp/mc33775a/config/nxp_afe_dma_cfg.c rename to src/app/driver/ts/vishay/ntcle413e2103f102l/lookup-table/vishay_ntcle413e2103f102l_lookup-table.c index e4e0035f..c260ef99 100644 --- a/src/app/driver/afe/nxp/mc33775a/config/nxp_afe_dma_cfg.c +++ b/src/app/driver/ts/vishay/ntcle413e2103f102l/lookup-table/vishay_ntcle413e2103f102l_lookup-table.c @@ -40,22 +40,21 @@ */ /** - * @file nxp_afe_dma_cfg.c + * @file vishay_ntcle413e2103f102l_lookup-table.c * @author foxBMS Team - * @date 2020-03-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup DRIVERS_CONFIGURATION - * @prefix DMA + * @date 2021-11-03 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup TEMPERATURE_SENSORS + * @prefix TS * - * @brief Configuration for the DMA module + * @brief Resistive divider used for measuring temperature * */ /*========== Includes =======================================================*/ -#include "nxp_afe_dma_cfg.h" - -#include "nxp_mc33775a.h" +#include "tsi.h" +#include "vishay_ntcle413e2103f102l.h" #include @@ -71,6 +70,10 @@ /*========== Extern Function Implementations ================================*/ +extern int16_t TSI_GetTemperature(uint16_t adcVoltage_mV) { + return TS_Vis02GetTemperatureFromLut(adcVoltage_mV); +} + /*========== Externalized Static Function Implementations (Unit Test) =======*/ #ifdef UNITY_UNIT_TEST #endif diff --git a/src/app/driver/ts/vishay/ntcle413e2103f102l/vishay_ntcle413e2103f102l.c b/src/app/driver/ts/vishay/ntcle413e2103f102l/vishay_ntcle413e2103f102l.c new file mode 100644 index 00000000..227c7402 --- /dev/null +++ b/src/app/driver/ts/vishay/ntcle413e2103f102l/vishay_ntcle413e2103f102l.c @@ -0,0 +1,175 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file vishay_ntcle413e2103f102l.c + * @author foxBMS Team + * @date 2021-11-03 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup TEMPERATURE_SENSORS + * @prefix TS + * + * @brief Resistive divider used for measuring temperature + * + */ + +/*========== Includes =======================================================*/ +#include "vishay_ntcle413e2103f102l.h" + +#include "fassert.h" +#include "foxmath.h" +#include "temperature_sensor_defs.h" + +#include +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/** LUT filled from higher resistance to lower resistance */ +static const TS_TEMPERATURE_SENSOR_LUT_s ts_ntcle413e2103f102lLut[] = { + {-40, 190953.0f}, {-35, 145953.0f}, {-30, 112440.0f}, {-25, 87285.0f}, {-20, 68260.0f}, {-15, 53762.0f}, + {-10, 42636.0f}, {-5, 34038.0f}, {0, 27348.0f}, {5, 22108.0f}, {10, 17979.0f}, {15, 17706.0f}, + {20, 12904.0f}, {25, 10000.0f}, {30, 8310.8f}, {35, 6941.1f}, {40, 5824.9f}, {45, 4910.6f}, + {50, 4158.3f}, {55, 3536.2f}, {60, 3019.7f}, {65, 2588.8f}, {70, 2228.0f}, {75, 1924.6f}, + {80, 1668.4f}, {85, 1451.3f}, {90, 1266.7f}, {95, 1109.2f}, {100, 974.26f}, {105, 858.33f}}; + +/** size of the #ts_ntcle413e2103f102lLut LUT */ +static const uint16_t ts_ntcle413e2103f102lLutSize = sizeof(ts_ntcle413e2103f102lLut) / + sizeof(TS_TEMPERATURE_SENSOR_LUT_s); + +/*========== Extern Constant and Variable Definitions =======================*/ +/** + * Defines for calculating the ADC voltage on the ends of the operating range. + * The ADC voltage is calculated with the following formula: + * + * V_adc = ( ( V_supply * R_ntc ) / ( R + R_ntc ) ) + * + * Depending on the position of the NTC in the voltage resistor (R_1/R_2), + * different R_ntc values are used for the calculation. + * @{ + */ +#if defined(TS_VISHAY_NTCLE413E2103F102L_POSITION_IN_RESISTOR_DIVIDER_IS_R_1) && \ + (TS_VISHAY_NTCLE413E2103F102L_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == true) +#define TS_VISHAY_NTCLE413E2103F102L_ADC_VOLTAGE_V_MAX_V \ + ((float_t)((TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ntcle413e2103f102lLut[ts_ntcle413e2103f102lLutSize-1u].resistance_Ohm) / (ts_ntcle413e2103f102lLut[ts_ntcle413e2103f102lLutSize-1u].resistance_Ohm+TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) +#define TS_VISHAY_NTCLE413E2103F102L_ADC_VOLTAGE_V_MIN_V \ + ((float_t)((TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ntcle413e2103f102lLut[0u].resistance_Ohm) / (ts_ntcle413e2103f102lLut[0u].resistance_Ohm+TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) +#else /* TS_VISHAY_NTCLE413E2103F102L_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 is false */ +#define TS_VISHAY_NTCLE413E2103F102L_ADC_VOLTAGE_V_MIN_V \ + ((float_t)((TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ntcle413e2103f102lLut[ts_ntcle413e2103f102lLutSize-1u].resistance_Ohm) / (ts_ntcle413e2103f102lLut[ts_ntcle413e2103f102lLutSize-1u].resistance_Ohm+TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) +#define TS_VISHAY_NTCLE413E2103F102L_ADC_VOLTAGE_V_MAX_V \ + ((float_t)((TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ntcle413e2103f102lLut[0u].resistance_Ohm) / (ts_ntcle413e2103f102lLut[0u].resistance_Ohm+TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))) +#endif +/**@}*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ + +extern int16_t TS_Vis02GetTemperatureFromLut(uint16_t adcVoltage_mV) { + int16_t temperature_ddegC = INT16_MIN; + float_t adcVoltage_V = (float_t)adcVoltage_mV / TS_SCALING_FACTOR_1V_IN_MV_FLOAT; /* Convert mV to V */ + + /* Check for valid ADC measurements to prevent undefined behavior */ + if (adcVoltage_V > TS_VISHAY_NTCLE413E2103F102L_ADC_VOLTAGE_V_MAX_V) { + /* Invalid measured ADC voltage -> sensor out of operating range or disconnected/shorted */ + temperature_ddegC = INT16_MIN; + } else if (adcVoltage_V < TS_VISHAY_NTCLE413E2103F102L_ADC_VOLTAGE_V_MIN_V) { + /* Invalid measured ADC voltage -> sensor out of operating range or shorted/disconnected */ + temperature_ddegC = INT16_MAX; + } else { + /* Calculate NTC resistance based on measured ADC voltage */ +#if defined(TS_VISHAY_NTCLE413E2103F102L_POSITION_IN_RESISTOR_DIVIDER_IS_R_1) && \ + (TS_VISHAY_NTCLE413E2103F102L_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == true) + /* formula: R_1 = R_2 * ( ( V_supply / V_adc ) - 1 ) */ + const float_t resistance_Ohm = + TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm * + ((TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V / adcVoltage_V) - 1); +#else /* TS_VISHAY_NTCLE413E2103F102L_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 is false */ + /* formula: R_2 = R_1 * ( V_2 / ( V_supply - V_adc ) ) */ + const float_t resistance_Ohm = + TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm * + (adcVoltage_V / (TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V - adcVoltage_V)); +#endif /* TS_VISHAY_NTCLE413E2103F102L_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 */ + + /* Variables for interpolating LUT value */ + uint16_t between_high = 0; + uint16_t between_low = 0; + for (uint16_t i = 0u; i < ts_ntcle413e2103f102lLutSize; i++) { + if (resistance_Ohm < ts_ntcle413e2103f102lLut[i].resistance_Ohm) { + between_low = i + 1u; + between_high = i; + } + } + + /* Interpolate between LUT values, but do not extrapolate LUT! */ + if (!(((between_high == 0u) && (between_low == 0u)) || /* measured resistance > maximum LUT resistance */ + (between_low >= ts_ntcle413e2103f102lLutSize))) { /* measured resistance < minimum LUT resistance */ + temperature_ddegC = (int16_t)MATH_LinearInterpolation( + ts_ntcle413e2103f102lLut[between_low].resistance_Ohm, + (float_t)ts_ntcle413e2103f102lLut[between_low].temperature_ddegC, + ts_ntcle413e2103f102lLut[between_high].resistance_Ohm, + (float_t)ts_ntcle413e2103f102lLut[between_high].temperature_ddegC, + resistance_Ohm); + } + } + + /* Return temperature based on measured NTC resistance */ + return temperature_ddegC; +} + +extern int16_t TS_Vis02GetTemperatureFromPolynomial(uint16_t adcVoltage_mV) { + (void)adcVoltage_mV; + FAS_ASSERT(FAS_TRAP); + int16_t temperature_ddegC = 0; + /* TODO this is not implemented */ + return temperature_ddegC; +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/application/algorithm/state_estimation/soc/debug/soc_debug_cfg.h b/src/app/driver/ts/vishay/ntcle413e2103f102l/vishay_ntcle413e2103f102l.h similarity index 54% rename from src/app/application/algorithm/state_estimation/soc/debug/soc_debug_cfg.h rename to src/app/driver/ts/vishay/ntcle413e2103f102l/vishay_ntcle413e2103f102l.h index 00affb87..d1eaed7a 100644 --- a/src/app/application/algorithm/state_estimation/soc/debug/soc_debug_cfg.h +++ b/src/app/driver/ts/vishay/ntcle413e2103f102l/vishay_ntcle413e2103f102l.h @@ -40,34 +40,80 @@ */ /** - * @file soc_debug_cfg.h + * @file vishay_ntcle413e2103f102l.h * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOC + * @date 2021-10-29 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup TEMPERATURE_SENSORS + * @prefix TS * - * @brief Header for SOC configuration + * @brief Resistive divider used for measuring temperature * + * V_supply + * --.-- + * | + * +-.-+ + * | | + * | | R_1 + * | | + * +-.-+ + * | + * .--- V_adc + * | + * +-.-+ + * | | + * | | R_2 + * | | + * +-.-+ + * | + * --.-- + * GND */ -#ifndef FOXBMS__SOC_DEBUG_CFG_H_ -#define FOXBMS__SOC_DEBUG_CFG_H_ +#ifndef FOXBMS__VISHAY_NTCLE413E2103F102L_H_ +#define FOXBMS__VISHAY_NTCLE413E2103F102L_H_ /*========== Includes =======================================================*/ #include /*========== Macros and Definitions =========================================*/ +/** + * Position of the NTC in the voltage resistor + * true: NTC is positioned above the voltage tap for the ADC voltage. + * This equals resistor R_1 in the above circuit diagram + * + * false: NTC is positioned below the voltage tap for the ADC voltage. + * This equals resistor R_2 in the above circuit diagram + */ +#define TS_VISHAY_NTCLE413E2103F102L_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 (false) + +/** Resistor divider supply voltage in volt */ +#define TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V (3.0f) /** - * Cell capacity used for SOC calculation, in this case Ah counting - * Specified once according to data sheet of cell usually. + * Resistance value of the other resistor (not the NTC) in the resistor + * divider in Ohm. */ -#define SOX_CELL_CAPACITY (20000.0f) +#define TS_VISHAY_NTCLE413E2103F102L_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm (10000.0f) /*========== Extern Constant and Variable Declarations ======================*/ +/** + * @brief returns temperature based on measured ADC voltage. + * @param adcVoltage_mV voltage in mV + * @return corresponding temperature in deci °C or INT16_MAX/INT16_MIN if + * NTC is shorted or got disconnected. The caller of this functions + * needs to check for these return values to prevent invalid data. + */ +extern int16_t TS_Vis02GetTemperatureFromLut(uint16_t adcVoltage_mV); + +/** + * @brief returns temperature based on measured ADC voltage + * @param adcVoltage_mV voltage in mV + * @return corresponding temperature in deci °C + */ +extern int16_t TS_Vis02GetTemperatureFromPolynomial(uint16_t adcVoltage_mV); /*========== Extern Function Prototypes =====================================*/ @@ -75,4 +121,4 @@ #ifdef UNITY_UNIT_TEST #endif -#endif /* FOXBMS__SOC_DEBUG_CFG_H_ */ +#endif /* FOXBMS__VISHAY_NTCLE413E2103F102L_H_ */ diff --git a/src/app/driver/wscript b/src/app/driver/wscript index 5129c3de..9987f8bc 100644 --- a/src/app/driver/wscript +++ b/src/app/driver/wscript @@ -55,20 +55,32 @@ def build(bld): os.path.join("adc", "adc.c"), os.path.join("can", "can.c"), os.path.join("can", "cbs", "can_helper.c"), + os.path.join("can", "cbs", "rx", "can_cbs_rx_aerosol-sensor.c"), os.path.join("can", "cbs", "rx", "can_cbs_rx_current-sensor.c"), - os.path.join("can", "cbs", "rx", "can_cbs_rx_imd.c"), + os.path.join("can", "cbs", "rx", "can_cbs_rx_imd-response.c"), + os.path.join("can", "cbs", "rx", "can_cbs_rx_imd-info.c"), os.path.join("can", "cbs", "rx", "can_cbs_rx_debug.c"), - os.path.join("can", "cbs", "rx", "can_cbs_rx_state-request.c"), + os.path.join("can", "cbs", "rx", "can_cbs_rx_bms-state-request.c"), os.path.join("can", "cbs", "tx", "can_cbs_tx_cell-temperatures.c"), os.path.join("can", "cbs", "tx", "can_cbs_tx_cell-voltages.c"), os.path.join("can", "cbs", "tx", "can_cbs_tx_debug-response.c"), - os.path.join("can", "cbs", "tx", "can_cbs_tx_limit-values.c"), - os.path.join("can", "cbs", "tx", "can_cbs_tx_minimum-maximum-values.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_crash-dump.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_pack-limits.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_pack-minimum-maximum-values.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_string-minimum-maximum-values.c"), os.path.join("can", "cbs", "tx", "can_cbs_tx_pack-state-estimation.c"), - os.path.join("can", "cbs", "tx", "can_cbs_tx_state.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_bms-state.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_bms-state-details.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_string-state.c"), os.path.join("can", "cbs", "tx", "can_cbs_tx_string-state-estimation.c"), - os.path.join("can", "cbs", "tx", "can_cbs_tx_system-values.c"), - os.path.join("can", "cbs", "tx", "can_cbs_tx_unsupported-message.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_pack-values-p0.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_pack-values-p1.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_string-values-p0.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_string-values-p1.c"), + os.path.join("can", "cbs", "tx", "can_cbs_tx_imd-request.c"), + os.path.join( + "can", "cbs", "tx", "can_cbs_tx_debug-unsupported-multiplexer-values.c" + ), os.path.join("checksum", "checksum.c"), os.path.join("crc", "crc.c"), os.path.join("config", "contactor_cfg.c"), @@ -77,8 +89,6 @@ def build(bld): os.path.join("config", "can_cfg.c"), os.path.join("config", "dma_cfg.c"), os.path.join("config", "fram_cfg.c"), - os.path.join("config", "interlock_cfg.c"), - os.path.join("config", "nxpfs85xx_cfg.c"), os.path.join("config", "pex_cfg.c"), os.path.join("config", "spi_cfg.c"), os.path.join("config", "sps_cfg.c"), @@ -107,9 +117,12 @@ def build(bld): os.path.join("ts", "epcos", "b57251v5103j060", "epcos_b57251v5103j060.c"), os.path.join("ts", "epcos", "b57861s0103f045", "epcos_b57861s0103f045.c"), os.path.join("ts", "fake", "none", "fake_none.c"), - os.path.join("ts", "murata", "ncu15xh103f6sxx", "murata_ncu15xh103f6sxx.c"), + os.path.join("ts", "murata", "ncxxxxh103", "murata_ncxxxxh103.c"), os.path.join("ts", "vishay", "ntcalug01a103g", "vishay_ntcalug01a103g.c"), os.path.join("ts", "vishay", "ntcle317e4103sba", "vishay_ntcle317e4103sba.c"), + os.path.join( + "ts", "vishay", "ntcle413e2103f102l", "vishay_ntcle413e2103f102l.c" + ), os.path.join("ts", "beta.c"), ] includes = [ @@ -146,9 +159,10 @@ def build(bld): os.path.join("ts", "epcos", "b57251v5103j060"), os.path.join("ts", "epcos", "b57861s0103f045"), os.path.join("ts", "fake", "none"), - os.path.join("ts", "murata", "ncu15xh103f6sxx"), + os.path.join("ts", "murata", "ncxxxxh103"), os.path.join("ts", "vishay", "ntcalug01a103g"), os.path.join("ts", "vishay", "ntcle317e4103sba"), + os.path.join("ts", "vishay", "ntcle413e2103f102l"), os.path.join("..", "application", "bal"), os.path.join("..", "application", "bms"), os.path.join("..", "application", "config"), @@ -156,7 +170,7 @@ def build(bld): os.path.join("..", "engine", "config"), os.path.join("..", "engine", "database"), os.path.join("..", "engine", "diag"), - os.path.join("..", "engine", "hwinfo"), + os.path.join("..", "engine", "hw_info"), os.path.join("..", "engine", "sys"), os.path.join("..", "engine", "sys_mon"), os.path.join("..", "main", "include", "config"), diff --git a/src/app/engine/config/database_cfg.c b/src/app/engine/config/database_cfg.c index 1ca24ed8..30f1207f 100644 --- a/src/app/engine/config/database_cfg.c +++ b/src/app/engine/config/database_cfg.c @@ -43,8 +43,8 @@ * @file database_cfg.c * @author foxBMS Team * @date 2015-08-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE_CONFIGURATION * @prefix DATA * @@ -145,8 +145,14 @@ static DATA_BLOCK_RSL_FLAG_s data_blockRsl = {.header.uniqueId = DATA_BLOCK_ID_R /** data block: maximum operating limit violations */ static DATA_BLOCK_MOL_FLAG_s data_blockMol = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; -/** data block: sox */ -static DATA_BLOCK_SOX_s data_blockSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +/** data block: soc */ +static DATA_BLOCK_SOC_s data_blockSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; + +/** data block: soh */ +static DATA_BLOCK_SOH_s data_blockSoh = {.header.uniqueId = DATA_BLOCK_ID_SOH}; + +/** data block: soe */ +static DATA_BLOCK_SOE_s data_blockSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; /** data block: can state request */ static DATA_BLOCK_STATE_REQUEST_s data_blockStaterequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; @@ -171,6 +177,9 @@ static DATA_BLOCK_HTSEN_s data_blockHumidityTemperatureSensor = {.header.uniqueI static DATA_BLOCK_DUMMY_FOR_SELF_TEST_s data_blockDummyForSelfTest = { .header.uniqueId = DATA_BLOCK_ID_DUMMY_FOR_SELF_TEST}; +/** data block: aerosol sensor */ +static DATA_BLOCK_AEROSOL_SENSOR_s data_blockAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; + /** * @brief channel configuration of database (data blocks) * @details all data block managed by database are listed here (address, size, @@ -195,7 +204,9 @@ DATA_BASE_s data_database[] = { {(void *)(&data_blockMsl), sizeof(DATA_BLOCK_MSL_FLAG_s)}, {(void *)(&data_blockRsl), sizeof(DATA_BLOCK_RSL_FLAG_s)}, {(void *)(&data_blockMol), sizeof(DATA_BLOCK_MOL_FLAG_s)}, - {(void *)(&data_blockSox), sizeof(DATA_BLOCK_SOX_s)}, + {(void *)(&data_blockSoc), sizeof(DATA_BLOCK_SOC_s)}, + {(void *)(&data_blockSoh), sizeof(DATA_BLOCK_SOH_s)}, + {(void *)(&data_blockSoe), sizeof(DATA_BLOCK_SOE_s)}, {(void *)(&data_blockStaterequest), sizeof(DATA_BLOCK_STATE_REQUEST_s)}, {(void *)(&data_blockMovingAverage), sizeof(DATA_BLOCK_MOVING_AVERAGE_s)}, {(void *)(&data_blockCellVoltageBase), sizeof(DATA_BLOCK_CELL_VOLTAGE_s)}, @@ -210,6 +221,7 @@ DATA_BASE_s data_database[] = { {(void *)(&data_blockAdcVoltage), sizeof(DATA_BLOCK_ADC_VOLTAGE_s)}, {(void *)(&data_blockHumidityTemperatureSensor), sizeof(DATA_BLOCK_HTSEN_s)}, {(void *)(&data_blockDummyForSelfTest), sizeof(DATA_BLOCK_DUMMY_FOR_SELF_TEST_s)}, + {(void *)(&data_blockAerosolSensor), sizeof(DATA_BLOCK_AEROSOL_SENSOR_s)}, }; /*========== Static Function Prototypes =====================================*/ diff --git a/src/app/engine/config/database_cfg.h b/src/app/engine/config/database_cfg.h index c074178f..f829e6e4 100644 --- a/src/app/engine/config/database_cfg.h +++ b/src/app/engine/config/database_cfg.h @@ -43,8 +43,8 @@ * @file database_cfg.h * @author foxBMS Team * @date 2015-08-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE_CONFIGURATION * @prefix DATA * @@ -76,39 +76,42 @@ typedef struct { /** data block identification numbers */ typedef enum { - DATA_BLOCK_ID_CELL_VOLTAGE, - DATA_BLOCK_ID_CELL_TEMPERATURE, - DATA_BLOCK_ID_MIN_MAX, - DATA_BLOCK_ID_CURRENT_SENSOR, + DATA_BLOCK_ID_ADC_VOLTAGE, + DATA_BLOCK_ID_AEROSOL_SENSOR, + DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE, + DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_REDUNDANCY0, DATA_BLOCK_ID_BALANCING_CONTROL, - DATA_BLOCK_ID_SLAVE_CONTROL, DATA_BLOCK_ID_BALANCING_FEEDBACK_BASE, - DATA_BLOCK_ID_USER_MUX, - DATA_BLOCK_ID_OPEN_WIRE_BASE, - DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE, - DATA_BLOCK_ID_ERROR_STATE, + DATA_BLOCK_ID_BALANCING_FEEDBACK_REDUNDANCY0, + DATA_BLOCK_ID_CELL_TEMPERATURE, + DATA_BLOCK_ID_CELL_TEMPERATURE_BASE, + DATA_BLOCK_ID_CELL_TEMPERATURE_REDUNDANCY0, + DATA_BLOCK_ID_CELL_VOLTAGE, + DATA_BLOCK_ID_CELL_VOLTAGE_BASE, + DATA_BLOCK_ID_CELL_VOLTAGE_REDUNDANCY0, DATA_BLOCK_ID_CONTACTOR_FEEDBACK, + DATA_BLOCK_ID_CURRENT_SENSOR, + DATA_BLOCK_ID_DUMMY_FOR_SELF_TEST, + DATA_BLOCK_ID_ERROR_STATE, + DATA_BLOCK_ID_HTSEN, + DATA_BLOCK_ID_INSULATION_MONITORING, DATA_BLOCK_ID_INTERLOCK_FEEDBACK, - DATA_BLOCK_ID_SOF, - DATA_BLOCK_ID_SYSTEM_STATE, - DATA_BLOCK_ID_MSL_FLAG, - DATA_BLOCK_ID_RSL_FLAG, + DATA_BLOCK_ID_MIN_MAX, DATA_BLOCK_ID_MOL_FLAG, - DATA_BLOCK_ID_SOX, - DATA_BLOCK_ID_STATE_REQUEST, DATA_BLOCK_ID_MOVING_AVERAGE, - DATA_BLOCK_ID_CELL_VOLTAGE_BASE, - DATA_BLOCK_ID_CELL_TEMPERATURE_BASE, - DATA_BLOCK_ID_CELL_VOLTAGE_REDUNDANCY0, - DATA_BLOCK_ID_CELL_TEMPERATURE_REDUNDANCY0, - DATA_BLOCK_ID_BALANCING_FEEDBACK_REDUNDANCY0, - DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_REDUNDANCY0, + DATA_BLOCK_ID_MSL_FLAG, + DATA_BLOCK_ID_OPEN_WIRE_BASE, DATA_BLOCK_ID_OPEN_WIRE_REDUNDANCY0, - DATA_BLOCK_ID_INSULATION_MONITORING, DATA_BLOCK_ID_PACK_VALUES, - DATA_BLOCK_ID_HTSEN, - DATA_BLOCK_ID_ADC_VOLTAGE, - DATA_BLOCK_ID_DUMMY_FOR_SELF_TEST, + DATA_BLOCK_ID_RSL_FLAG, + DATA_BLOCK_ID_SLAVE_CONTROL, + DATA_BLOCK_ID_SOC, + DATA_BLOCK_ID_SOE, + DATA_BLOCK_ID_SOF, + DATA_BLOCK_ID_SOH, + DATA_BLOCK_ID_STATE_REQUEST, + DATA_BLOCK_ID_SYSTEM_STATE, + DATA_BLOCK_ID_USER_MUX, DATA_BLOCK_ID_MAX, /**< DO NOT CHANGE, MUST BE THE LAST ENTRY */ } DATA_BLOCK_ID_e; @@ -129,10 +132,11 @@ typedef struct { /* This struct needs to be at the beginning of every database entry. During * the initialization of a database struct, uniqueId must be set to the * respective database entry representation in enum DATA_BLOCK_ID_e. */ - DATA_BLOCK_HEADER_s header; /*!< Data block header */ - uint8_t state; /*!< for future use */ - int32_t stringVoltage_mV[BS_NR_OF_STRINGS]; /*!< uint: mV */ - int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_CELL_BLOCKS_PER_STRING]; /*!< unit: mV */ + DATA_BLOCK_HEADER_s header; /*!< Data block header */ + uint8_t state; /*!< for future use */ + int32_t stringVoltage_mV[BS_NR_OF_STRINGS]; /*!< uint: mV */ + int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING] + [BS_NR_OF_CELL_BLOCKS_PER_MODULE]; /*!< unit: mV */ uint64_t invalidCellVoltage[BS_NR_OF_STRINGS] [BS_NR_OF_MODULES_PER_STRING]; /*!< bitmask if voltages are valid. 0->valid, 1->invalid */ @@ -146,9 +150,10 @@ typedef struct { /* This struct needs to be at the beginning of every database entry. During * the initialization of a database struct, uniqueId must be set to the * respective database entry representation in enum DATA_BLOCK_ID_e. */ - DATA_BLOCK_HEADER_s header; /*!< Data block header */ - uint8_t state; /*!< for future use */ - int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_TEMP_SENSORS_PER_STRING]; /*!< unit: deci °C */ + DATA_BLOCK_HEADER_s header; /*!< Data block header */ + uint8_t state; /*!< for future use */ + int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING] + [BS_NR_OF_TEMP_SENSORS_PER_MODULE]; /*!< unit: deci °C */ uint16_t invalidCellTemperature [BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]; /*!< bitmask if temperatures are valid. 0->valid, 1->invalid */ uint16_t nrValidTemperatures[BS_NR_OF_STRINGS]; /*!< number of valid temperatures in each string */ @@ -354,6 +359,7 @@ typedef struct { bool openWireDetectedError[BS_NR_OF_STRINGS]; /*!< false -> no error, true -> error */ bool stateRequestTimingViolationError; /*!< false -> no error, true -> error */ bool canRxQueueFullError; /*!< false -> no error, true -> error */ + bool canTxQueueFullError; /*!< false -> no error, true -> error */ bool coinCellLowVoltageError; /*!< false -> no error, true -> error */ bool plausibilityCheckPackVoltageError[BS_NR_OF_STRINGS]; /*!< false -> no error, true -> error */ bool plausibilityCheckCellVoltageError[BS_NR_OF_STRINGS]; /*!< false -> no error, true -> error */ @@ -388,6 +394,7 @@ typedef struct { bool task100msTimingViolationError; /*!< timing violation in 100ms task */ bool task100msAlgoTimingViolationError; /*!< timing violation in 100ms algorithm task */ bool alertFlagSetError; /*!< true: ALERT situation detected, false: everything okay */ + bool aerosolAlert; /*!< true: high aerosol concentration detected */ } DATA_BLOCK_ERROR_STATE_s; /** data block struct of contactor feedback */ @@ -502,7 +509,7 @@ typedef struct { uint8_t pcbUndertemperature[BS_NR_OF_STRINGS]; /*!< 0 -> MOL NOT violated, 1 -> MOL violated */ } DATA_BLOCK_MOL_FLAG_s; -/** data block struct of sox */ +/** data block struct of SOC */ typedef struct { /* This struct needs to be at the beginning of every database entry. During * the initialization of a database struct, uniqueId must be set to the @@ -511,16 +518,32 @@ typedef struct { float_t averageSoc_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= averageSoc <= 100.0 */ float_t minimumSoc_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= minSoc <= 100.0 */ float_t maximumSoc_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= maxSoc <= 100.0 */ - float_t averageSoe_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= averageSoe <= 100.0 */ - float_t minimumSoe_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= minimumSoe <= 100.0 */ - float_t maximumSoe_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= maximumSoe <= 100.0 */ +} DATA_BLOCK_SOC_s; + +/** data block struct of SOH */ +typedef struct { + /* This struct needs to be at the beginning of every database entry. During + * the initialization of a database struct, uniqueId must be set to the + * respective database entry representation in enum DATA_BLOCK_ID_e. */ + DATA_BLOCK_HEADER_s header; /*!< Data block header */ float_t averageSoh_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= averageSoh <= 100.0 */ float_t minimumSoh_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= minimumSoh <= 100.0 */ float_t maximumSoh_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= maximumSoh <= 100.0 */ +} DATA_BLOCK_SOH_s; + +/** data block struct of SOE */ +typedef struct { + /* This struct needs to be at the beginning of every database entry. During + * the initialization of a database struct, uniqueId must be set to the + * respective database entry representation in enum DATA_BLOCK_ID_e. */ + DATA_BLOCK_HEADER_s header; /*!< Data block header */ + float_t averageSoe_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= averageSoe <= 100.0 */ + float_t minimumSoe_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= minimumSoe <= 100.0 */ + float_t maximumSoe_perc[BS_NR_OF_STRINGS]; /*!< 0.0 <= maximumSoe <= 100.0 */ uint32_t maximumSoe_Wh[BS_NR_OF_STRINGS]; /*!< maximum string energy in Wh */ uint32_t averageSoe_Wh[BS_NR_OF_STRINGS]; /*!< average string energy in Wh */ uint32_t minimumSoe_Wh[BS_NR_OF_STRINGS]; /*!< minimum string energy in Wh */ -} DATA_BLOCK_SOX_s; +} DATA_BLOCK_SOE_s; /** data block struct of can state request */ typedef struct { @@ -604,6 +627,20 @@ typedef struct { uint8_t member2; /*!< second member of self-test struct */ } DATA_BLOCK_DUMMY_FOR_SELF_TEST_s; +/** data block struct for the BAS6C-X00 aerosol sensor */ +typedef struct { + /* This struct needs to be at the beginning of every database entry. During + * the initialization of a database struct, uniqueId must be set to the + * respective database entry representation in enum DATA_BLOCK_ID_e. */ + DATA_BLOCK_HEADER_s header; /*!< Data block header */ + uint8_t sensorStatus; /*!< 0: normal, 1: alarm, 2: reserved */ + bool photoelectricError; /*!< true when sensor has photoelectric device fault */ + bool supplyOvervoltageError; /*!< true when voltage supply supplies over voltage */ + bool supplyUndervoltageError; /*!< true when voltage supply supplies under voltage */ + uint16_t particulateMatterConcentration; /*!< particulate matter concentration in microgram/m^3 */ + uint8_t crcCheckCode; /*!< */ +} DATA_BLOCK_AEROSOL_SENSOR_s; + /** array for the database */ extern DATA_BASE_s data_database[DATA_BLOCK_ID_MAX]; diff --git a/src/app/engine/config/diag_cfg.c b/src/app/engine/config/diag_cfg.c index 9e42b350..1272d637 100644 --- a/src/app/engine/config/diag_cfg.c +++ b/src/app/engine/config/diag_cfg.c @@ -43,8 +43,8 @@ * @file diag_cfg.c * @author foxBMS Team * @date 2019-11-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE_CONFIGURATION * @prefix DIAG * @@ -93,7 +93,7 @@ /*========== Macros and Definitions =========================================*/ /** value of #DIAG_ID_MAX (as a define for the pre-processor) */ -#define DIAG_ID_MAX_FOR_INIT (83u) +#define DIAG_ID_MAX_FOR_INIT (85u) FAS_STATIC_ASSERT(DIAG_ID_MAX_FOR_INIT == (uint16_t)DIAG_ID_MAX, "Both values need to be identical."); @@ -183,6 +183,7 @@ DIAG_ID_CFG_s diag_diagnosisIdConfiguration[] = { /* Communication events */ {DIAG_ID_CAN_TIMING, DIAG_ERROR_CAN_TIMING_SENSITIVITY, DIAG_FATAL_ERROR, DIAG_DELAY_CAN_TIMING_ms, DIAG_RECORDING_ENABLED, DIAG_CAN_TIMING, DIAG_ErrorCanTiming}, {DIAG_ID_CAN_RX_QUEUE_FULL, DIAG_ERROR_SENSITIVITY_FIRST_EVENT, DIAG_WARNING, DIAG_DELAY_DISCARDED, DIAG_RECORDING_ENABLED, DIAG_EVALUATION_ENABLED, DIAG_ErrorCanRxQueueFull}, + {DIAG_ID_CAN_TX_QUEUE_FULL, DIAG_ERROR_SENSITIVITY_FIRST_EVENT, DIAG_WARNING, DIAG_DELAY_DISCARDED, DIAG_RECORDING_ENABLED, DIAG_EVALUATION_ENABLED, DIAG_ErrorCanTxQueueFull}, {DIAG_ID_CAN_CC_RESPONDING, DIAG_ERROR_CAN_TIMING_CC_SENSITIVITY, DIAG_FATAL_ERROR, DIAG_DELAY_EC_CC_TIMING_ms, DIAG_RECORDING_ENABLED, DIAG_CAN_SENSOR_PRESENT, DIAG_ErrorCurrentSensor}, {DIAG_ID_CAN_EC_RESPONDING, DIAG_ERROR_CAN_TIMING_CC_SENSITIVITY, DIAG_FATAL_ERROR, DIAG_DELAY_EC_CC_TIMING_ms, DIAG_RECORDING_ENABLED, DIAG_CAN_SENSOR_PRESENT, DIAG_ErrorCurrentSensor}, {DIAG_ID_CURRENT_SENSOR_RESPONDING, DIAG_ERROR_CAN_SENSOR_SENSITIVITY, DIAG_FATAL_ERROR, DIAG_DELAY_CURRENT_SENSOR_ms, DIAG_RECORDING_ENABLED, DIAG_CAN_SENSOR_PRESENT, DIAG_ErrorCurrentSensor}, @@ -231,6 +232,8 @@ DIAG_ID_CFG_s diag_diagnosisIdConfiguration[] = { {DIAG_ID_FRAM_READ_CRC_ERROR, DIAG_ERROR_SENSITIVITY_HIGH, DIAG_INFO, DIAG_NO_DELAY, DIAG_RECORDING_ENABLED, DIAG_EVALUATION_ENABLED, DIAG_FramError}, {DIAG_ID_ALERT_MODE, DIAG_ERROR_SENSITIVITY_HIGH, DIAG_FATAL_ERROR, DIAG_NO_DELAY, DIAG_RECORDING_ENABLED, DIAG_EVALUATION_ENABLED, DIAG_AlertFlag}, + + {DIAG_ID_AEROSOL_ALERT, DIAG_ERROR_SENSITIVITY_HIGH, DIAG_WARNING, DIAG_NO_DELAY, DIAG_RECORDING_ENABLED, DIAG_EVALUATION_ENABLED, DIAG_AerosolAlert}, /* clang-format on */ }; diff --git a/src/app/engine/config/diag_cfg.h b/src/app/engine/config/diag_cfg.h index 2ce9a0cf..7c0530f9 100644 --- a/src/app/engine/config/diag_cfg.h +++ b/src/app/engine/config/diag_cfg.h @@ -43,8 +43,8 @@ * @file diag_cfg.h * @author foxBMS Team * @date 2019-11-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE_CONFIGURATION * @prefix DIAG * @@ -183,6 +183,7 @@ typedef enum { DIAG_ID_AFE_CONFIG, /*!< the AFE driver has recognized a configuration error */ DIAG_ID_CAN_TIMING, /*!< the BMS does not receive CAN messages or they are not inside the expected timing constraints */ DIAG_ID_CAN_RX_QUEUE_FULL, /*!< the reception queue of the driver is full; no new messages can be received */ + DIAG_ID_CAN_TX_QUEUE_FULL, /*!< the transmission queue of the driver is full; all new messages will be lost */ DIAG_ID_CAN_CC_RESPONDING, /*!< current counter measurements on the CAN bus are missing or not inside expected timing constraints */ DIAG_ID_CAN_EC_RESPONDING, /*!< energy counter measurements on the CAN bus are missing or not inside expected timing constraints */ DIAG_ID_CURRENT_SENSOR_RESPONDING, /*!< current sensor measurements on the CAN bus are missing or not inside expected timing constraints */ @@ -256,8 +257,9 @@ typedef enum { DIAG_ID_RTC_CLOCK_INTEGRITY_ERROR, /*!< clock integrity not garanteed error in RTC IC */ DIAG_ID_RTC_BATTERY_LOW_ERROR, /*!< RTC IC battery low flag set */ DIAG_ID_FRAM_READ_CRC_ERROR, /*!< CRC does not match when reading from the FRAM */ - DIAG_ID_ALERT_MODE, /*!< Critical error while opening the contactors. Fuse has not triggered */ - DIAG_ID_MAX, /*!< MAX indicator - do not change */ + DIAG_ID_ALERT_MODE, /*!< Critical error while opening the contactors. Fuse has not triggered */ + DIAG_ID_AEROSOL_ALERT, /*!< high aerosol concentration detected */ + DIAG_ID_MAX, /*!< MAX indicator - do not change */ } DIAG_ID_e; /** diagnosis check result (event) */ diff --git a/src/app/engine/config/sys_cfg.c b/src/app/engine/config/sys_cfg.c index 2eb1fc2f..83e43e4b 100644 --- a/src/app/engine/config/sys_cfg.c +++ b/src/app/engine/config/sys_cfg.c @@ -43,8 +43,8 @@ * @file sys_cfg.c * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE_CONFIGURATION * @prefix SYS * @@ -75,6 +75,7 @@ void SYS_SendBootMessage(void) { /* The magic boot sequence on CAN is: - : 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0x0F - : + - : - : - : - : @@ -86,6 +87,9 @@ void SYS_SendBootMessage(void) { if (CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_TRANSMIT_BMS_VERSION_INFO) != STD_OK) { FAS_ASSERT(FAS_TRAP); } + if (CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_TRANSMIT_COMMIT_HASH) != STD_OK) { + FAS_ASSERT(FAS_TRAP); + } if (CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_TRANSMIT_MCU_UNIQUE_DIE_ID) != STD_OK) { FAS_ASSERT(FAS_TRAP); } diff --git a/src/app/engine/config/sys_cfg.h b/src/app/engine/config/sys_cfg.h index dcfe15bd..786087f4 100644 --- a/src/app/engine/config/sys_cfg.h +++ b/src/app/engine/config/sys_cfg.h @@ -43,8 +43,8 @@ * @file sys_cfg.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE_CONFIGURATION * @prefix SYS * @@ -70,13 +70,13 @@ #define SYS_TASK_CYCLE_CONTEXT_MS (10u) /** - * SYS statemachine short time definition in #SYS_Trigger() calls until next + * SYS state machine short time definition in #SYS_Trigger() calls until next * state/substate is processed */ #define SYS_FSM_SHORT_TIME (1u) /** - * SYS statemachine medium time definition in #SYS_Trigger() calls until next + * SYS state machine medium time definition in #SYS_Trigger() calls until next * state/substate is processed */ #define SYS_FSM_MEDIUM_TIME (5u) diff --git a/src/app/engine/config/sys_mon_cfg.c b/src/app/engine/config/sys_mon_cfg.c index 89955ad8..aa93b5f0 100644 --- a/src/app/engine/config/sys_mon_cfg.c +++ b/src/app/engine/config/sys_mon_cfg.c @@ -43,8 +43,8 @@ * @file sys_mon_cfg.c * @author foxBMS Team * @date 2019-11-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE_CONFIGURATION * @prefix SYSM * @@ -127,6 +127,6 @@ static void SYSM_DummyCallback(SYSM_TASK_ID_e taskId) { /*========== Externalized Static Function Implementations (Unit Test) =======*/ #ifdef UNITY_UNIT_TEST void TEST_SYSM_DummyCallback(SYSM_TASK_ID_e taskId) { - return SYSM_DummyCallback(taskId); + SYSM_DummyCallback(taskId); } #endif diff --git a/src/app/engine/config/sys_mon_cfg.h b/src/app/engine/config/sys_mon_cfg.h index b7a1edf5..55513971 100644 --- a/src/app/engine/config/sys_mon_cfg.h +++ b/src/app/engine/config/sys_mon_cfg.h @@ -43,8 +43,8 @@ * @file sys_mon_cfg.h * @author foxBMS Team * @date 2019-11-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE_CONFIGURATION * @prefix SYSM * diff --git a/src/app/engine/database/database.c b/src/app/engine/database/database.c index 4f69ff8e..ca7cb73a 100644 --- a/src/app/engine/database/database.c +++ b/src/app/engine/database/database.c @@ -43,8 +43,8 @@ * @file database.c * @author foxBMS Team * @date 2015-08-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DATA * diff --git a/src/app/engine/database/database.h b/src/app/engine/database/database.h index f78a7394..6ca31395 100644 --- a/src/app/engine/database/database.h +++ b/src/app/engine/database/database.h @@ -43,8 +43,8 @@ * @file database.h * @author foxBMS Team * @date 2015-08-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DATA * diff --git a/src/app/engine/database/database_helper.c b/src/app/engine/database/database_helper.c index b796db22..574b2033 100644 --- a/src/app/engine/database/database_helper.c +++ b/src/app/engine/database/database_helper.c @@ -43,8 +43,8 @@ * @file database_helper.c * @author foxBMS Team * @date 2021-05-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DATA * diff --git a/src/app/engine/database/database_helper.h b/src/app/engine/database/database_helper.h index 8a76b237..31ef82d4 100644 --- a/src/app/engine/database/database_helper.h +++ b/src/app/engine/database/database_helper.h @@ -43,8 +43,8 @@ * @file database_helper.h * @author foxBMS Team * @date 2021-05-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DATA * diff --git a/src/app/engine/diag/cbs/diag_cbs.h b/src/app/engine/diag/cbs/diag_cbs.h index 64fe0f65..941af501 100644 --- a/src/app/engine/diag/cbs/diag_cbs.h +++ b/src/app/engine/diag/cbs/diag_cbs.h @@ -43,8 +43,8 @@ * @file diag_cbs.h * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * @@ -263,7 +263,7 @@ extern void DIAG_ErrorCanTiming( uint32_t data); /** - * @brief diagnosis callback function for CAN related events + * @brief diagnosis callback function for CAN Rx related events * @param[in] diagId ID of diag entry * @param[in] event #DIAG_EVENT_e * @param[in] kpkDiagShim shim to the database entries @@ -275,6 +275,20 @@ extern void DIAG_ErrorCanRxQueueFull( const DIAG_DATABASE_SHIM_s *const kpkDiagShim, uint32_t data); +/** + * @brief diagnosis callback function for CAN Tx related events + * @param[in] diagId ID of diag entry + * @param[in] event #DIAG_EVENT_e + * @param[in] kpkDiagShim shim to the database entries + * @param[in] data data + */ + +extern void DIAG_ErrorCanTxQueueFull( + DIAG_ID_e diagId, + DIAG_EVENT_e event, + const DIAG_DATABASE_SHIM_s *const kpkDiagShim, + uint32_t data); + /** * @brief diagnosis callback function for AFE module related events * @param[in] diagId ID of diag entry @@ -483,6 +497,19 @@ extern void DIAG_PrechargeProcess( const DIAG_DATABASE_SHIM_s *const kpkDiagShim, uint32_t stringNumber); +/** + * @brief diagnosis callback function for aerosol alert + * @param[in] diagId ID of diag entry + * @param[in] event OK, NOK or RESET + * @param[in] kpkDiagShim shim to the database entries + * @param[in] data not relevant + */ +extern void DIAG_AerosolAlert( + DIAG_ID_e diagId, + DIAG_EVENT_e event, + const DIAG_DATABASE_SHIM_s *const kpkDiagShim, + uint32_t data); + /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ #ifdef UNITY_UNIT_TEST #endif diff --git a/src/app/engine/diag/cbs/diag_cbs_aerosol-sensor.c b/src/app/engine/diag/cbs/diag_cbs_aerosol-sensor.c new file mode 100644 index 00000000..75909f78 --- /dev/null +++ b/src/app/engine/diag/cbs/diag_cbs_aerosol-sensor.c @@ -0,0 +1,95 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file diag_cbs_aerosol-sensor.c + * @author foxBMS Team + * @date 2023-09-06 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup ENGINE + * @prefix DIAG + * + * @brief Diagnosis driver implementation + * @details TODO + */ + +/*========== Includes =======================================================*/ +#include "diag_cbs.h" +#include "fassert.h" +#include "fstd_types.h" + +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ +void DIAG_AerosolAlert( + DIAG_ID_e diagId, + DIAG_EVENT_e event, + const DIAG_DATABASE_SHIM_s *const kpkDiagShim, + uint32_t data) { + FAS_ASSERT(diagId == DIAG_ID_AEROSOL_ALERT); + FAS_ASSERT((event == DIAG_EVENT_OK) || (event == DIAG_EVENT_NOT_OK) || (event == DIAG_EVENT_RESET)); + FAS_ASSERT(kpkDiagShim != NULL_PTR); + /* AXIVION Routine Generic-MissingParameterAssert: data: parameter not used -> accept everything */ + (void)data; /* data is unused */ + + if (event == DIAG_EVENT_RESET) { + kpkDiagShim->pTableError->aerosolAlert = false; + } else if (event == DIAG_EVENT_NOT_OK) { + kpkDiagShim->pTableError->aerosolAlert = true; + } else { + /* nothing to to */ + } +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/src/app/engine/diag/cbs/diag_cbs_afe.c b/src/app/engine/diag/cbs/diag_cbs_afe.c index 5d0b48c9..0c50782f 100644 --- a/src/app/engine/diag/cbs/diag_cbs_afe.c +++ b/src/app/engine/diag/cbs/diag_cbs_afe.c @@ -43,8 +43,8 @@ * @file diag_cbs_afe.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_bms.c b/src/app/engine/diag/cbs/diag_cbs_bms.c index 3bff8d8b..f6d7d22a 100644 --- a/src/app/engine/diag/cbs/diag_cbs_bms.c +++ b/src/app/engine/diag/cbs/diag_cbs_bms.c @@ -43,8 +43,8 @@ * @file diag_cbs_bms.c * @author foxBMS Team * @date 2022-07-26 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup APPLICATION * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_can.c b/src/app/engine/diag/cbs/diag_cbs_can.c index f264e6e0..050c6121 100644 --- a/src/app/engine/diag/cbs/diag_cbs_can.c +++ b/src/app/engine/diag/cbs/diag_cbs_can.c @@ -43,8 +43,8 @@ * @file diag_cbs_can.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * @@ -106,6 +106,25 @@ extern void DIAG_ErrorCanRxQueueFull( } } +extern void DIAG_ErrorCanTxQueueFull( + DIAG_ID_e diagId, + DIAG_EVENT_e event, + const DIAG_DATABASE_SHIM_s *const kpkDiagShim, + uint32_t data) { + /* AXIVION Routine MisraC2012-2.7: data: Parameter from function prototype */ + /* AXIVION Routine Generic-MissingParameterAssert: data: parameter not used */ + FAS_ASSERT(diagId == DIAG_ID_CAN_TX_QUEUE_FULL); + FAS_ASSERT((event == DIAG_EVENT_OK) || (event == DIAG_EVENT_NOT_OK) || (event == DIAG_EVENT_RESET)); + FAS_ASSERT(kpkDiagShim != NULL_PTR); + + if (event == DIAG_EVENT_RESET) { + kpkDiagShim->pTableError->canTxQueueFullError = false; + } + if (event == DIAG_EVENT_NOT_OK) { + kpkDiagShim->pTableError->canTxQueueFullError = true; + } +} + /*========== Externalized Static Function Implementations (Unit Test) =======*/ #ifdef UNITY_UNIT_TEST #endif diff --git a/src/app/engine/diag/cbs/diag_cbs_contactor.c b/src/app/engine/diag/cbs/diag_cbs_contactor.c index 36a51efb..ea838c9d 100644 --- a/src/app/engine/diag/cbs/diag_cbs_contactor.c +++ b/src/app/engine/diag/cbs/diag_cbs_contactor.c @@ -43,8 +43,8 @@ * @file diag_cbs_contactor.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_current-sensor.c b/src/app/engine/diag/cbs/diag_cbs_current-sensor.c index afee3c01..0c433bfd 100644 --- a/src/app/engine/diag/cbs/diag_cbs_current-sensor.c +++ b/src/app/engine/diag/cbs/diag_cbs_current-sensor.c @@ -43,8 +43,8 @@ * @file diag_cbs_current-sensor.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_current.c b/src/app/engine/diag/cbs/diag_cbs_current.c index f94edce7..0dbf052e 100644 --- a/src/app/engine/diag/cbs/diag_cbs_current.c +++ b/src/app/engine/diag/cbs/diag_cbs_current.c @@ -43,8 +43,8 @@ * @file diag_cbs_current.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_deep-discharge.c b/src/app/engine/diag/cbs/diag_cbs_deep-discharge.c index 6bf3fce2..9a2fb913 100644 --- a/src/app/engine/diag/cbs/diag_cbs_deep-discharge.c +++ b/src/app/engine/diag/cbs/diag_cbs_deep-discharge.c @@ -43,8 +43,8 @@ * @file diag_cbs_deep-discharge.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_dummy.c b/src/app/engine/diag/cbs/diag_cbs_dummy.c index 0268d6a0..62a29982 100644 --- a/src/app/engine/diag/cbs/diag_cbs_dummy.c +++ b/src/app/engine/diag/cbs/diag_cbs_dummy.c @@ -43,8 +43,8 @@ * @file diag_cbs_dummy.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_fram.c b/src/app/engine/diag/cbs/diag_cbs_fram.c index d4ad87aa..81ef067b 100644 --- a/src/app/engine/diag/cbs/diag_cbs_fram.c +++ b/src/app/engine/diag/cbs/diag_cbs_fram.c @@ -43,8 +43,8 @@ * @file diag_cbs_fram.c * @author foxBMS Team * @date 2022-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_i2c.c b/src/app/engine/diag/cbs/diag_cbs_i2c.c index 57cfe71c..1b2b67ae 100644 --- a/src/app/engine/diag/cbs/diag_cbs_i2c.c +++ b/src/app/engine/diag/cbs/diag_cbs_i2c.c @@ -43,8 +43,8 @@ * @file diag_cbs_i2c.c * @author foxBMS Team * @date 2021-09-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_insulation.c b/src/app/engine/diag/cbs/diag_cbs_insulation.c index f203a1d2..2eef6a72 100644 --- a/src/app/engine/diag/cbs/diag_cbs_insulation.c +++ b/src/app/engine/diag/cbs/diag_cbs_insulation.c @@ -43,8 +43,8 @@ * @file diag_cbs_insulation.c * @author foxBMS Team * @date 2021-02-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_interlock.c b/src/app/engine/diag/cbs/diag_cbs_interlock.c index 0950abc5..d577190f 100644 --- a/src/app/engine/diag/cbs/diag_cbs_interlock.c +++ b/src/app/engine/diag/cbs/diag_cbs_interlock.c @@ -43,8 +43,8 @@ * @file diag_cbs_interlock.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_plausibility.c b/src/app/engine/diag/cbs/diag_cbs_plausibility.c index 621ca05a..b7729d0e 100644 --- a/src/app/engine/diag/cbs/diag_cbs_plausibility.c +++ b/src/app/engine/diag/cbs/diag_cbs_plausibility.c @@ -43,8 +43,8 @@ * @file diag_cbs_plausibility.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_power-measurement.c b/src/app/engine/diag/cbs/diag_cbs_power-measurement.c index 9b30757e..2069c1c2 100644 --- a/src/app/engine/diag/cbs/diag_cbs_power-measurement.c +++ b/src/app/engine/diag/cbs/diag_cbs_power-measurement.c @@ -43,8 +43,8 @@ * @file diag_cbs_power-measurement.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_rtc.c b/src/app/engine/diag/cbs/diag_cbs_rtc.c index 44f5e2e0..6de3925c 100644 --- a/src/app/engine/diag/cbs/diag_cbs_rtc.c +++ b/src/app/engine/diag/cbs/diag_cbs_rtc.c @@ -43,8 +43,8 @@ * @file diag_cbs_rtc.c * @author foxBMS Team * @date 2022-11-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_sbc.c b/src/app/engine/diag/cbs/diag_cbs_sbc.c index b43c4d0c..ac8a1657 100644 --- a/src/app/engine/diag/cbs/diag_cbs_sbc.c +++ b/src/app/engine/diag/cbs/diag_cbs_sbc.c @@ -43,8 +43,8 @@ * @file diag_cbs_sbc.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_sys-mon.c b/src/app/engine/diag/cbs/diag_cbs_sys-mon.c index b293143c..38319692 100644 --- a/src/app/engine/diag/cbs/diag_cbs_sys-mon.c +++ b/src/app/engine/diag/cbs/diag_cbs_sys-mon.c @@ -43,8 +43,8 @@ * @file diag_cbs_sys-mon.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_temperature.c b/src/app/engine/diag/cbs/diag_cbs_temperature.c index 333ca926..c114be5a 100644 --- a/src/app/engine/diag/cbs/diag_cbs_temperature.c +++ b/src/app/engine/diag/cbs/diag_cbs_temperature.c @@ -43,8 +43,8 @@ * @file diag_cbs_temperature.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/cbs/diag_cbs_voltage.c b/src/app/engine/diag/cbs/diag_cbs_voltage.c index 91fa5193..7c7d0d67 100644 --- a/src/app/engine/diag/cbs/diag_cbs_voltage.c +++ b/src/app/engine/diag/cbs/diag_cbs_voltage.c @@ -43,8 +43,8 @@ * @file diag_cbs_voltage.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/diag.c b/src/app/engine/diag/diag.c index ab742965..3d45303c 100644 --- a/src/app/engine/diag/diag.c +++ b/src/app/engine/diag/diag.c @@ -43,8 +43,8 @@ * @file diag.c * @author foxBMS Team * @date 2019-11-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/diag/diag.h b/src/app/engine/diag/diag.h index c2c0f2aa..106768e4 100644 --- a/src/app/engine/diag/diag.h +++ b/src/app/engine/diag/diag.h @@ -43,8 +43,8 @@ * @file diag.h * @author foxBMS Team * @date 2019-11-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix DIAG * diff --git a/src/app/engine/hwinfo/masterinfo.c b/src/app/engine/hw_info/master_info.c similarity index 97% rename from src/app/engine/hwinfo/masterinfo.c rename to src/app/engine/hw_info/master_info.c index 385885aa..fb459fba 100644 --- a/src/app/engine/hwinfo/masterinfo.c +++ b/src/app/engine/hw_info/master_info.c @@ -40,11 +40,11 @@ */ /** - * @file masterinfo.c + * @file master_info.c * @author foxBMS Team * @date 2020-07-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL * @prefix MINFO * @@ -56,7 +56,7 @@ */ /*========== Includes =======================================================*/ -#include "masterinfo.h" +#include "master_info.h" #include "fassert.h" diff --git a/src/app/engine/hwinfo/masterinfo.h b/src/app/engine/hw_info/master_info.h similarity index 95% rename from src/app/engine/hwinfo/masterinfo.h rename to src/app/engine/hw_info/master_info.h index 960ccd8a..26a96f25 100644 --- a/src/app/engine/hwinfo/masterinfo.h +++ b/src/app/engine/hw_info/master_info.h @@ -40,11 +40,11 @@ */ /** - * @file masterinfo.h + * @file master_info.h * @author foxBMS Team * @date 2020-07-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL * @prefix MINFO * @@ -55,8 +55,8 @@ * */ -#ifndef FOXBMS__MASTERINFO_H_ -#define FOXBMS__MASTERINFO_H_ +#ifndef FOXBMS__MASTER_INFO_H_ +#define FOXBMS__MASTER_INFO_H_ /*========== Includes =======================================================*/ #include "HL_system.h" @@ -113,4 +113,4 @@ MINFO_DEBUG_PROBE_CONNECTION_STATE_e MINFO_GetDebugProbeConnectionState(void); #ifdef UNITY_UNIT_TEST #endif -#endif /* FOXBMS__MASTERINFO_H_ */ +#endif /* FOXBMS__MASTER_INFO_H_ */ diff --git a/src/app/engine/sys/reset.c b/src/app/engine/sys/reset.c index d65485ab..287827f4 100644 --- a/src/app/engine/sys/reset.c +++ b/src/app/engine/sys/reset.c @@ -43,8 +43,8 @@ * @file reset.c * @author foxBMS Team * @date 2022-11-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix SYS * diff --git a/src/app/engine/sys/reset.h b/src/app/engine/sys/reset.h index 861bb6f8..af1bbbb2 100644 --- a/src/app/engine/sys/reset.h +++ b/src/app/engine/sys/reset.h @@ -43,8 +43,8 @@ * @file reset.h * @author foxBMS Team * @date 2022-11-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix SYS * diff --git a/src/app/engine/sys/sys.c b/src/app/engine/sys/sys.c index c55ad233..cf0228b0 100644 --- a/src/app/engine/sys/sys.c +++ b/src/app/engine/sys/sys.c @@ -43,8 +43,8 @@ * @file sys.c * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix SYS * @@ -124,29 +124,6 @@ SYS_STATE_s sys_state = { */ static SYS_CHECK_MULTIPLE_CALLS_e SYS_CheckMultipleCalls(SYS_STATE_s *pSystemState); -/** - * @brief Sets the next state, the next substate and the timer value - * of the state variable. - * @param pSystemState state of the example state machine - * @param nextState state to be transferred into - * @param nextSubstate substate to be transferred into - * @param idleTime wait time for the state machine - */ -static void SYS_SetState( - SYS_STATE_s *pSystemState, - SYS_FSM_STATES_e nextState, - SYS_FSM_SUBSTATES_e nextSubstate, - uint16_t idleTime); - -/** - * @brief Sets the next substate and the timer value - * of the state variable. - * @param pSystemState state of the example state machine - * @param nextSubstate substate to be transferred into - * @param idleTime wait time for the state machine - */ -static void SYS_SetSubstate(SYS_STATE_s *pSystemState, SYS_FSM_SUBSTATES_e nextSubstate, uint16_t idleTime); - /** * @brief Defines the state transitions * @details This function contains the implementation of the state @@ -175,28 +152,6 @@ static SYS_CHECK_MULTIPLE_CALLS_e SYS_CheckMultipleCalls(SYS_STATE_s *pSystemSta return multipleCalls; } -#pragma diag_push -#pragma diag_suppress 179 -#pragma WEAK(SYS_SetState) -static void SYS_SetState( - SYS_STATE_s *pSystemState, - SYS_FSM_STATES_e nextState, - SYS_FSM_SUBSTATES_e nextSubstate, - uint16_t idleTime) { - FAS_ASSERT(pSystemState != NULL_PTR); - - pSystemState->timer = idleTime; -} -#pragma diag_pop - -#pragma diag_push -#pragma diag_suppress 179 -#pragma WEAK(SYS_SetSubstate) -static void SYS_SetSubstate(SYS_STATE_s *pSystemState, SYS_FSM_SUBSTATES_e nextSubstate, uint16_t idleTime) { - FAS_ASSERT(pSystemState != NULL_PTR); -} -#pragma diag_push - static STD_RETURN_TYPE_e SYS_RunStateMachine(SYS_STATE_s *pSystemState) { STD_RETURN_TYPE_e ranStateMachine = STD_OK; diff --git a/src/app/engine/sys/sys.h b/src/app/engine/sys/sys.h index f7af0df8..29070012 100644 --- a/src/app/engine/sys/sys.h +++ b/src/app/engine/sys/sys.h @@ -43,8 +43,8 @@ * @file sys.h * @author foxBMS Team * @date 2020-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix SYS * @@ -78,7 +78,7 @@ typedef enum { SYS_FSM_STATE_HAS_NEVER_RUN, /*!< never run state - always the second state */ SYS_FSM_STATE_UNINITIALIZED, /*!< uninitialized state */ SYS_FSM_STATE_INITIALIZATION, /*!< initializing the state machine */ - SYS_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ + SYS_FSM_STATE_RUNNING, /*!< operational mode of the state machine */ SYS_FSM_STATE_ERROR, /*!< state for error processing */ } SYS_FSM_STATES_e; @@ -146,14 +146,14 @@ typedef enum { SYS_CURRENT_SENSOR_PRESENCE_ERROR, /*!< Substate error if first measurement cycle does not complete */ } SYS_STATEMACH_SUB_e; -/** State requests for the SYS statemachine */ +/** State requests for the SYS state machine */ typedef enum { SYS_STATE_INITIALIZATION_REQUEST, /*!< initialization request */ SYS_STATE_ERROR_REQUEST, /*!< error state requested */ SYS_STATE_NO_REQUEST, /*!< no request */ } SYS_STATE_REQUEST_e; -/** Possible return values when state requests are made to the SYS statemachine */ +/** Possible return values when state requests are made to the SYS state machine */ typedef enum { SYS_OK, /*!< sys --> ok */ SYS_BUSY_OK, /*!< sys busy --> ok */ @@ -170,7 +170,7 @@ typedef enum { typedef struct { uint16_t timer; /*!< time in ms before the state machine processes the next state, e.g. in counts of 1ms */ SYS_STATE_REQUEST_e stateRequest; /*!< current state request made to the state machine */ - SYS_STATEMACH_e state; /*!< state of Driver State Machine */ + SYS_STATEMACH_e state; /*!< state of driver state machine */ SYS_STATEMACH_SUB_e substate; /*!< current substate of the state machine */ SYS_STATEMACH_e lastState; /*!< previous state of the state machine */ SYS_STATEMACH_SUB_e lastSubstate; /*!< previous substate of the state machine */ diff --git a/src/app/engine/sys_mon/sys_mon.c b/src/app/engine/sys_mon/sys_mon.c index acbbb64c..1cc460ab 100644 --- a/src/app/engine/sys_mon/sys_mon.c +++ b/src/app/engine/sys_mon/sys_mon.c @@ -43,8 +43,8 @@ * @file sys_mon.c * @author foxBMS Team * @date 2019-11-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix SYSM * diff --git a/src/app/engine/sys_mon/sys_mon.h b/src/app/engine/sys_mon/sys_mon.h index 1e2e9efd..05c38a36 100644 --- a/src/app/engine/sys_mon/sys_mon.h +++ b/src/app/engine/sys_mon/sys_mon.h @@ -43,8 +43,8 @@ * @file sys_mon.h * @author foxBMS Team * @date 2019-11-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ENGINE * @prefix SYSM * diff --git a/src/app/engine/wscript b/src/app/engine/wscript index f3b18476..5f987458 100644 --- a/src/app/engine/wscript +++ b/src/app/engine/wscript @@ -55,6 +55,7 @@ def build(bld): os.path.join("config", "sys_mon_cfg.c"), os.path.join("database", "database.c"), os.path.join("database", "database_helper.c"), + os.path.join("diag", "cbs", "diag_cbs_aerosol-sensor.c"), os.path.join("diag", "cbs", "diag_cbs_bms.c"), os.path.join("diag", "cbs", "diag_cbs_can.c"), os.path.join("diag", "cbs", "diag_cbs_contactor.c"), @@ -75,7 +76,7 @@ def build(bld): os.path.join("diag", "cbs", "diag_cbs_temperature.c"), os.path.join("diag", "cbs", "diag_cbs_voltage.c"), os.path.join("diag", "diag.c"), - os.path.join("hwinfo", "masterinfo.c"), + os.path.join("hw_info", "master_info.c"), os.path.join("sys", "reset.c"), os.path.join("sys", "sys.c"), os.path.join("sys_mon", "sys_mon.c"), diff --git a/src/app/main/fassert.c b/src/app/main/fassert.c index 066d7693..b56d2315 100644 --- a/src/app/main/fassert.c +++ b/src/app/main/fassert.c @@ -43,8 +43,8 @@ * @file fassert.c * @author foxBMS Team * @date 2020-05-26 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ASSERT * @prefix FAS * diff --git a/src/app/main/fstartup.c b/src/app/main/fstartup.c index 441c10e9..e3b547f8 100644 --- a/src/app/main/fstartup.c +++ b/src/app/main/fstartup.c @@ -43,8 +43,8 @@ * @file fstartup.c * @author foxBMS Team * @date 2020-07-09 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL * @prefix STU * diff --git a/src/app/main/include/config/version_cfg.h b/src/app/main/include/config/version_cfg.h index 523b650d..4d4c49f3 100644 --- a/src/app/main/include/config/version_cfg.h +++ b/src/app/main/include/config/version_cfg.h @@ -43,8 +43,8 @@ * @file version_cfg.h * @author foxBMS Team * @date 2021-07-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL * @prefix VER * diff --git a/src/app/main/include/fassert.h b/src/app/main/include/fassert.h index ce5b3c1f..dd5891d1 100644 --- a/src/app/main/include/fassert.h +++ b/src/app/main/include/fassert.h @@ -43,8 +43,8 @@ * @file fassert.h * @author foxBMS Team * @date 2020-03-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup ASSERT * @prefix FAS * @@ -183,7 +183,8 @@ extern void FAS_StoreAssertLocation(uint32_t *pc, uint32_t line); static inline void FAS_InfiniteLoop(void) { /* disable IRQ interrupts */ FAS_DisableInterrupts(); - /* AXIVION Next Codeline Style MisraC2012-2.2: an infinite loop is intended to stop further code execution */ + /* AXIVION Next Codeline Style MisraC2012-2.2 Generic-NoEmptyLoops: an + infinite loop is intended to stop further code execution */ while (true) { /* Stay here until watchdog reset happens */ } } diff --git a/src/app/main/include/fstartup.h b/src/app/main/include/fstartup.h index b191d085..8db2c1ce 100644 --- a/src/app/main/include/fstartup.h +++ b/src/app/main/include/fstartup.h @@ -43,8 +43,8 @@ * @file fstartup.h * @author foxBMS Team * @date 2022-05-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL * @prefix STU * diff --git a/src/app/main/include/fstd_types.h b/src/app/main/include/fstd_types.h index 37f74598..e56b7ed1 100644 --- a/src/app/main/include/fstd_types.h +++ b/src/app/main/include/fstd_types.h @@ -43,8 +43,8 @@ * @file fstd_types.h * @author foxBMS Team * @date 2015-12-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL_CONF * @prefix STD * diff --git a/src/app/main/include/fsystem.h b/src/app/main/include/fsystem.h index e66b8a55..170cb5dc 100644 --- a/src/app/main/include/fsystem.h +++ b/src/app/main/include/fsystem.h @@ -43,8 +43,8 @@ * @file fsystem.h * @author foxBMS Team * @date 2020-07-21 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup SYSTEM * @prefix FSYS * diff --git a/src/app/main/include/general.h b/src/app/main/include/general.h index 35a13a4c..a98ac98d 100644 --- a/src/app/main/include/general.h +++ b/src/app/main/include/general.h @@ -43,8 +43,8 @@ * @file general.h * @author foxBMS Team * @date 2019-09-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL_CONF * @prefix GEN * diff --git a/src/app/main/include/infinite-loop-helper.h b/src/app/main/include/infinite-loop-helper.h index ffb0edd6..83e50ca4 100644 --- a/src/app/main/include/infinite-loop-helper.h +++ b/src/app/main/include/infinite-loop-helper.h @@ -43,8 +43,8 @@ * @file infinite-loop-helper.h * @author foxBMS Team * @date 2022-12-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL_CONF * @prefix GEN * diff --git a/src/app/main/include/main.h b/src/app/main/include/main.h index 8e66e953..d58e8c46 100644 --- a/src/app/main/include/main.h +++ b/src/app/main/include/main.h @@ -43,8 +43,8 @@ * @file main.h * @author foxBMS Team * @date 2018-10-23 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL * @prefix TODO * diff --git a/src/app/main/main.c b/src/app/main/main.c index 3888820e..27cd6b26 100644 --- a/src/app/main/main.c +++ b/src/app/main/main.c @@ -43,8 +43,8 @@ * @file main.c * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL * @prefix TODO * @@ -70,7 +70,7 @@ #include "foxmath.h" #include "i2c.h" #include "led.h" -#include "masterinfo.h" +#include "master_info.h" #include "os.h" #include "pwm.h" #include "spi.h" diff --git a/src/app/main/wscript b/src/app/main/wscript index c0e88812..d6c269c5 100644 --- a/src/app/main/wscript +++ b/src/app/main/wscript @@ -76,7 +76,7 @@ def build(bld): os.path.join("..", "engine", "config"), os.path.join("..", "engine", "database"), os.path.join("..", "engine", "diag"), - os.path.join("..", "engine", "hwinfo"), + os.path.join("..", "engine", "hw_info"), os.path.join("..", "task", "os"), os.path.join("..", "task", "config"), ] diff --git a/src/app/task/config/ftask_cfg.c b/src/app/task/config/ftask_cfg.c index 44e0b72c..49e22903 100644 --- a/src/app/task/config/ftask_cfg.c +++ b/src/app/task/config/ftask_cfg.c @@ -43,8 +43,8 @@ * @file ftask_cfg.c * @author foxBMS Team * @date 2019-08-26 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TASK_CONFIGURATION * @prefix FTSK * @@ -159,8 +159,7 @@ extern void FTSK_InitializeUserCodeEngine(void) { /* See function definition doxygen comment for details */ STD_RETURN_TYPE_e retval = DATA_Initialize(); - if (retval == E_NOT_OK) { - /* Fatal error! */ + if (retval == STD_NOT_OK) { FAS_ASSERT(FAS_TRAP); } @@ -174,8 +173,7 @@ extern void FTSK_InitializeUserCodeEngine(void) { retval = SYSM_Init(); - if (retval == E_NOT_OK) { - /* Fatal error! */ + if (retval == STD_NOT_OK) { FAS_ASSERT(FAS_TRAP); } diff --git a/src/app/task/config/ftask_cfg.h b/src/app/task/config/ftask_cfg.h index 029ddedc..4649f0c4 100644 --- a/src/app/task/config/ftask_cfg.h +++ b/src/app/task/config/ftask_cfg.h @@ -43,8 +43,8 @@ * @file ftask_cfg.h * @author foxBMS Team * @date 2019-08-26 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TASK_CONFIGURATION * @prefix FTSK * @@ -153,7 +153,7 @@ #define FTSK_TASK_CYCLIC_ALGORITHM_100MS_PV_PARAMETERS (NULL_PTR) /** @brief Stack size of continuously running task for I2C */ -#define FTSK_TASK_I2C_STACK_SIZE_IN_BYTES (2048u / 4u) +#define FTSK_TASK_I2C_STACK_SIZE_IN_BYTES (2048u) /** @brief Priority of continuously running task for I2C */ #define FTSK_TASK_I2C_PRIORITY (FTSK_TASK_CYCLIC_10MS_PRIORITY) @@ -164,14 +164,11 @@ /** @brief Cycle time of continuously running task for I2C */ #define FTSK_TASK_I2C_CYCLE_TIME (0u) -/** @brief Maximum allowed jitter of continuously running task for I2C */ -#define FTSK_TASK_AFE_MAXIMUM_JITTER (5u) - /** @brief pvParameters of the continuously running task for I2C */ #define FTSK_TASK_I2C_PV_PARAMETERS (NULL_PTR) /** @brief Stack size of continuously running task for AFEs */ -#define FTSK_TASK_AFE_STACK_SIZE_IN_BYTES (4096u / 4u) +#define FTSK_TASK_AFE_STACK_SIZE_IN_BYTES (4096u) /** @brief Priority of continuously running task for AFEs */ #define FTSK_TASK_AFE_PRIORITY (OS_PRIORITY_ABOVE_HIGH) @@ -182,9 +179,6 @@ /** @brief Cycle time of continuously running task for AFEs */ #define FTSK_TASK_AFE_CYCLE_TIME (0u) -/** @brief Maximum allowed jitter of continuously running task for AFEs */ -#define FTSK_TASK_AFE_MAXIMUM_JITTER (5u) - /** @brief pvParameters of the continuously running task for AFEs */ #define FTSK_TASK_AFE_PV_PARAMETERS (NULL_PTR) diff --git a/src/app/task/ftask/freertos/ftask_freertos.c b/src/app/task/ftask/freertos/ftask_freertos.c index 46dea043..32cc8da3 100644 --- a/src/app/task/ftask/freertos/ftask_freertos.c +++ b/src/app/task/ftask/freertos/ftask_freertos.c @@ -43,8 +43,8 @@ * @file ftask_freertos.c * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TASK * @prefix FTSK * @@ -92,6 +92,10 @@ /** size of storage area for the CAN Rx queue*/ #define FTSK_CAN_RX_QUEUE_STORAGE_AREA (FTSK_CAN_RX_QUEUE_LENGTH * FTSK_CAN_RX_QUEUE_ITEM_SIZE_IN_BYTES) +/** size of storage area for the CAN Tx unsent messages queue*/ +#define FTSK_CAN_TX_UNSENT_MESSAGES_QUEUE_STORAGE_AREA \ + (FTSK_CAN_TX_UNSENT_MESSAGES_QUEUE_LENGTH * FTSK_CAN_TX_UNSENT_MESSAGES_QUEUE_ITEM_SIZE_IN_BYTES) + /** size of storage area for the RTC set time queue*/ #define FTSK_RTC_QUEUE_STORAGE_AREA (FTSK_RTC_QUEUE_LENGTH * FTSK_RTC_QUEUE_ITEM_SIZE_IN_BYTES) @@ -115,7 +119,9 @@ OS_QUEUE ftsk_imdCanDataQueue = NULL_PTR; OS_QUEUE ftsk_canRxQueue = NULL_PTR; /* INCLUDE MARKER FOR THE DOCUMENTATION; DO NOT MOVE can-documentation-rx-queue-handle-stop-include */ -OS_QUEUE ftsk_afeRequestQueue; +OS_QUEUE ftsk_canTxUnsentMessagesQueue = NULL_PTR; + +OS_QUEUE ftsk_afeRequestQueue = NULL_PTR; OS_QUEUE ftsk_rtcSetTimeQueue = NULL_PTR; OS_QUEUE ftsk_afeToI2cQueue = NULL_PTR; @@ -170,6 +176,18 @@ extern void FTSK_CreateQueues(void) { vQueueAddToRegistry(ftsk_canRxQueue, "CAN Receive Queue"); FAS_ASSERT(ftsk_canRxQueue != NULL); + /* structure and array for static CAN TX unsent messages queue */ + static uint8_t ftsk_canTxUnsentMessagesQueueStorageArea[FTSK_CAN_TX_UNSENT_MESSAGES_QUEUE_STORAGE_AREA] = {0}; + static StaticQueue_t ftsk_canTxUnsentMessagesQueueStructure = {0}; + + ftsk_canTxUnsentMessagesQueue = xQueueCreateStatic( + FTSK_CAN_TX_UNSENT_MESSAGES_QUEUE_LENGTH, + FTSK_CAN_TX_UNSENT_MESSAGES_QUEUE_ITEM_SIZE_IN_BYTES, + ftsk_canTxUnsentMessagesQueueStorageArea, + &ftsk_canTxUnsentMessagesQueueStructure); + FAS_ASSERT(ftsk_canTxUnsentMessagesQueue != NULL); + vQueueAddToRegistry(ftsk_canTxUnsentMessagesQueue, "CAN Transmit Unsent Messages Queue"); + /** * @brief size of storage area for the AFE request queue * @details The array that is used for the queue's storage area. diff --git a/src/app/task/ftask/ftask.c b/src/app/task/ftask/ftask.c index b33ce429..229d8d2b 100644 --- a/src/app/task/ftask/ftask.c +++ b/src/app/task/ftask/ftask.c @@ -43,8 +43,8 @@ * @file ftask.c * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TASK * @prefix FTSK * diff --git a/src/app/task/ftask/ftask.h b/src/app/task/ftask/ftask.h index daa1a643..286b1139 100644 --- a/src/app/task/ftask/ftask.h +++ b/src/app/task/ftask/ftask.h @@ -43,8 +43,8 @@ * @file ftask.h * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TASK * @prefix FTSK * @@ -83,6 +83,11 @@ /** Size of queue item that is used in the can driver */ #define FTSK_CAN_RX_QUEUE_ITEM_SIZE_IN_BYTES (sizeof(CAN_BUFFER_ELEMENT_s)) +/** Length of queue that is used in the can module for tracking unsent messages */ +#define FTSK_CAN_TX_UNSENT_MESSAGES_QUEUE_LENGTH (5u) +/** Size of queue item that is used in the can driver */ +#define FTSK_CAN_TX_UNSENT_MESSAGES_QUEUE_ITEM_SIZE_IN_BYTES (sizeof(CAN_BUFFER_ELEMENT_s)) + #define FTSK_AFE_REQUEST_QUEUE_LENGTH (1u) #define FTSK_AFE_REQUEST_QUEUE_ITEM_SIZE (sizeof(AFE_REQUEST_e)) @@ -106,6 +111,9 @@ extern OS_QUEUE ftsk_imdCanDataQueue; /** CAN driver data queue for RX messages */ extern OS_QUEUE ftsk_canRxQueue; +/** CAN driver data queue for unsent TX messages */ +extern OS_QUEUE ftsk_canTxUnsentMessagesQueue; + /** handle of the AFE driver request queue */ extern OS_QUEUE ftsk_afeRequestQueue; diff --git a/src/app/task/os/freertos/os_freertos.c b/src/app/task/os/freertos/os_freertos.c index bc685e23..9112fddd 100644 --- a/src/app/task/os/freertos/os_freertos.c +++ b/src/app/task/os/freertos/os_freertos.c @@ -43,8 +43,8 @@ * @file os_freertos.c * @author foxBMS Team * @date 2021-11-18 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup OS * @prefix OS * @@ -57,6 +57,7 @@ #include "HL_sys_core.h" +#include "can_cbs_tx_crash-dump.h" #include "ftask.h" #include @@ -126,7 +127,22 @@ void vApplicationIdleHook(void) { #if (configCHECK_FOR_STACK_OVERFLOW > 0) /* FreeRTOS internal function, keep FreeRTOS types */ +/* AXIVION Next Codeline Style CodingStyle-Naming.Function: keep the parameter + names as provided by FreeRTOS */ +/* AXIVION Next Codeline Style MisraC2012-2.7: The parameters are only required + by the API given through FreeRTOS and are not used (as they are not needed), + therefore it is save to ignore them. */ +/* AXIVION Next Codeline Style MisraC2012-8.13: The types of the parameters are + provided by the API. As stated, the parameters are not used, therefore the + 'const'-qualifier can be ignored. */ +/* AXIVION Next Codeline Style Generic-MissingParameterAssert: As stated above, + the parameters are not used, so there is no reason to assert their on their + values.*/ void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) { + /* After the FreeRTOS stack overflow detection has been triggered, try to + instantly send a CAN message, that tells the higher level control unit, + that a stack overflow appeared in one of the FreeRTOS tasks. */ + CANTX_SendReasonsForFatalErrors(CANTX_FATAL_ERRORS_ACTIONS_STACK_OVERFLOW); FAS_ASSERT(FAS_TRAP); } #endif /* configCHECK_FOR_STACK_OVERFLOW */ @@ -226,7 +242,7 @@ extern OS_STD_RETURN_e OS_NotifyIndexedFromIsr( if (xNotification == pdTRUE) { notification = OS_SUCCESS; } - /* Make the scheduler yield when notification made, so that unblocked tasks is run imediately + /* Make the scheduler yield when notification made, so that unblocked tasks is run immediately (if priorities allow it, instead of waiting for the next OS tick) */ portYIELD_FROM_ISR(xHigherPriorityTaskWoken); return notification; diff --git a/src/app/task/os/freertos/os_freertos_config-validation.h b/src/app/task/os/freertos/os_freertos_config-validation.h index 636a8452..fbca8997 100644 --- a/src/app/task/os/freertos/os_freertos_config-validation.h +++ b/src/app/task/os/freertos/os_freertos_config-validation.h @@ -43,8 +43,8 @@ * @file os_freertos_config-validation.h * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup OS * @prefix OS * diff --git a/src/app/task/os/os.c b/src/app/task/os/os.c index bf6ccce5..4b0c1c64 100644 --- a/src/app/task/os/os.c +++ b/src/app/task/os/os.c @@ -43,8 +43,8 @@ * @file os.c * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup OS * @prefix OS * diff --git a/src/app/task/os/os.h b/src/app/task/os/os.h index 88a4ec76..31df7f1b 100644 --- a/src/app/task/os/os.h +++ b/src/app/task/os/os.h @@ -43,8 +43,8 @@ * @file os.h * @author foxBMS Team * @date 2019-08-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup OS * @prefix OS * @@ -59,6 +59,10 @@ #include "fstd_types.h" +/* clang-format off */ +#include +/* clang-format on */ + #if defined(FOXBMS_USES_FREERTOS) #include "FreeRTOS.h" #include "queue.h" @@ -69,7 +73,6 @@ #define OS_ENABLE_CACHE (false) /**< true: Enable cache, false: Disable cache */ #endif -#include #include /*========== Macros and Definitions =========================================*/ diff --git a/src/app/task/wscript b/src/app/task/wscript index 43dbff91..beffd2c4 100644 --- a/src/app/task/wscript +++ b/src/app/task/wscript @@ -75,6 +75,7 @@ def build(bld): os.path.join("..", "application", "redundancy"), os.path.join("..", "driver", "adc"), os.path.join("..", "driver", "can"), + os.path.join("..", "driver", "can", "cbs", "tx"), os.path.join("..", "driver", "config"), os.path.join("..", "driver", "contactor"), os.path.join("..", "driver", "crc"), diff --git a/src/doxygen_src.h b/src/doxygen_src.h index 870ad79f..7778ac34 100644 --- a/src/doxygen_src.h +++ b/src/doxygen_src.h @@ -43,8 +43,8 @@ * @file doxygen_src.h * @author foxBMS Team * @date 2019-06-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup DOXYGEN * @prefix DX * diff --git a/src/opt/cells/config/lg_inr18650mj1.c b/src/opt/cells/config/lg_inr18650mj1.c index 5a8e3b5c..274bcdd9 100644 --- a/src/opt/cells/config/lg_inr18650mj1.c +++ b/src/opt/cells/config/lg_inr18650mj1.c @@ -43,8 +43,8 @@ * @file lg_inr18650mj1.c * @author foxBMS Team * @date 2017-11-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup BATTERY_CELL_CONFIGURATION * @prefix BC * diff --git a/src/opt/cells/config/lg_inr18650mj1.h b/src/opt/cells/config/lg_inr18650mj1.h index ff76e006..79e4925e 100644 --- a/src/opt/cells/config/lg_inr18650mj1.h +++ b/src/opt/cells/config/lg_inr18650mj1.h @@ -43,8 +43,8 @@ * @file lg_inr18650mj1.h * @author foxBMS Team * @date 2017-11-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup BATTERY_CELL_CONFIGURATION * @prefix BC * diff --git a/src/opt/cells/config/panasonic_ncr18650bd.h b/src/opt/cells/config/panasonic_ncr18650bd.h index 87d07c0c..d4938c58 100644 --- a/src/opt/cells/config/panasonic_ncr18650bd.h +++ b/src/opt/cells/config/panasonic_ncr18650bd.h @@ -43,8 +43,8 @@ * @file panasonic_ncr18650bd.h * @author foxBMS Team * @date 2018-10-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup BATTERY_CELL_CONFIGURATION * @prefix BC * diff --git a/src/os/freertos/include/FreeRTOSConfig.h b/src/os/freertos/include/FreeRTOSConfig.h index 6c527349..27830bee 100644 --- a/src/os/freertos/include/FreeRTOSConfig.h +++ b/src/os/freertos/include/FreeRTOSConfig.h @@ -64,7 +64,7 @@ #define configGENERATE_RUN_TIME_STATS ( 0 ) #define configUSE_MALLOC_FAILED_HOOK ( 0 ) -#define configCHECK_FOR_STACK_OVERFLOW ( 0 ) +#define configCHECK_FOR_STACK_OVERFLOW ( 2 ) #define configRECORD_STACK_HIGH_ADDRESS ( 1 ) #define configAPPLICATION_ALLOCATED_HEAP ( 0 ) diff --git a/tests/axivion/README.md b/tests/axivion/README.md index e453b50c..dba55781 100644 --- a/tests/axivion/README.md +++ b/tests/axivion/README.md @@ -48,7 +48,7 @@ │ └───scripts ci_check_freshness_of_architecture_svg.py - dep_analysis.py + dependency_analysis.py gravis_export_architecture_svg.py start_analysis.bat start_local_analysis.bat @@ -62,11 +62,12 @@ The compiler configuration file is created by running `ticgtsetup`. This example shows the command line for TI ARM CGT 20.2.6. -``` +```pwsh ticgtsetup --cc "C:\ti\ccs1200\ccs\tools\compiler\ti-cgt-arm_20.2.6.LTS\bin\armcl.EXE --silicon_version=7R5 --code_state=32 --float_support=VFPv3D16 -g --diag_wrap=off --display_error_number --enum_type=packed --abi=eabi --c11 -Ooff --issue_remarks --strict_ansi" --cxx "C:\ti\ccs1200\ccs\tools\compiler\ti-cgt-arm_20.2.6.LTS\bin\armcl.EXE --silicon_version=7R5 --code_state=32 --float_support=VFPv3D16 -g --diag_wrap=off --display_error_number --enum_type=packed --abi=eabi --c11 -Ooff --issue_remarks --strict_ansi" --config tests\axivion\compiler_config.json ``` -With the appropiate Axivion version in PATH and the appropiate compiler version -specified in the arguments. + +With the appropriate Axivion version in PATH and the appropriate compiler +version specified in the arguments. ## `axivion_preinc.h` diff --git a/tests/axivion/additional_compiler_config.json b/tests/axivion/additional_compiler_config.json index eed3da3a..795b09e6 100644 --- a/tests/axivion/additional_compiler_config.json +++ b/tests/axivion/additional_compiler_config.json @@ -2,16 +2,6 @@ "Project": { "TIARMToolchain": { "_active": true, - "language_c": { - "preprocessing": { - "predefined_macros": { - "$(delta:+)": { - "_Imaginary": "_Complex" - }, - "$(delta:-)": [] - } - } - }, "preincludes": { "$(delta:+)": [ "axivion_preinc.h" diff --git a/tests/axivion/ci_config.json b/tests/axivion/ci_config.json index 1c3f1599..6774e222 100644 --- a/tests/axivion/ci_config.json +++ b/tests/axivion/ci_config.json @@ -60,7 +60,7 @@ }, "JSONReport": { "_active": true, - "filename": "foxbms-2_axivion_report.json" + "filename": "foxbms_spa_report.json" } }, "_Format": "1.0", diff --git a/tests/axivion/config-test/test_macro-names.c b/tests/axivion/config-test/test_macro-names.c index 03faa6e9..dabc2c7b 100644 --- a/tests/axivion/config-test/test_macro-names.c +++ b/tests/axivion/config-test/test_macro-names.c @@ -7,9 +7,9 @@ #include "test_macro-names.h" #define TEST_HALLO /* valid prefix, casing -> good */ #define TEST_HALLO_ms /* valid prefix, casing and suffix -> good */ -#define MACRO_MISSIS_PREFIX /* must fail */ +#define MACRO_MISSES_PREFIX /* must fail */ #define macro_has_bad_casing /* must fail */ -// test: TESTCASE.add_expected_stdout("test_macro-names.c:10:9: error: The macro name is not 'ALL_CAPS'. [MACRO_MISSIS_PREFIX] (Rule CodingStyle-Naming.Macro)") +// test: TESTCASE.add_expected_stdout("test_macro-names.c:10:9: error: The macro name is not 'ALL_CAPS'. [MACRO_MISSES_PREFIX] (Rule CodingStyle-Naming.Macro)") // test: TESTCASE.add_expected_stdout("test_macro-names.c:11:9: error: Macro names shall use the naming convention '(prefix.upper())_ALL_CAPS' (and optional unit suffix preceded by _) or for include guards 'FOXBMS__FILENAME_H_'. [macro_has_bad_casing] (Rule CodingStyle-Naming.Macro)") // test: TESTCASE.add_expected_stdout("test_macro-names.c:11:9: error: The macro name is not 'ALL_CAPS'. [macro_has_bad_casing] (Rule CodingStyle-Naming.Macro)") diff --git a/tests/axivion/config-test/test_parameter-names.c b/tests/axivion/config-test/test_parameter-names.c new file mode 100644 index 00000000..010c634d --- /dev/null +++ b/tests/axivion/config-test/test_parameter-names.c @@ -0,0 +1,123 @@ +/* + * @prefix TEST + */ + +// test: analysis(['CodingStyle-Naming.Parameter']) +#include + +void TEST_VoidOk00(void) { /* ok */ +} +/* suffixes */ +void TEST_SuffixOk00(int abc) { /* ok */ +} +void TEST_SuffixOk01(int abcPascalCase) { /* ok */ +} +void TEST_SuffixOk02(int abc_degC) { /* ok */ +} +void TEST_SuffixOk03(int abc_ddegC) { /* ok */ +} +void TEST_SuffixOk04(int abc_dK) { /* ok */ +} +void TEST_SuffixOk05(int abc_ohm) { /* ok */ +} +void TEST_SuffixOk06(int abc_kOhm) { /* ok */ +} +void TEST_SuffixOk07(int abc_ms) { /* ok */ +} +void TEST_SuffixOk08(int abc_us) { /* ok */ +} +void TEST_SuffixOk20(int abc_perc) { /* ok */ +} +void TEST_SuffixOk21(int abc_mV) { /* ok */ +} +void TEST_SuffixOk22(int abc_V) { /* ok */ +} +void TEST_SuffixOk23(int abc_mA) { /* ok */ +} +void TEST_SuffixOk24(int abc_A) { /* ok */ +} +void TEST_SuffixOk25(int abc_mAs) { /* ok */ +} +void TEST_SuffixOk26(int abc_mAh) { /* ok */ +} +void TEST_SuffixOk27(int abc_As) { /* ok */ +} +void TEST_SuffixOk28(int abc_Wh) { /* ok */ +} +void TEST_SuffixOk29(int abc_t) { /* ok */ +} +void TEST_SuffixOk30(int abc_Hz) { /* ok */ +} +void TEST_SuffixNotOk00(int abc_SuffixNotOk00) { /* not ok: invalid suffix */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:51:29: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [abc_SuffixNotOk00] (Rule CodingStyle-Naming.Parameter)") +} + +/* const */ +void TEST_ConstOk00(const int kConstOk00) { /* ok */ +} +void TEST_ConstNotOk00(const int constNotOk00) { /* not ok: 'k'-prefix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:58:34: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [constNotOk00] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_ConstNotOk01(const int kconstNotOk01) { /* not ok: 'k'-prefix, but not 'PascalCase' */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:61:34: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [kconstNotOk01] (Rule CodingStyle-Naming.Parameter)") +} +/* pointers */ +void TEST_PointerOk00(int *pPointerOk00) { /* ok */ +} +void TEST_PointerNotOk00(int *ointerNotOk00) { /* not ok: 'p'-prefix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:67:31: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [ointerNotOk00] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_PointerNotOk01(int *ppointerNotOk00) { /* not ok: 'p'-prefix, but not 'PascalCase' */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:70:31: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [ppointerNotOk00] (Rule CodingStyle-Naming.Parameter)") +} +/* pointer to const */ +void TEST_PointerToConstOk00(const int *pkPointerToConstOk00) { /* ok */ +} +void TEST_PointerToConstNotOk00(const int *ointerToConstNotOk00) { /* not ok: 'pk'-prefix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:76:44: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [ointerToConstNotOk00] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_PointerToConstNotOk01(const int *pPointerToConstNotOk01) { /* not ok: 'k'-infix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:79:44: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [pPointerToConstNotOk01] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_PointerToConstNotOk02(const int *kPointerToConstNotOk02) { /* not ok: 'p'-prefix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:82:44: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [kPointerToConstNotOk02] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_PointerToConstNotOk03(const int *pkpointerToConstNotOk03) { /* not ok: not 'PascalCase' */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:85:44: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [pkpointerToConstNotOk03] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_PointerToConstNotOk04(const int *kpPointerToConstNotOk04) { /* not ok: wrong order in prefix */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:88:44: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [kpPointerToConstNotOk04] (Rule CodingStyle-Naming.Parameter)") +} +/* const pointer to */ +void TEST_ConstPointerOk00(int *const kpConstPointerOk00) { /* ok */ +} +void TEST_ConstPointerNotOk00(int *const constPointerNotOk00) { /* not ok: 'kp'-prefix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:94:42: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [constPointerNotOk00] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_ConstPointerNotOk01(int *const pConstPointerNotOk01) { /* not ok: 'k'-prefix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:97:42: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [pConstPointerNotOk01] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_ConstPointerNotOk02(int *const kConstPointerNotOk02) { /* not ok: 'p'-infix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:100:42: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [kConstPointerNotOk02] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_ConstPointerNotOk03(int *const pkconstPointerNotOk03) { /* not ok: not 'PascalCase' */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:103:42: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [pkconstPointerNotOk03] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_ConstPointerNotOk04(int *const pkConstPointerNotOk04) { /* not ok: wrong order in prefix */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:106:42: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [pkConstPointerNotOk04] (Rule CodingStyle-Naming.Parameter)") +} +/* const pointers to const */ +void TEST_ConstPointerToConstOk00(const int *const kpkConstPointerToConstOk00) { /* ok */ +} +void TEST_ConstPointerToConstNotOk00(const int *const constPointerToConstNotOk00) { /* not ok: 'kpk'-prefix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:112:55: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [constPointerToConstNotOk00] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_ConstPointerToConstNotOk01(const int *const kpConstPointerToConstNotOk01) { /* not ok: 'k'-infix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:115:55: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [kpConstPointerToConstNotOk01] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_ConstPointerToConstNotOk02(const int *const kkConstPointerToConstNotOk02) { /* not ok: 'p'-infix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:118:55: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [kkConstPointerToConstNotOk02] (Rule CodingStyle-Naming.Parameter)") +} +void TEST_ConstPointerToConstNotOk03(const int *const pkConstPointerToConstNotOk03) { /* not ok: 'k'-prefix missing */ + // test: TESTCASE.add_expected_stdout("test_parameter-names.c:121:55: error: The parameter name is not 'camelCase' or does not pre- or suffix the parameter correctly. [pkConstPointerToConstNotOk03] (Rule CodingStyle-Naming.Parameter)") +} diff --git a/tests/axivion/forbidden-violations/check_forbidden_violations.py b/tests/axivion/forbidden-violations/check_forbidden_violations.py index cf421236..2c900054 100644 --- a/tests/axivion/forbidden-violations/check_forbidden_violations.py +++ b/tests/axivion/forbidden-violations/check_forbidden_violations.py @@ -44,6 +44,8 @@ import json import logging import sys +import os +from pathlib import Path def main(): @@ -83,6 +85,15 @@ def main(): else: logging.basicConfig(level=logging.ERROR) + valid = True + if not Path(args.forbidden).is_file(): + valid = False + logging.error(f"File '{args.forbidden}' does not exist.") + if not Path(args.report).is_file(): + valid = False + logging.error(f"File '{args.report}' does not exist.") + if not valid: + sys.exit("Invalid script arguments.") forbidden_rules = [] with open(args.forbidden, mode="r", encoding="utf-8") as forbidden: @@ -93,11 +104,14 @@ def main(): continue if not rule.lstrip().startswith("#"): forbidden_rules.append(rule) - logging.info(f"loaded the following rules as forbidden: {forbidden_rules}") + logging.info( + "loaded the following rules as forbidden:\n" + f"{os.linesep.join(forbidden_rules)}" + ) with open(args.report, mode="r", encoding="utf-8") as report: report_json = json.load(report) - logging.info("successfully loaded a JSON report file") + logging.info(f"successfully loaded a JSON report file '{args.report}'.") fatal_violations_found = False for violation in report_json: diff --git a/tests/axivion/mapping.gxl b/tests/axivion/mapping.gxl index 41c9613a..1cc13e52 100644 --- a/tests/axivion/mapping.gxl +++ b/tests/axivion/mapping.gxl @@ -542,15 +542,6 @@ f src/app/driver/config/fram_cfg.c - - - - interlock_cfg.c - - - f src/app/driver/config/interlock_cfg.c - - diff --git a/tests/axivion/rule_config_addon.json b/tests/axivion/rule_config_addon.json index 7e75afc8..b7c28db7 100644 --- a/tests/axivion/rule_config_addon.json +++ b/tests/axivion/rule_config_addon.json @@ -22,6 +22,7 @@ "exclude_in_macros": [ "adcGROUP1", "adcREG1", + "AVCLK1_FREQ", "canREG1", "canREG2", "crcREG1", @@ -29,6 +30,9 @@ "ecapREG1", "esmREG", "etpwmREG1", + "FLT_EPSILON", + "FLT_MAX", + "FLT_MIN", "FS8x_C*", "FS8X_FS_A*", "FS8X_FS_BAD_*", @@ -48,10 +52,35 @@ "FS8X_FS_WDW_*", "FS8X_M_*", "FS8x_WD_SEED_DEFAULT", + "HCLK_FREQ", "hetREG1", "hetREG2", + "I2C_REPEATMODE", "i2cREG1", + "MC33775_ALLM_APP_CTRL_*", + "MC33775_ALLM_CFG_*", + "MC33775_ALLM_VCVB_*", + "MC33775_BAL_CH_CFG_*", + "MC33775_BAL_GLOB_CFG_*", + "MC33775_I2C_CFG_*", + "MC33775_I2C_CTRL_*", + "MC33775_I2C_DATA*", + "MC33775_I2C_STAT_*", + "MC33775_I2C_STAT_*", + "MC33775_PRMM_AIN_CFG_*", + "MC33775_PRMM_APP_*", + "MC33775_SECM_AIN_CFG_*", + "MC33775_SECM_APP_AIN4_*", + "MC33775_SECM_PER_NPNISENSE_*", + "MC33775_SYS_COM_CFG_BUSFW_*", + "MC33775_SYS_COM_CFG_OFFSET", + "MC33775_SYS_COM_TO_CFG_*", + "MC33775_SYS_MODE_OFFSET", + "MC33775_SYS_MODE_TARGETMODE_*", + "MC33775_SYS_UID_LOW_OFFSET", + "MC33775_SYS_VERSION_OFFSET", "NULL_PTR", + "RTI_FREQ", "spiREG1", "spiREG2", "spiREG3", @@ -59,9 +88,8 @@ "spiREG5", "SYS_EXCEPTION", "systemREG1", - "FLT_EPSILON", "UINT32_MAX", - "RTI_FREQ" + "UINT64_MAX" ], "excludes": [] }, diff --git a/tests/axivion/rule_config_c.json b/tests/axivion/rule_config_c.json index ba657054..d1245e28 100644 --- a/tests/axivion/rule_config_c.json +++ b/tests/axivion/rule_config_c.json @@ -345,6 +345,8 @@ "names": [ "*Notification", "_c_int00", + "FTSK_CreateTask*", + "main", "vApplicationIdleHook", "vApplicationStackOverflowHook" ] @@ -1310,6 +1312,9 @@ "NextCodeline": { "_active": true }, + "NextConstruct": { + "_active": true + }, "NextLine": { "_active": true }, diff --git a/tests/axivion/rule_config_names.py b/tests/axivion/rule_config_names.py index 0b33a1fd..3d83290d 100644 --- a/tests/axivion/rule_config_names.py +++ b/tests/axivion/rule_config_names.py @@ -45,10 +45,15 @@ import sys from pathlib import Path -import axivion.config # pylint: disable=import-error -from bauhaus import ir # pylint: disable=import-error -from bauhaus import style # pylint: disable=import-error -from bauhaus.ir.common.scanner import comments # pylint: disable=import-error +# disable import checking for Python modules that come with Axivion +# pylint: disable=import-error +import axivion.config +from bauhaus import ir +from bauhaus import style +from bauhaus.ir.common.scanner import comments +from bauhaus.ir.common.output.unparse import unparse_type + +# pylint: enable=import-error if "perform_tests" in sys.argv[0]: logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.DEBUG) @@ -65,9 +70,11 @@ "dK", # deci Kelvin "ohm", # ohm "kOhm", # kilo ohm + "kHz", # kilo Hertz "ms", # milliseconds "us", # microseconds "perc", # percentage + "perm", # per mill "mV", # millivolt "V", # volt "mA", # milliampere @@ -75,6 +82,7 @@ "mAs", # milliampere seconds "mAh", # milliampere hours "As", # ampere seconds + "W", # watt "Wh", # watt hours "t", # "typedef" "Hz", # Hertz @@ -308,13 +316,34 @@ def check_parameter_name(node: ir.Node, module_prefixes: ModulePrefixLookup) -> optional suffix that indicates the unit.""" if not node.Name: return True + + # check for const and pointer prefixes + expected_prefix = "" + node_type: str = unparse_type(node.Its_Type) + + for i in node_type.split()[::-1]: # Clockwise/Spiral Rule + if i.endswith("*"): + expected_prefix += "p" + if i == "const": + expected_prefix += "k" base_name = str(node.Name) base_name_splitted = base_name.split("_", maxsplit=1) parameter_name = base_name_splitted[0] if not parameter_name: # a="_bla"; a.split("_"); ['', 'bla'] return False - + valid_indicator = True + if not parameter_name.startswith(expected_prefix): + valid_indicator = False + if expected_prefix: + try: + # if we can not index, the name is invalid in any case + first_letter_after_prefix = parameter_name[len(expected_prefix)] + except IndexError: + return False + # 'pabc' would otherwise be valid, but it needs to be 'pAbc' + if not first_letter_after_prefix == first_letter_after_prefix.upper(): + return False try: # TODO: will not work if suffix contains underscore parameter_name_suffix = base_name_splitted[1] except IndexError: @@ -336,7 +365,7 @@ def check_parameter_name(node: ir.Node, module_prefixes: ModulePrefixLookup) -> break valid_suffix = validate_suffix(parameter_name_suffix) - return valid_camel_case and valid_suffix + return all([valid_indicator, valid_camel_case, valid_suffix]) def check_global_variable_name( @@ -414,7 +443,10 @@ def check_global_variable_name( FUNCTION_NAME_ERROR_MESSAGE = "The function name is not 'PascalCase'." GLOBAL_VARIABLE_ERROR_MESSAGE = "The global variable name is not 'camelCase'." MACRO_ERROR_MESSAGE = "The macro name is not 'ALL_CAPS'." -PARAMETER_ERROR_MESSAGE = "The parameter name is not 'camelCase'." +PARAMETER_ERROR_MESSAGE = ( + "The parameter name is not 'camelCase' or does not " + "pre- or suffix the parameter correctly." +) STRUCT_MEMBER_NAME_ERROR_MESSAGE = "The struct member name is not 'camelCase'." naming_errors = { "Function": (check_function_name, FUNCTION_NAME_ERROR_MESSAGE), diff --git a/tests/axivion/scripts/check_axivion_versions.py b/tests/axivion/scripts/check_axivion_versions.py new file mode 100644 index 00000000..6fa5f498 --- /dev/null +++ b/tests/axivion/scripts/check_axivion_versions.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Check that the Axivion version specifier is the same in all configuration +files""" + +import sys +import json +from pathlib import Path + +import git +from git.exc import InvalidGitRepositoryError + +SCRIPT_DIR = Path(__file__).parent.resolve() + +try: + repo = git.Repo(SCRIPT_DIR, search_parent_directories=True) + REPO_ROOT = Path(repo.git.rev_parse("--show-toplevel")) +except InvalidGitRepositoryError: + sys.exit("Test can only be run in a git repository.") + + +def get_axivion_configuration_files() -> list: + """Find all Axivion configuration files""" + return [ + i + for i in (REPO_ROOT / "tests/axivion").glob("*.json") + if not i.name == "axivion_config.json" + ] + [ + i + for i in (REPO_ROOT / "tests/unit/axivion").glob("*.json") + if not i.name == "axivion_config.json" + ] + + +def main(): + """Runs the Axivion version check script""" + errors = [] + file_and_version_info = [] + for i in get_axivion_configuration_files(): + with open(i, "r", encoding="utf-8") as f: + cfg = json.load(f) + try: + cfg["_Version"] + except KeyError: + errors.append(f"{i}: '_Version' not specified") + continue + try: + cfg["_VersionNum"] + except KeyError: + errors.append(f"{i}: '_VersionNum' not specified") + continue + + file_and_version_info.append((i, cfg["_Version"], cfg["_VersionNum"])) + + versions = [] + version_nums = [] + for j in file_and_version_info: + if j[1] not in versions: + versions.append(j[1]) + version_num_str = ".".join([str(k) for k in j[2]]) + if version_num_str not in version_nums: + version_nums.append(version_num_str) + + if len(versions) > 1: + for i in versions: + errors.append( + f"Found multiple versions ('_Version'): {', '.join(versions)}" + ) + if len(version_nums) > 1: + for i in version_nums: + errors.append( + f"Found multiple versions numbers ('_VersionNum'): {', '.join(version_nums)}" + ) + + for i in errors: + print(i, file=sys.stderr) + + sys.exit(len(errors)) + + +if __name__ == "__main__": + main() diff --git a/tests/axivion/scripts/dep_analysis.py b/tests/axivion/scripts/dependency_analysis.py similarity index 100% rename from tests/axivion/scripts/dep_analysis.py rename to tests/axivion/scripts/dependency_analysis.py diff --git a/tests/c-std/c-std-test-inline-helper.h b/tests/c-std/c-std-test-inline-helper.h index b3ff3622..48350452 100644 --- a/tests/c-std/c-std-test-inline-helper.h +++ b/tests/c-std/c-std-test-inline-helper.h @@ -43,8 +43,8 @@ * @file c-std-test-inline-helper.h * @author foxBMS Team * @date 2022-03-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TESTS * @prefix TEST * @@ -56,6 +56,8 @@ /*========== Includes =======================================================*/ +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Macros and Definitions =========================================*/ #if defined(__STDC_VERSION__) /* We have some newer compiler (C94 at least) */ #if __STDC_VERSION__ == 199409L && defined(__GNUC__) diff --git a/tests/c-std/c-std-test.c b/tests/c-std/c-std-test.c index 271d4ca0..b365e9c3 100644 --- a/tests/c-std/c-std-test.c +++ b/tests/c-std/c-std-test.c @@ -43,8 +43,8 @@ * @file c-std-test.c * @author foxBMS Team * @date 2022-03-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup TESTS * @prefix TEST * diff --git a/tests/can/check_ids.py b/tests/can/check_ids.py index b300f1d4..5e4395a2 100644 --- a/tests/can/check_ids.py +++ b/tests/can/check_ids.py @@ -61,7 +61,7 @@ except ImportError: pass -FILE_RE = r"\(in:([a-z_-]{1,}\.c):([A-Z]{2,5}_.*), fv:((tx)|(rx))\)" +FILE_RE = r"\(in:([a-z_\-0-9]{1,}\.c):([A-Z]{2,5}_.*), fv:((tx)|(rx))\)" FILE_RE_COMPILED = re.compile(FILE_RE) @@ -155,7 +155,7 @@ def construct_msg_define(msg) -> ExpectedCanMessageDefines: if m.group(3).lower() == "rx": direction = RxTx.Rx pref = "CANRX_" - phase_macro = "Rx has no phase" # receive messages have ne phase + phase_macro = "Rx has no phase" # receive messages have no phase message_id_macro = pref + message_id_macro period_macro = pref + period_macro full_message_macro = pref + full_message_macro diff --git a/tests/can/check_implemented.py b/tests/can/check_implemented.py index cc190035..31674943 100644 --- a/tests/can/check_implemented.py +++ b/tests/can/check_implemented.py @@ -58,7 +58,7 @@ except ImportError: pass -FILE_RE = r"\(in:([a-z_-]{1,}\.c):([A-Z]{2,5}_.*), fv:((tx)|(rx))\)" +FILE_RE = r"\(in:([a-z_\-0-9]{1,}\.c):([A-Z]{2,5}_.*), fv:((tx)|(rx))\)" FILE_RE_COMPILED = re.compile(FILE_RE) diff --git a/tests/dbc/overlapping-signals.dbc b/tests/dbc/overlapping-signals.dbc index 138d5754..fa8219d0 100644 --- a/tests/dbc/overlapping-signals.dbc +++ b/tests/dbc/overlapping-signals.dbc @@ -33,7 +33,7 @@ SG_ foxBMS_AuxiliaryFuseBlown : 23|1@1+ (1,0) [0|1] "" Vector__XXX SG_ foxBMS_chargingFuseBlown : 24|1@1+ (1,0) [0|1] "" Vector__XXX -CM_ BO_ 544 "Message contains foxBMS state (in:can_cbs_tx_state.c:CAN_TxState)"; +CM_ BO_ 544 "Message contains foxBMS state (in:can_cbs_tx_bms-state.c:CAN_TxState)"; CM_ SG_ 544 foxBMS_generalError "0x00: No error detected, 0x01: Error detected"; CM_ SG_ 544 foxBMS_generalWarning "0x00: No warning detected, 0x01: Warning detected"; CM_ SG_ 544 foxBMS_Error_dieTemperatureMCU "0x00: No error, 0x01: Error detected"; diff --git a/tests/dbc/overlapping-signals.sym b/tests/dbc/overlapping-signals.sym index 48658624..8441b8aa 100644 --- a/tests/dbc/overlapping-signals.sym +++ b/tests/dbc/overlapping-signals.sym @@ -8,7 +8,7 @@ enum VtSig_foxBMS_modeRequest(0="mode_Standby", 1="mode_Discharge", {SENDRECEIVE} [foxBMS_State] -ID=220h // Message contains foxBMS state (in:can_cbs_tx_state.c:CAN_TxState) +ID=220h // Message contains foxBMS state (in:can_cbs_tx_bms_state.c:CAN_TxState) DLC=8 Var=foxBMS_State unsigned 4,4 -m Var=foxBMS_generalError bit 13,1 -m // 0x00: No error detected, 0x01: Error detected diff --git a/tests/unit/README.md b/tests/unit/README.md new file mode 100644 index 00000000..14e159d0 --- /dev/null +++ b/tests/unit/README.md @@ -0,0 +1,225 @@ +# Unit Tests + +## "Standard" Unit Test Build + +The *standard* way of building and running the unit tests is to run +``waf build_unit_test`` in the root of the repository. + +This runs the unit test suite using Ceedling. + +The overview of the results of the unit tests (if they are successfully run) is +then found at +``/build/unit_test/artifacts/gcov/GcovCoverageResults.html`` + +## Axivion Analysis of the Unit Test Implementation + +The unit test implementation, i.e., the files in this directory +(``/tests/unit``), also needs to be analyzed by Axivion as it +is done for the actual software (``/src``). + +### Workflow + +To achieve this, this directory holds a configuration to build the unit tests +directly, without using Ceedling, but instead using ``gcc`` and ``cafeCC`` +directly. +**However, it is required to first run the Ceedling based unit test, as this +creates the mocks and runners for the test files.** + +The workflow is therefore as follows (assuming the user name is ``vulpes`` and +the repository is cloned into ``C:\Users\vulpes\Documents\foxbms-2``): + +```cmd +C:\Users\vulpes>cd "C:\Users\vulpes\Documents\foxbms-2" +C:\Users\vulpes\Documents\foxbms-2>waf build_unit_test +@REM the mocks and unit tests are now created and the test suite runs +C:\Users\vulpes\Documents\foxbms-2>cd "tests\unit" +@REM configure the project +C:\Users\vulpes\Documents\foxbms-2\tests\unit>run_ut_gcc_build.bat configure +@REM use 'build_host' to create a host build of the unit tests; this is the +@REM same as ceedling does; this just exists to ensure, that the test suite +@REM builds and works as expected +C:\Users\vulpes\Documents\foxbms-2\tests\unit>run_ut_gcc_build.bat build_host +@REM Run an Axivion build (argument: 'build_axivion'), to pass the results to +@REM Axivion Suite +C:\Users\vulpes\Documents\foxbms-2\tests\unit>run_ut_gcc_build.bat build_axivion +``` + +The analysis of the test source is configured in +``/tests/unit/axivion``. + +### Adding an Additional Test to the Analysis + +- Analyze what ceedling does, when it creates a test suite for a specific test, + e.g., ``src/app/driver/crc/crc.c`` by running: + ```cmd + C:\Users\vulpes\Documents\foxbms-2>cd "build\unit_test" + C:\Users\vulpes\Documents\foxbms-2>..\..\conf\unit\ceedling.cmd test:test_crc.c + ``` +- Ceedling will then tell what it actually does: + ``` + Test 'test_crc.c' + ----------------- + Generating include list for fassert.h... + Creating mock for fassert... + Generating runner for test_crc.c... + Compiling test_crc_runner.c... + Compiling test_crc.c... + Compiling Mockfassert.c... + Compiling crc.c... + Linking test_crc.out... + Running test_crc.out... + ``` +- It can be seen, that the test of the ``crc`` module requires generating some + mocks and compiling these and other files, linking all that together and + finally running the created test binary. +- In order to add this Ceedling-based test to this build, the following needs + to be done in ``build.test.json``: + - a new list item must be created with this basic setup: + ```json + { + "uut": { + "source": "", + "includes": [], + "framework-includes": [] + }, + "test": { + "includes": [], + "framework-includes": [] + }, + "runner": { + "includes": [], + "framework-includes": [], + "use": [] + } + } + ``` + + - In this item the source of the new *unit-under-test* (key: ``uut``, sub key + ``source``) must be added, e.g., for this exampling it then would be + + ``"source" : "src/app/driver/crc/crc.c"``. + + - Trying to compile this unit-under-test (``run_ut_gcc_build.bat -v -j 1``) + will fail, as most likely includes are missing. + - Therefore, the includes now need to added. The includes from the source + tree (key: ``includes``) are added by the using the path relative to the + repository root and the Ceedling and mock includes (key: + ``framework-includes``) are added by using magic names. + These magic names, and their respective values they are replaced with, are: + - ``cexception`` for ``tools/vendor/ceedling/vendor/c_exception/lib``, + - ``mocks`` for ``build/unit_test/test/mocks``, + - ``cmock`` for ``tools/vendor/ceedling/vendor/cmock/src`` and + - ``unity`` for ``tools/vendor/ceedling/vendor/unity/src``. + + Add ``includes`` and ``framework-includes`` as required, i.e., the + unit-under-test needs to compile without any error. + For this example, the ``uut`` key looks then like this: + ```json + "uut": { + "source": "src/app/driver/crc/crc.c", + "includes": [ + "src/app/main/include" + ], + "framework-includes": [ + "cexception" + ] + } + ``` + - At next, the ``test`` key needs to defined. + The name of the test file is derived from the unit-under-test, i.e., in + example it is ``tests/unit/app/driver/crc/test_crc.c``. + The build system therefore automatically derives the name of the test file + and only the ``includes`` and ``framework`` includes needed to be added. + This works the same as way as described above. + For this example, the ``test`` key looks then like this: + ```json + "test": { + "includes": [ + "src/app/driver/crc", + "src/app/main/include", + "src/os/freertos/include", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "framework-includes": [ + "cexception", + "mocks", + "unity" + ] + } + ``` + - As last step, the test runner needs to added using the key ``runner``. + The name of the test runner source is also derived automatically and is + therefore omitted in the configuration file. + Adding ``includes`` and ``framework-includes`` again works the same way. + As creating the test runner requires a linking step, it is needed to add a + list of required objects in order to link the binary (key: ``use``). + The ``use`` key again accepts the magic strings. These are for the Ceedling + objects: + - ``cexception`` built from + ``tools/vendor/ceedling/vendor/c_exception/lib/CException.c``, + - ``cmock`` built from + ``tools/vendor/ceedling/vendor/cmock/src/cmock.c`` and + - ``unity`` built from + ``tools/vendor/ceedling/vendor/unity/src/unity.c``. + + Furthermore, all other objects from other build steps for this binary + that are required for linking are also defined by magic strings. + The magic string for a object is the base name of the file that is compiled + in all lowercase and without file extension. + Based on the output from the original ceedling build it is seen, that + ``Mockfassert.c`` needs to be compiled for that test, which means the + object is required for linking. + To add this object the entry in the ``use`` list would be ``mockfassert``. + The unit-under-test as well as the test and the test runner are + automatically added as required objects and are therefore omitted. + For this example, the ``runner`` key looks then like this: + ```json + "runner": { + "includes": [ + "src/app/main/include", + "src/os/freertos/include", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "framework-includes": [ + "cexception", + "cmock", + "mocks", + "unity" + ], + "use": [ + "cexception", + "cmock", + "mockfassert", + "unity" + ] + } + ``` + - For some tests, more than just the unit-under-test, test file and test + runner are needed to be compiled and linked into the final test binary. + For these cases, the ``needs`` key can used. + This key contains a list of the additional sources. + For each entry in ``needs``, the ``source``, the ``includes`` and the + ``framework-includes`` can be added as needed in the same way as described above. + The objects that are created do not need to be added to the list in the + ``use`` key of the runner, as they are automatically added by the build + system. + + +### Adding a New Mock to Build + +If a new mock is created, it needs to be added in ``build.mocks.json``. +There it is only required to provide the path of the mock relative to +``build/unit_test`` using the key ``source`` and the includes relative to the +repository root using the key ``includes``. + + +# Configuration + +Most of the Axivion configuration is the same for the embedded source and the +unit tests (compare ``test/axivion/axivion_config.json`` and +``tests/unit/axivion/axivion_config.json``). +The main difference is that unit test functions need to start with ``test`` as +the ceedling requires this (and accordingly to our guidelines would functions +would need to start with ``TEST``.) diff --git a/tests/unit/app/application/algorithm/config/test_algorithm_cfg.c b/tests/unit/app/application/algorithm/config/test_algorithm_cfg.c index d5602b33..4f285de2 100644 --- a/tests/unit/app/application/algorithm/config/test_algorithm_cfg.c +++ b/tests/unit/app/application/algorithm/config/test_algorithm_cfg.c @@ -43,8 +43,8 @@ * @file test_algorithm_cfg.c * @author foxBMS Team * @date 2020-06-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,6 +62,10 @@ #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/algorithm/config") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/moving_average") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/application/algorithm/moving_average/test_moving_average.c b/tests/unit/app/application/algorithm/moving_average/test_moving_average.c index b8600f9f..053cb897 100644 --- a/tests/unit/app/application/algorithm/moving_average/test_moving_average.c +++ b/tests/unit/app/application/algorithm/moving_average/test_moving_average.c @@ -43,8 +43,8 @@ * @file test_moving_average.c * @author foxBMS Team * @date 2020-07-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,6 +59,10 @@ #include "moving_average.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/algorithm/config") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/moving_average") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting.c b/tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting.c index 063a4c58..cb8dee89 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting.c +++ b/tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting.c @@ -43,8 +43,8 @@ * @file test_soc_counting.c * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,9 +59,27 @@ #include "Mockfram.h" #include "battery_cell_cfg.h" +#include "soc_counting_cfg.h" #include "foxmath.h" -#include "soc_counting.h" +#include "state_estimation.h" + +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("soc_counting.c") +TEST_SOURCE_FILE("soe_none.c") +TEST_SOURCE_FILE("soh_none.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation/soc/counting") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ FRAM_SOC_s fram_soc = {0}; @@ -74,7 +92,7 @@ void tearDown(void) { } void testSE_GetStateOfChargeFromVoltage(void) { - float test_soc = -1.0; + float_t test_soc = -1.0f; int16_t test_voltage_mV = 3780; test_soc = SE_GetStateOfChargeFromVoltage(test_voltage_mV); TEST_ASSERT_EQUAL(64.0f, test_soc); diff --git a/tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug.c b/tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug.c index 4f9e8931..e26ea859 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug.c +++ b/tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug.c @@ -43,8 +43,8 @@ * @file test_soc_debug.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -54,8 +54,16 @@ /*========== Includes =======================================================*/ #include "unity.h" +#include "Mockdatabase.h" -#include "soc_debug.h" +#include "state_estimation.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("soc_debug.c") +TEST_SOURCE_FILE("soe_debug.c") +TEST_SOURCE_FILE("soh_debug.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none.c b/tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none.c index d2d70cb8..d368d373 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none.c +++ b/tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none.c @@ -43,8 +43,8 @@ * @file test_soc_none.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -54,8 +54,16 @@ /*========== Includes =======================================================*/ #include "unity.h" +#include "Mockdatabase.h" -#include "soc_none.h" +#include "state_estimation.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("soc_none.c") +TEST_SOURCE_FILE("soe_none.c") +TEST_SOURCE_FILE("soh_none.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting.c b/tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting.c index f242e745..1759d393 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting.c +++ b/tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting.c @@ -43,8 +43,8 @@ * @file test_soe_counting.c * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,7 +61,21 @@ #include "battery_cell_cfg.h" #include "foxmath.h" -#include "soe_counting.h" +#include "state_estimation.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("soc_none.c") +TEST_SOURCE_FILE("soe_counting.c") +TEST_SOURCE_FILE("soh_none.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ FRAM_SOE_s fram_soe = {0}; diff --git a/tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug.c b/tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug.c index f0306e86..a6abbddf 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug.c +++ b/tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug.c @@ -43,8 +43,8 @@ * @file test_soe_debug.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -54,8 +54,16 @@ /*========== Includes =======================================================*/ #include "unity.h" +#include "Mockdatabase.h" -#include "soe_debug.h" +#include "state_estimation.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("soc_debug.c") +TEST_SOURCE_FILE("soe_debug.c") +TEST_SOURCE_FILE("soh_debug.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug_cfg.c b/tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug_cfg.c deleted file mode 100644 index 755075bd..00000000 --- a/tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug_cfg.c +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_soe_debug_cfg.c - * @author foxBMS Team - * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Tests for SOE module responsible for calculation of state-of-energy - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" - -#include "soe_debug_cfg.h" - -/*========== Definitions and Implementations for Unit Test ==================*/ - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -void testDummy(void) { -} - -/*========== Test Cases =====================================================*/ diff --git a/tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none.c b/tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none.c index 5b737905..d124b470 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none.c +++ b/tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none.c @@ -43,8 +43,8 @@ * @file test_soe_none.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -54,8 +54,16 @@ /*========== Includes =======================================================*/ #include "unity.h" +#include "Mockdatabase.h" -#include "soe_none.h" +#include "state_estimation.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("soc_none.c") +TEST_SOURCE_FILE("soe_none.c") +TEST_SOURCE_FILE("soh_none.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none_cfg.c b/tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none_cfg.c deleted file mode 100644 index b1bdd28c..00000000 --- a/tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none_cfg.c +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_soe_none_cfg.c - * @author foxBMS Team - * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Tests for SOE module responsible for calculation of state-of-energy - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" - -#include "soe_none_cfg.h" - -/*========== Definitions and Implementations for Unit Test ==================*/ - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -void testDummy(void) { -} - -/*========== Test Cases =====================================================*/ diff --git a/tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid.c b/tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid.c index 0debb644..533fa4e8 100644 --- a/tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid.c +++ b/tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid.c @@ -43,8 +43,8 @@ * @file test_sof_trapezoid.c * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -63,6 +63,17 @@ #include "foxmath.h" #include "sof_trapezoid.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation/sof/trapezoid") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ FRAM_SOC_s fram_soc = {0}; diff --git a/tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid_cfg.c b/tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid_cfg.c index b2e1280c..ccebba53 100644 --- a/tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid_cfg.c +++ b/tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid_cfg.c @@ -43,8 +43,8 @@ * @file test_sof_trapezoid_cfg.c * @author foxBMS Team * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,9 @@ #include "sof_trapezoid_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation/sof/trapezoid") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug.c b/tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug.c index c8e80c6a..57e835d5 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug.c +++ b/tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug.c @@ -43,8 +43,8 @@ * @file test_soh_debug.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -56,9 +56,16 @@ #include "unity.h" #include "Mockdatabase.h" -#include "soh_debug.h" +#include "state_estimation.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("soc_debug.c") +TEST_SOURCE_FILE("soe_debug.c") +TEST_SOURCE_FILE("soh_debug.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ @@ -71,9 +78,9 @@ void tearDown(void) { /*========== Test Cases =====================================================*/ /** test invalid input values */ void testInvalidInput(void) { - DATA_BLOCK_SOX_s table_test = {.header.uniqueId = DATA_BLOCK_ID_SOX}; + DATA_BLOCK_SOH_s table_testSoh = {.header.uniqueId = DATA_BLOCK_ID_SOH}; TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfHealth(NULL_PTR, BS_NR_OF_STRINGS - 1u)); - TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfHealth(&table_test, BS_NR_OF_STRINGS)); + TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfHealth(&table_testSoh, BS_NR_OF_STRINGS)); TEST_ASSERT_FAIL_ASSERT(SE_CalculateStateOfHealth(NULL_PTR)); } diff --git a/tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug_cfg.c b/tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug_cfg.c deleted file mode 100644 index 311398b0..00000000 --- a/tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug_cfg.c +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_soh_debug_cfg.c - * @author foxBMS Team - * @date 2021-12-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Test for the configuration for SOH - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" - -#include "soh_debug_cfg.h" - -/*========== Definitions and Implementations for Unit Test ==================*/ - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -/*========== Test Cases =====================================================*/ -/** empty dummy test */ -void testDummy(void) { -} diff --git a/tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none.c b/tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none.c index 42e9880b..120a839e 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none.c +++ b/tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none.c @@ -43,8 +43,8 @@ * @file test_soh_none.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -56,9 +56,17 @@ #include "unity.h" #include "Mockdatabase.h" -#include "soh_none.h" +#include "state_estimation.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("soc_none.c") +TEST_SOURCE_FILE("soe_none.c") +TEST_SOURCE_FILE("soh_none.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ @@ -71,9 +79,9 @@ void tearDown(void) { /*========== Test Cases =====================================================*/ /** test invalid input values */ void testInvalidInput(void) { - DATA_BLOCK_SOX_s table_test = {.header.uniqueId = DATA_BLOCK_ID_SOX}; + DATA_BLOCK_SOH_s table_testSoh = {.header.uniqueId = DATA_BLOCK_ID_SOH}; TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfHealth(NULL_PTR, BS_NR_OF_STRINGS - 1u)); - TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfHealth(&table_test, BS_NR_OF_STRINGS)); + TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfHealth(&table_testSoh, BS_NR_OF_STRINGS)); TEST_ASSERT_FAIL_ASSERT(SE_CalculateStateOfHealth(NULL_PTR)); } diff --git a/tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none_cfg.c b/tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none_cfg.c deleted file mode 100644 index 271b61e4..00000000 --- a/tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none_cfg.c +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_soh_none_cfg.c - * @author foxBMS Team - * @date 2021-12-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Test for the configuration for SOH - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" - -#include "soh_none_cfg.h" - -/*========== Definitions and Implementations for Unit Test ==================*/ - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -/*========== Test Cases =====================================================*/ -/** empty dummy test */ -void testDummy(void) { -} diff --git a/tests/unit/app/application/algorithm/state_estimation/test_state_estimation.c b/tests/unit/app/application/algorithm/state_estimation/test_state_estimation.c index 6225d72b..462223fc 100644 --- a/tests/unit/app/application/algorithm/state_estimation/test_state_estimation.c +++ b/tests/unit/app/application/algorithm/state_estimation/test_state_estimation.c @@ -43,8 +43,8 @@ * @file test_state_estimation.c * @author foxBMS Team * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -56,14 +56,18 @@ #include "unity.h" #include "Mockdatabase.h" -#include "soc_none.h" -#include "soe_none.h" -#include "soh_none.h" #include "state_estimation.h" #include "test_assert_helper.h" #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("soc_none.c") +TEST_SOURCE_FILE("soe_none.c") +TEST_SOURCE_FILE("soh_none.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ @@ -76,7 +80,9 @@ void tearDown(void) { /*========== Test Cases =====================================================*/ /** test invalid input on interfaces */ void testInvalidInput(void) { - DATA_BLOCK_SOX_s table_test = {.header.uniqueId = DATA_BLOCK_ID_SOX}; + DATA_BLOCK_SOC_s table_testSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; + DATA_BLOCK_SOH_s table_testSoh = {.header.uniqueId = DATA_BLOCK_ID_SOH}; + DATA_BLOCK_SOE_s table_testSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; TEST_ASSERT_FAIL_ASSERT(SE_InitializeSoc(true, BS_NR_OF_STRINGS)); TEST_ASSERT_FAIL_ASSERT(SE_InitializeSoe(true, BS_NR_OF_STRINGS)); @@ -84,17 +90,17 @@ void testInvalidInput(void) { TEST_ASSERT_FAIL_ASSERT(SE_InitializeSoh(BS_NR_OF_STRINGS)); TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfCharge(NULL_PTR, true, BS_NR_OF_STRINGS - 1u)); - TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfCharge(&table_test, true, BS_NR_OF_STRINGS)); + TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfCharge(&table_testSoc, true, BS_NR_OF_STRINGS)); TEST_ASSERT_FAIL_ASSERT(SE_CalculateStateOfCharge(NULL_PTR)); TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfEnergy(NULL_PTR, true, BS_NR_OF_STRINGS - 1u)); - TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfEnergy(&table_test, true, BS_NR_OF_STRINGS)); + TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfEnergy(&table_testSoe, true, BS_NR_OF_STRINGS)); TEST_ASSERT_FAIL_ASSERT(SE_CalculateStateOfEnergy(NULL_PTR)); TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfHealth(NULL_PTR, BS_NR_OF_STRINGS - 1u)); - TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfHealth(&table_test, BS_NR_OF_STRINGS)); + TEST_ASSERT_FAIL_ASSERT(SE_InitializeStateOfHealth(&table_testSoh, BS_NR_OF_STRINGS)); TEST_ASSERT_FAIL_ASSERT(SE_CalculateStateOfHealth(NULL_PTR)); } diff --git a/tests/unit/app/application/algorithm/test_algorithm.c b/tests/unit/app/application/algorithm/test_algorithm.c index ea827c16..09924510 100644 --- a/tests/unit/app/application/algorithm/test_algorithm.c +++ b/tests/unit/app/application/algorithm/test_algorithm.c @@ -43,8 +43,8 @@ * @file test_algorithm.c * @author foxBMS Team * @date 2020-06-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,6 +62,10 @@ #include "fstd_types.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/algorithm") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/config") + /*========== Definitions and Implementations for Unit Test ==================*/ ALGO_TASKS_s algo_algorithms[] = { {ALGO_UNINITIALIZED, 100, 1000, 0, NULL_PTR, &TEST_AlgorithmComputeFunction}, diff --git a/tests/unit/app/application/bal/history/test_bal_strategy_history.c b/tests/unit/app/application/bal/history/test_bal_strategy_history.c index 8eecce5a..f1017fe5 100644 --- a/tests/unit/app/application/bal/history/test_bal_strategy_history.c +++ b/tests/unit/app/application/bal/history/test_bal_strategy_history.c @@ -43,8 +43,8 @@ * @file test_bal_strategy_history.c * @author foxBMS Team * @date 2020-06-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -69,7 +69,20 @@ #include "database_cfg.h" #include "bal.h" -#include "bal_strategy_history.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("bal_strategy_history.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") +TEST_INCLUDE_PATH("../../src/app/application/bal") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/application/bal/none/test_bal_strategy_none.c b/tests/unit/app/application/bal/none/test_bal_strategy_none.c index b9883bcd..4902c990 100644 --- a/tests/unit/app/application/bal/none/test_bal_strategy_none.c +++ b/tests/unit/app/application/bal/none/test_bal_strategy_none.c @@ -43,8 +43,8 @@ * @file test_bal_strategy_none.c * @author foxBMS Team * @date 2020-08-03 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -66,7 +66,20 @@ #include "database_cfg.h" -#include "bal_strategy_none.h" +#include "bal.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("bal_strategy_none.c") + +TEST_INCLUDE_PATH("../../src/app/application/bal") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/application/bal/test_bal.c b/tests/unit/app/application/bal/test_bal.c index e873d2d8..20614336 100644 --- a/tests/unit/app/application/bal/test_bal.c +++ b/tests/unit/app/application/bal/test_bal.c @@ -43,8 +43,8 @@ * @file test_bal.c * @author foxBMS Team * @date 2020-08-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -64,6 +64,9 @@ #include #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/bal") + /*========== Definitions and Implementations for Unit Test ==================*/ BAL_STATE_s initState; diff --git a/tests/unit/app/application/bal/voltage/test_bal_strategy_voltage.c b/tests/unit/app/application/bal/voltage/test_bal_strategy_voltage.c index 004ac355..3a34e800 100644 --- a/tests/unit/app/application/bal/voltage/test_bal_strategy_voltage.c +++ b/tests/unit/app/application/bal/voltage/test_bal_strategy_voltage.c @@ -43,8 +43,8 @@ * @file test_bal_strategy_voltage.c * @author foxBMS Team * @date 2020-06-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -70,6 +70,18 @@ #include "bal.h" #include "bal_strategy_voltage.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/bal") +TEST_INCLUDE_PATH("../../src/app/application/bal/voltage") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/application/bms/test_bms.c b/tests/unit/app/application/bms/test_bms.c index e959fb7d..11d1f3da 100644 --- a/tests/unit/app/application/bms/test_bms.c +++ b/tests/unit/app/application/bms/test_bms.c @@ -43,8 +43,8 @@ * @file test_bms.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -76,8 +76,26 @@ #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/bal") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/application/plausibility") +TEST_INCLUDE_PATH("../../src/app/application/soa") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/interlock") +TEST_INCLUDE_PATH("../../src/app/driver/led") +TEST_INCLUDE_PATH("../../src/app/driver/meas") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ -DIAG_ID_CFG_s diag_diagnosisIdConfiguration[] = {}; + +DIAG_ID_CFG_s diag_diagnosisIdConfiguration[] = {0}; DIAG_DEV_s diag_device = { .nrOfConfiguredDiagnosisEntries = sizeof(diag_diagnosisIdConfiguration) / sizeof(DIAG_ID_CFG_s), diff --git a/tests/unit/app/application/config/test_bal_cfg.c b/tests/unit/app/application/config/test_bal_cfg.c index 10447786..e03ba75d 100644 --- a/tests/unit/app/application/config/test_bal_cfg.c +++ b/tests/unit/app/application/config/test_bal_cfg.c @@ -43,8 +43,8 @@ * @file test_bal_cfg.c * @author foxBMS Team * @date 2022-02-26 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,6 +58,8 @@ #include "bal_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/application/config/test_battery_cell_cfg.c b/tests/unit/app/application/config/test_battery_cell_cfg.c index 3b8c7e49..0c3c7c5a 100644 --- a/tests/unit/app/application/config/test_battery_cell_cfg.c +++ b/tests/unit/app/application/config/test_battery_cell_cfg.c @@ -43,8 +43,8 @@ * @file test_battery_cell_cfg.c * @author foxBMS Team * @date 2020-10-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,8 @@ #include "battery_cell_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/application/config/test_battery_system_cfg.c b/tests/unit/app/application/config/test_battery_system_cfg.c index 346e3def..c5c04ec2 100644 --- a/tests/unit/app/application/config/test_battery_system_cfg.c +++ b/tests/unit/app/application/config/test_battery_system_cfg.c @@ -43,8 +43,8 @@ * @file test_battery_system_cfg.c * @author foxBMS Team * @date 2020-04-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,6 +59,8 @@ #include "battery_system_cfg.h" #include "database_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/application/config/test_soa_cfg.c b/tests/unit/app/application/config/test_soa_cfg.c index 139b028c..be42013b 100644 --- a/tests/unit/app/application/config/test_soa_cfg.c +++ b/tests/unit/app/application/config/test_soa_cfg.c @@ -43,8 +43,8 @@ * @file test_soa_cfg.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,6 +62,13 @@ #include #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ @@ -126,8 +133,8 @@ void testSOA_IsCellCurrentLimitViolated(void) { TEST_ASSERT_EQUAL(false, SOA_IsCellCurrentLimitViolated(0u, BMS_RELAXATION)); TEST_ASSERT_EQUAL(false, SOA_IsCellCurrentLimitViolated(0u, BMS_AT_REST)); - uint32_t chargeLimit = BS_NR_OF_PARALLEL_CELLS_PER_MODULE * BC_CURRENT_MAX_CHARGE_MSL_mA; - uint32_t dischargeLimit = BS_NR_OF_PARALLEL_CELLS_PER_MODULE * BC_CURRENT_MAX_DISCHARGE_MSL_mA; + uint32_t chargeLimit = BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK * BC_CURRENT_MAX_CHARGE_MSL_mA; + uint32_t dischargeLimit = BS_NR_OF_PARALLEL_CELLS_PER_CELL_BLOCK * BC_CURRENT_MAX_DISCHARGE_MSL_mA; TEST_ASSERT_EQUAL(false, SOA_IsCellCurrentLimitViolated(chargeLimit, BMS_CHARGING)); TEST_ASSERT_EQUAL(false, SOA_IsCellCurrentLimitViolated(dischargeLimit, BMS_DISCHARGING)); diff --git a/tests/unit/app/application/plausibility/test_plausibility.c b/tests/unit/app/application/plausibility/test_plausibility.c index 5a679baf..5ee6379f 100644 --- a/tests/unit/app/application/plausibility/test_plausibility.c +++ b/tests/unit/app/application/plausibility/test_plausibility.c @@ -43,8 +43,8 @@ * @file test_plausibility.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,12 +59,13 @@ #include "plausibility.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/plausibility") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ -/** local copies of database tables */ -/**@{*/ -static DATA_BLOCK_CELL_VOLTAGE_s cellVoltage = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; -static DATA_BLOCK_CURRENT_SENSOR_s currentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; -/**@}*/ /*========== Setup and Teardown =============================================*/ void setUp(void) { diff --git a/tests/unit/app/application/redundancy/test_redundancy.c b/tests/unit/app/application/redundancy/test_redundancy.c index ce7ef741..68429d76 100644 --- a/tests/unit/app/application/redundancy/test_redundancy.c +++ b/tests/unit/app/application/redundancy/test_redundancy.c @@ -43,8 +43,8 @@ * @file test_redundancy.c * @author foxBMS Team * @date 2020-07-31 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -68,7 +68,19 @@ #include #include -TEST_FILE("redundancy.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("redundancy.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/application/plausibility") +TEST_INCLUDE_PATH("../../src/app/application/redundancy") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/application/soa/test_soa.c b/tests/unit/app/application/soa/test_soa.c index b1d550ad..c9a0ee55 100644 --- a/tests/unit/app/application/soa/test_soa.c +++ b/tests/unit/app/application/soa/test_soa.c @@ -43,12 +43,12 @@ * @file test_soa.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * - * @brief Tests for SOX module responsible for calculation of current derating and of SOC + * @brief Tests for SOA module responsible for the current, voltage and temperature checking of the safe operating area. * */ @@ -63,6 +63,16 @@ #include "foxmath.h" #include "soa.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/application/soa") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/adc/test_adc.c b/tests/unit/app/driver/adc/test_adc.c index 7b7be647..4a1c14c4 100644 --- a/tests/unit/app/driver/adc/test_adc.c +++ b/tests/unit/app/driver/adc/test_adc.c @@ -43,8 +43,8 @@ * @file test_adc.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -60,6 +60,9 @@ #include "adc.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/adc") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-rdb.c b/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-rdb.c new file mode 100644 index 00000000..00d412fb --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-rdb.c @@ -0,0 +1,144 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades1830_helpers_test-data-rdb.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" + +#include "adi_ades1830_helpers_test-data-rdb.h" + +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../tests/unit/app/driver/afe/adi/ades1830") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +const uint8_t testReadDataBitsDataReceivedData[TEST_MATRIX_SIZE_READ_DATA_BITS] = + {0x00u, 0x45u, 0x4Fu, 0xF5u, 0xAAu, 0xBEu, 0x10u, 0xFF}; +const uint8_t testReadDataBitsDataPositions[TEST_MATRIX_SIZE_READ_DATA_BITS] = {0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u}; +const uint8_t testReadDataBitsDataMasks[TEST_MATRIX_SIZE_READ_DATA_BITS] = + {0x1Eu, 0x43u, 0xD6u, 0xD0u, 0xD6u, 0x6Fu, 0xBEu, 0xFFu}; + +const uint8_t testReadDataBitsExpectedDataResults[TEST_MATRIX_SIZE_READ_DATA_BITS][TEST_MATRIX_SIZE_READ_DATA_BITS] + [TEST_MATRIX_SIZE_READ_DATA_BITS] = { + {{0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}, + {{4u, 65u, 68u, 64u, 68u, 69u, 4u, 69u}, + {2u, 32u, 34u, 32u, 34u, 34u, 2u, 34u}, + {1u, 16u, 17u, 16u, 17u, 17u, 1u, 17u}, + {0u, 8u, 8u, 8u, 8u, 8u, 0u, 8u}, + {0u, 4u, 4u, 4u, 4u, 4u, 0u, 4u}, + {0u, 2u, 2u, 2u, 2u, 2u, 0u, 2u}, + {0u, 1u, 1u, 1u, 1u, 1u, 0u, 1u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}, + {{14u, 67u, 70u, 64u, 70u, 79u, 14u, 79u}, + {7u, 33u, 35u, 32u, 35u, 39u, 7u, 39u}, + {3u, 16u, 17u, 16u, 17u, 19u, 3u, 19u}, + {1u, 8u, 8u, 8u, 8u, 9u, 1u, 9u}, + {0u, 4u, 4u, 4u, 4u, 4u, 0u, 4u}, + {0u, 2u, 2u, 2u, 2u, 2u, 0u, 2u}, + {0u, 1u, 1u, 1u, 1u, 1u, 0u, 1u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}, + {{20u, 65u, 212u, 208u, 212u, 101u, 180u, 245u}, + {10u, 32u, 106u, 104u, 106u, 50u, 90u, 122u}, + {5u, 16u, 53u, 52u, 53u, 25u, 45u, 61u}, + {2u, 8u, 26u, 26u, 26u, 12u, 22u, 30u}, + {1u, 4u, 13u, 13u, 13u, 6u, 11u, 15u}, + {0u, 2u, 6u, 6u, 6u, 3u, 5u, 7u}, + {0u, 1u, 3u, 3u, 3u, 1u, 2u, 3u}, + {0u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}}, + {{10u, 2u, 130u, 128u, 130u, 42u, 170u, 170u}, + {5u, 1u, 65u, 64u, 65u, 21u, 85u, 85u}, + {2u, 0u, 32u, 32u, 32u, 10u, 42u, 42u}, + {1u, 0u, 16u, 16u, 16u, 5u, 21u, 21u}, + {0u, 0u, 8u, 8u, 8u, 2u, 10u, 10u}, + {0u, 0u, 4u, 4u, 4u, 1u, 5u, 5u}, + {0u, 0u, 2u, 2u, 2u, 0u, 2u, 2u}, + {0u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}}, + {{30u, 2u, 150u, 144u, 150u, 46u, 190u, 190u}, + {15u, 1u, 75u, 72u, 75u, 23u, 95u, 95u}, + {7u, 0u, 37u, 36u, 37u, 11u, 47u, 47u}, + {3u, 0u, 18u, 18u, 18u, 5u, 23u, 23u}, + {1u, 0u, 9u, 9u, 9u, 2u, 11u, 11u}, + {0u, 0u, 4u, 4u, 4u, 1u, 5u, 5u}, + {0u, 0u, 2u, 2u, 2u, 0u, 2u, 2u}, + {0u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}}, + {{16u, 0u, 16u, 16u, 16u, 0u, 16u, 16u}, + {8u, 0u, 8u, 8u, 8u, 0u, 8u, 8u}, + {4u, 0u, 4u, 4u, 4u, 0u, 4u, 4u}, + {2u, 0u, 2u, 2u, 2u, 0u, 2u, 2u}, + {1u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}, + {{30u, 67u, 214u, 208u, 214u, 111u, 190u, 255u}, + {15u, 33u, 107u, 104u, 107u, 55u, 95u, 127u}, + {7u, 16u, 53u, 52u, 53u, 27u, 47u, 63u}, + {3u, 8u, 26u, 26u, 26u, 13u, 23u, 31u}, + {1u, 4u, 13u, 13u, 13u, 6u, 11u, 15u}, + {0u, 2u, 6u, 6u, 6u, 3u, 5u, 7u}, + {0u, 1u, 3u, 3u, 3u, 1u, 2u, 3u}, + {0u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}}, +}; + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* just a helper file */ diff --git a/src/app/application/algorithm/state_estimation/soh/none/soh_none.h b/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-rdb.h similarity index 69% rename from src/app/application/algorithm/state_estimation/soh/none/soh_none.h rename to tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-rdb.h index d374692c..d039511a 100644 --- a/src/app/application/algorithm/state_estimation/soh/none/soh_none.h +++ b/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-rdb.h @@ -40,34 +40,34 @@ */ /** - * @file soh_none.h + * @file adi_ades1830_helpers_test-data-rdb.h * @author foxBMS Team - * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOH + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST * - * @brief Header for SOH module, responsible for calculation state-of-health + * @brief Test of some module * */ -#ifndef FOXBMS__SOH_NONE_H_ -#define FOXBMS__SOH_NONE_H_ +#ifndef FOXBMS__ADI_ADES1830_HELPERS_TEST_DATA_RDB_H_ +#define FOXBMS__ADI_ADES1830_HELPERS_TEST_DATA_RDB_H_ /*========== Includes =======================================================*/ -#include "state_estimation.h" - #include -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ +/*========== Unit Testing Framework Directives ==============================*/ -/*========== Extern Function Prototypes =====================================*/ +/*========== Macros and Definitions =========================================*/ +#define TEST_MATRIX_SIZE_READ_DATA_BITS (8) -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif +extern const uint8_t testReadDataBitsDataReceivedData[TEST_MATRIX_SIZE_READ_DATA_BITS]; +extern const uint8_t testReadDataBitsDataPositions[TEST_MATRIX_SIZE_READ_DATA_BITS]; +extern const uint8_t testReadDataBitsDataMasks[TEST_MATRIX_SIZE_READ_DATA_BITS]; +extern const uint8_t testReadDataBitsExpectedDataResults[TEST_MATRIX_SIZE_READ_DATA_BITS] + [TEST_MATRIX_SIZE_READ_DATA_BITS] + [TEST_MATRIX_SIZE_READ_DATA_BITS]; -#endif /* FOXBMS__SOH_NONE_H_ */ +#endif /* FOXBMS__ADI_ADES1830_HELPERS_TEST_DATA_RDB_H_ */ diff --git a/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-wdb.c b/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-wdb.c new file mode 100644 index 00000000..8d7b1cda --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-wdb.c @@ -0,0 +1,141 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file adi_ades1830_helpers_test-data-wdb.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" + +#include "adi_ades1830_helpers_test-data-wdb.h" + +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../tests/unit/app/driver/afe/adi/ades1830") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +const uint8_t testWriteDataBitsDataPositions[TEST_MATRIX_SIZE_WRITE_DATA_BITS] = {0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u}; +const uint8_t testWriteDataBitsDataMasks[TEST_MATRIX_SIZE_WRITE_DATA_BITS] = + {0x1Eu, 0x43u, 0xD6u, 0xD0u, 0xD6u, 0x6Fu, 0xBEu, 0xFFu}; + +const uint8_t testWriteDataBitsExpectedDataResults[TEST_MATRIX_SIZE_WRITE_DATA_BITS][TEST_MATRIX_SIZE_WRITE_DATA_BITS] + [TEST_MATRIX_SIZE_WRITE_DATA_BITS] = { + {{0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}, + {{4u, 65u, 68u, 64u, 68u, 69u, 4u, 69u}, + {2u, 32u, 34u, 32u, 34u, 34u, 2u, 34u}, + {1u, 16u, 17u, 16u, 17u, 17u, 1u, 17u}, + {0u, 8u, 8u, 8u, 8u, 8u, 0u, 8u}, + {0u, 4u, 4u, 4u, 4u, 4u, 0u, 4u}, + {0u, 2u, 2u, 2u, 2u, 2u, 0u, 2u}, + {0u, 1u, 1u, 1u, 1u, 1u, 0u, 1u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}, + {{14u, 67u, 70u, 64u, 70u, 79u, 14u, 79u}, + {7u, 33u, 35u, 32u, 35u, 39u, 7u, 39u}, + {3u, 16u, 17u, 16u, 17u, 19u, 3u, 19u}, + {1u, 8u, 8u, 8u, 8u, 9u, 1u, 9u}, + {0u, 4u, 4u, 4u, 4u, 4u, 0u, 4u}, + {0u, 2u, 2u, 2u, 2u, 2u, 0u, 2u}, + {0u, 1u, 1u, 1u, 1u, 1u, 0u, 1u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}, + {{20u, 65u, 212u, 208u, 212u, 101u, 180u, 245u}, + {10u, 32u, 106u, 104u, 106u, 50u, 90u, 122u}, + {5u, 16u, 53u, 52u, 53u, 25u, 45u, 61u}, + {2u, 8u, 26u, 26u, 26u, 12u, 22u, 30u}, + {1u, 4u, 13u, 13u, 13u, 6u, 11u, 15u}, + {0u, 2u, 6u, 6u, 6u, 3u, 5u, 7u}, + {0u, 1u, 3u, 3u, 3u, 1u, 2u, 3u}, + {0u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}}, + {{10u, 2u, 130u, 128u, 130u, 42u, 170u, 170u}, + {5u, 1u, 65u, 64u, 65u, 21u, 85u, 85u}, + {2u, 0u, 32u, 32u, 32u, 10u, 42u, 42u}, + {1u, 0u, 16u, 16u, 16u, 5u, 21u, 21u}, + {0u, 0u, 8u, 8u, 8u, 2u, 10u, 10u}, + {0u, 0u, 4u, 4u, 4u, 1u, 5u, 5u}, + {0u, 0u, 2u, 2u, 2u, 0u, 2u, 2u}, + {0u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}}, + {{30u, 2u, 150u, 144u, 150u, 46u, 190u, 190u}, + {15u, 1u, 75u, 72u, 75u, 23u, 95u, 95u}, + {7u, 0u, 37u, 36u, 37u, 11u, 47u, 47u}, + {3u, 0u, 18u, 18u, 18u, 5u, 23u, 23u}, + {1u, 0u, 9u, 9u, 9u, 2u, 11u, 11u}, + {0u, 0u, 4u, 4u, 4u, 1u, 5u, 5u}, + {0u, 0u, 2u, 2u, 2u, 0u, 2u, 2u}, + {0u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}}, + {{16u, 0u, 16u, 16u, 16u, 0u, 16u, 16u}, + {8u, 0u, 8u, 8u, 8u, 0u, 8u, 8u}, + {4u, 0u, 4u, 4u, 4u, 0u, 4u, 4u}, + {2u, 0u, 2u, 2u, 2u, 0u, 2u, 2u}, + {1u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}, + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}, + {{30u, 67u, 214u, 208u, 214u, 111u, 190u, 255u}, + {15u, 33u, 107u, 104u, 107u, 55u, 95u, 127u}, + {7u, 16u, 53u, 52u, 53u, 27u, 47u, 63u}, + {3u, 8u, 26u, 26u, 26u, 13u, 23u, 31u}, + {1u, 4u, 13u, 13u, 13u, 6u, 11u, 15u}, + {0u, 2u, 6u, 6u, 6u, 3u, 5u, 7u}, + {0u, 1u, 3u, 3u, 3u, 1u, 2u, 3u}, + {0u, 0u, 1u, 1u, 1u, 0u, 1u, 1u}}, +}; + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ diff --git a/src/app/application/algorithm/state_estimation/soc/debug/soc_debug.h b/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-wdb.h similarity index 68% rename from src/app/application/algorithm/state_estimation/soc/debug/soc_debug.h rename to tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-wdb.h index 0e75cd14..001eefd3 100644 --- a/src/app/application/algorithm/state_estimation/soc/debug/soc_debug.h +++ b/tests/unit/app/driver/afe/adi/ades1830/adi_ades1830_helpers_test-data-wdb.h @@ -40,34 +40,34 @@ */ /** - * @file soc_debug.h + * @file adi_ades1830_helpers_test-data-wdb.h * @author foxBMS Team - * @date 2020-10-14 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOC + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST * - * @brief Header for SOC module, responsible for calculation state-of-charge + * @brief Test of some module * */ -#ifndef FOXBMS__SOC_DEBUG_H_ -#define FOXBMS__SOC_DEBUG_H_ +#ifndef FOXBMS__ADI_ADES1830_HELPERS_TEST_DATA_WDB_H_ +#define FOXBMS__ADI_ADES1830_HELPERS_TEST_DATA_WDB_H_ /*========== Includes =======================================================*/ -#include "state_estimation.h" - #include -/*========== Macros and Definitions =========================================*/ - -/*========== Extern Constant and Variable Declarations ======================*/ +/*========== Unit Testing Framework Directives ==============================*/ -/*========== Extern Function Prototypes =====================================*/ +/*========== Macros and Definitions =========================================*/ +#define TEST_MATRIX_SIZE_WRITE_DATA_BITS (8) -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif +extern const uint8_t testWriteDataBitsDataReceivedData[TEST_MATRIX_SIZE_WRITE_DATA_BITS]; +extern const uint8_t testWriteDataBitsDataPositions[TEST_MATRIX_SIZE_WRITE_DATA_BITS]; +extern const uint8_t testWriteDataBitsDataMasks[TEST_MATRIX_SIZE_WRITE_DATA_BITS]; +extern const uint8_t testWriteDataBitsExpectedDataResults[TEST_MATRIX_SIZE_WRITE_DATA_BITS] + [TEST_MATRIX_SIZE_WRITE_DATA_BITS] + [TEST_MATRIX_SIZE_WRITE_DATA_BITS]; -#endif /* FOXBMS__SOC_DEBUG_H_ */ +#endif /* FOXBMS__ADI_ADES1830_HELPERS_TEST_DATA_WDB_H_ */ diff --git a/tests/unit/app/driver/afe/adi/ades1830/api/test_adi_ades1830_afe.c b/tests/unit/app/driver/afe/adi/ades1830/api/test_adi_ades1830_afe.c new file mode 100644 index 00000000..2ce6cec0 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/api/test_adi_ades1830_afe.c @@ -0,0 +1,147 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_afe.c + * @author foxBMS Team + * @date 2020-08-10 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "MockHL_sys_dma.h" +#include "Mockadi_ades183x.h" +#include "Mockadi_ades183x_cfg.h" + +#include "afe.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_afe.c") + +TEST_INCLUDE_PATH("../../src/app/application/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ +ADI_STATE_s adi_stateBase = {0}; + +const uint8_t testStringId = 1u; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +void testAFE_TriggerIc(void) { + ADI_MeasurementCycle_Expect(&adi_stateBase); + TEST_ASSERT_EQUAL(STD_OK, AFE_TriggerIc()); +} + +void testAFE_Initialize(void) { + ADI_ActivateInterfaceBoard_Expect(); + TEST_ASSERT_EQUAL(STD_OK, AFE_Initialize()); +} + +void testAFE_RequestEepromRead(void) { + TEST_ASSERT_EQUAL(STD_OK, AFE_RequestEepromRead(testStringId)); +} + +void testAFE_RequestEepromWrite(void) { + TEST_ASSERT_EQUAL(STD_OK, AFE_RequestEepromWrite(testStringId)); +} + +void testAFE_RequestTemperatureRead(void) { + TEST_ASSERT_EQUAL(STD_OK, AFE_RequestTemperatureRead(testStringId)); +} + +void testAFE_RequestBalancingFeedbackRead(void) { + TEST_ASSERT_EQUAL(STD_NOT_OK, AFE_RequestBalancingFeedbackRead(testStringId)); +} + +void testAFE_RequestOpenWireCheck(void) { + TEST_ASSERT_EQUAL(STD_OK, AFE_RequestOpenWireCheck(testStringId)); +} + +void testAFE_StartMeasurement(void) { + ADI_MakeRequest_ExpectAndReturn(AFE_START_REQUEST, STD_OK); + TEST_ASSERT_EQUAL(STD_OK, AFE_StartMeasurement()); +} + +void testAFE_IsFirstMeasurementCycleFinished(void) { + ADI_IsFirstMeasurementCycleFinished_ExpectAndReturn(&adi_stateBase, true); + TEST_ASSERT_TRUE(AFE_IsFirstMeasurementCycleFinished()); +} + +void testAFE_RequestIoRead(void) { + TEST_ASSERT_EQUAL(STD_NOT_OK, AFE_RequestIoRead(testStringId)); +} + +void testAFE_RequestIoWrite(void) { + TEST_ASSERT_EQUAL(STD_NOT_OK, AFE_RequestIoWrite(testStringId)); +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/api/test_adi_ades1830_afe_dma.c b/tests/unit/app/driver/afe/adi/ades1830/api/test_adi_ades1830_afe_dma.c new file mode 100644 index 00000000..9623dfbe --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/api/test_adi_ades1830_afe_dma.c @@ -0,0 +1,110 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_afe_dma.c + * @author foxBMS Team + * @date 2020-08-10 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockadi_ades183x.h" +#include "Mockfassert.h" +#include "Mockftask.h" +#include "Mockos.h" +#include "Mockspi.h" + +#include "dma_cfg.h" + +#include "adi_ades183x_defs.h" +#include "afe_dma.h" +#include "test_assert_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_afe_dma.c") + +TEST_INCLUDE_PATH("../../src/app/application/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ +OS_TASK_HANDLE ftsk_taskHandleAfe; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +void testAFE_DmaCallback(void) { + /* invalid SPI index */ + const uint8_t testInvalidSpiIndex = ADI_SPI_INDEX + 1; + TEST_ASSERT_FAIL_ASSERT(AFE_DmaCallback(testInvalidSpiIndex)); + + /* correct SPI index */ + OS_NotifyFromIsr_ExpectAndReturn(ftsk_taskHandleAfe, 0x50, OS_SUCCESS); + AFE_DmaCallback(ADI_SPI_INDEX); +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/config/test_adi_ades1830_cfg.c b/tests/unit/app/driver/afe/adi/ades1830/config/test_adi_ades1830_cfg.c new file mode 100644 index 00000000..2bf554a1 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/config/test_adi_ades1830_cfg.c @@ -0,0 +1,87 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_cfg.c + * @author foxBMS Team + * @date 2020-12-09 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS_CONFIGURATION + * @prefix ADI + * + * @brief Configuration for the ADI analog front-end + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mocktsi.h" + +#include "adi_ades183x_cfg.h" + +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") + +/*========== Definitions and Implementations for Unit Test ==================*/ +#define TEST_TEMPERATURE (100) + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +void testADI_ConvertGpioVoltageToTemperature(void) { + TSI_GetTemperature_ExpectAndReturn(2u, 10); + int16_t testResultTemperature = ADI_ConvertGpioVoltageToTemperature(2u); + TEST_ASSERT_EQUAL(TEST_TEMPERATURE, testResultTemperature); +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/pec/test_adi_ades1830_pec.c b/tests/unit/app/driver/afe/adi/ades1830/pec/test_adi_ades1830_pec.c new file mode 100644 index 00000000..bf4b8fa5 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/pec/test_adi_ades1830_pec.c @@ -0,0 +1,161 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_pec.c + * @author foxBMS Team + * @date 2022-11-04 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of ADI PEC computations + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" + +#include "adi_ades183x_pec.h" +#include "fstd_types.h" +#include "test_assert_helper.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_pec.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/* Test for PEC15 computation on command */ +uint8_t pec15Byte2Test0[2u] = {0x12u, 0x34u}; +uint8_t pec15Byte2Test1[2u] = {0xBEu, 0xEFu}; +uint8_t pec15Byte2Test2[2u] = {0x00u, 0x01u}; +uint8_t pec15Byte2Test3[2u] = {0x07u, 0x23u}; +uint8_t pec15Byte2Test4[2u] = {0x03u, 0x60u}; +/* Test for PEC15 computation on 6 bytes of data */ +uint8_t pec15Byte6Test0[6u] = {0x12u, 0x34u, 0x56u, 0x78u, 0x9Au, 0xBCu}; +uint8_t pec15Byte6Test1[6u] = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu}; +uint8_t pec15Byte6Test2[6u] = {0xBEu, 0xEFu, 0xBEu, 0xEFu, 0xBEu, 0xEFu}; +uint8_t pec15Byte6Test3[6u] = {0xA0u, 0xB0u, 0xC0u, 0xD0u, 0xE0u, 0xF0u}; +uint8_t pec15Byte6Test4[6u] = {0x01u, 0x2Eu, 0x9Bu, 0x33u, 0xACu, 0x55u}; + +/* Test for PEC10 computation on 6 bytes of data + 6 bits of command counter */ +uint8_t pec10Byte7Test0[7u] = {0x12u, 0x34u, 0x56u, 0x78u, 0x9Au, 0xBCu, 0xDEu}; +uint8_t pec10Byte7Test1[7u] = {0x12u, 0x34u, 0x56u, 0x78u, 0x9Au, 0xBCu, 0x00u}; +uint8_t pec10Byte7Test2[7u] = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu}; +uint8_t pec10Byte7Test3[7u] = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u}; +uint8_t pec10Byte7Test4[7u] = {0xBEu, 0xEFu, 0xBEu, 0xEFu, 0xBEu, 0xEFu, 0x35u}; +uint8_t pec10Byte7Test5[7u] = {0xBEu, 0xEFu, 0xBEu, 0xEFu, 0xBEu, 0xEFu, 0x00u}; +/* Test for PEC10 if command counter bits are handled correctly */ +uint8_t pec10Byte7Test6[7u] = {0x12u, 0x34u, 0x56u, 0x78u, 0x9Au, 0xBCu, 0x00u}; +uint8_t pec10Byte7Test7[7u] = {0x12u, 0x34u, 0x56u, 0x78u, 0x9Au, 0xBCu, 0xFFu}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +void testAdiPec15(void) { + TEST_ASSERT_EQUAL(0x1DD4u, ADI_Pec15(2u, pec15Byte2Test0)); + TEST_ASSERT_EQUAL(0xFD2Cu, ADI_Pec15(2u, pec15Byte2Test1)); + TEST_ASSERT_EQUAL(0x3D6Eu, ADI_Pec15(2u, pec15Byte2Test2)); + TEST_ASSERT_EQUAL(0xB9E4u, ADI_Pec15(2u, pec15Byte2Test3)); + TEST_ASSERT_EQUAL(0xF46Cu, ADI_Pec15(2u, pec15Byte2Test4)); + + TEST_ASSERT_EQUAL(0xBC24u, ADI_Pec15(6u, pec15Byte6Test0)); + TEST_ASSERT_EQUAL(0x664Cu, ADI_Pec15(6u, pec15Byte6Test1)); + TEST_ASSERT_EQUAL(0x845Au, ADI_Pec15(6u, pec15Byte6Test2)); + TEST_ASSERT_EQUAL(0x792Cu, ADI_Pec15(6u, pec15Byte6Test3)); + TEST_ASSERT_EQUAL(0xD522u, ADI_Pec15(6u, pec15Byte6Test4)); +} + +void testAdiPec10(void) { + TEST_ASSERT_EQUAL(0x1CCu, ADI_Pec10(6u, pec10Byte7Test0, false)); + TEST_ASSERT_EQUAL(0x53u, ADI_Pec10(6u, pec10Byte7Test0, true)); + TEST_ASSERT_EQUAL(0x1CCu, ADI_Pec10(6u, pec10Byte7Test1, false)); + TEST_ASSERT_EQUAL(0x1CCu, ADI_Pec10(6u, pec10Byte7Test1, true)); + + TEST_ASSERT_EQUAL(0x196u, ADI_Pec10(6u, pec10Byte7Test2, false)); + TEST_ASSERT_EQUAL(0xFEu, ADI_Pec10(6u, pec10Byte7Test2, true)); + TEST_ASSERT_EQUAL(0x196u, ADI_Pec10(6u, pec10Byte7Test3, false)); + TEST_ASSERT_EQUAL(0x196u, ADI_Pec10(6u, pec10Byte7Test3, true)); + + TEST_ASSERT_EQUAL(0x3F3u, ADI_Pec10(6u, pec10Byte7Test4, false)); + TEST_ASSERT_EQUAL(0x1B7u, ADI_Pec10(6u, pec10Byte7Test4, true)); + TEST_ASSERT_EQUAL(0x3F3u, ADI_Pec10(6u, pec10Byte7Test5, false)); + TEST_ASSERT_EQUAL(0x3F3u, ADI_Pec10(6u, pec10Byte7Test5, true)); + + /* pec10Test6: command counter bits set to 0 and taken into account because the receive */ + /* parameter is set to true */ + /* pec10Test7: command counter bits not set to 0 in data but must be ignored and replaced by 0 */ + /* because the receive parameter is set to false */ + /* So both function calls must return the same result */ + TEST_ASSERT_EQUAL(ADI_Pec10(6u, pec10Byte7Test6, true), ADI_Pec10(6u, pec10Byte7Test7, false)); +} + +void testAdiPec15Asserts(void) { + /* invalid data length */ + TEST_ASSERT_FAIL_ASSERT(ADI_Pec15(0, pec15Byte2Test0)); + /* invalid data */ + TEST_ASSERT_FAIL_ASSERT(ADI_Pec15(1, NULL_PTR)); +} + +void testAdiPec10Asserts(void) { + /* invalid data length */ + TEST_ASSERT_FAIL_ASSERT(ADI_Pec10(0, pec10Byte7Test0, true)); + /* invalid data */ + TEST_ASSERT_FAIL_ASSERT(ADI_Pec10(1, NULL_PTR, true)); +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830.c new file mode 100644 index 00000000..7896783d --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830.c @@ -0,0 +1,323 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830.c + * @author foxBMS Team + * @date 2020-08-10 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockadi_ades1830_defs.h" +#include "Mockadi_ades183x_balancing.h" +#include "Mockadi_ades183x_defs.h" +#include "Mockadi_ades183x_diagnostic.h" +#include "Mockadi_ades183x_gpio_voltages.h" +#include "Mockadi_ades183x_helpers.h" +#include "Mockadi_ades183x_initialization.h" +#include "Mockadi_ades183x_pec.h" +#include "Mockadi_ades183x_temperatures.h" +#include "Mockadi_ades183x_voltages.h" +#include "Mockafe_plausibility.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockdma.h" +#include "Mockfassert.h" +#include "Mockftask.h" +#include "Mockinfinite-loop-helper.h" +#include "Mockio.h" +#include "Mockos.h" +#include "Mockpex.h" +#include "Mockqueue.h" +#include "Mockspi.h" +#include "Mockspi_cfg.h" +#include "Mocktask.h" +#include "Mocktsi.h" + +#include "adi_ades183x_cfg.h" + +#include "adi_ades183x.h" +#include "adi_ades183x_buffers.h" /* use the real command config */ +#include "adi_ades183x_commands.h" /* use the real buffer configuration */ +#include "spi_cfg-helper.h" +#include "test_assert_helper.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades1830_cfg.c") +TEST_SOURCE_FILE("adi_ades183x.c") + +TEST_INCLUDE_PATH("../../src/app/application/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/** SPI data configuration struct for ADI communication */ +static spiDAT1_t spi_kAdiDataConfig[BS_NR_OF_STRINGS] = { + { /* struct is implemented in the TI HAL and uses uppercase true and false */ + .CS_HOLD = TRUE, /* If true, HW chip select kept active between words */ + .WDEL = FALSE, /* Activation of delay between words */ + .DFSEL = SPI_FMT_0, /* Data word format selection */ + .CSNR = SPI_HARDWARE_CHIP_SELECT_2_ACTIVE}, +}; + +/** + * SPI interface configuration for ADI communication + * This is a list of structs because of multistring + */ +SPI_INTERFACE_CONFIG_s spi_adiInterface[BS_NR_OF_STRINGS] = { + { + .pConfig = &spi_kAdiDataConfig[0u], + .pNode = spiREG1, + .pGioPort = &(spiREG1->PC3), + .csPin = 2u, + .csType = SPI_CHIP_SELECT_HARDWARE, + }, +}; + +OS_QUEUE ftsk_afeRequestQueue; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +void testADI_IsFirstMeasurementCycleFinished(void) { + /* Invalid pointer test */ + TEST_ASSERT_FAIL_ASSERT(ADI_IsFirstMeasurementCycleFinished(NULL_PTR)); + + adi_stateBase.firstMeasurementMade = true; + ADI_IsFirstMeasurementCycleFinished(&adi_stateBase); + TEST_ASSERT_TRUE(ADI_IsFirstMeasurementCycleFinished(&adi_stateBase)); + + adi_stateBase.firstMeasurementMade = false; + ADI_IsFirstMeasurementCycleFinished(&adi_stateBase); + TEST_ASSERT_FALSE(ADI_IsFirstMeasurementCycleFinished(&adi_stateBase)); +} + +void testADI_MakeRequest(void) { + AFE_REQUEST_e testRequest = AFE_START_REQUEST; + STD_RETURN_TYPE_e queued = STD_NOT_OK; + OS_SendToBackOfQueue_ExpectAndReturn(ftsk_afeRequestQueue, (void *)&testRequest, ADI_QUEUE_TIMEOUT_MS, OS_SUCCESS); + queued = ADI_MakeRequest(testRequest); + TEST_ASSERT_EQUAL(STD_OK, queued); + + queued = STD_OK; + OS_SendToBackOfQueue_ExpectAndReturn(ftsk_afeRequestQueue, (void *)&testRequest, ADI_QUEUE_TIMEOUT_MS, OS_FAIL); + queued = ADI_MakeRequest(testRequest); + TEST_ASSERT_EQUAL(STD_NOT_OK, queued); +} + +void testADI_ActivateInterfaceBoard(void) { + /* 8 pins are needed, and they are aligned after PEX_PIN10 so we make the test code short with some loop */ + const uint8_t nrOfPins = 8u; + for (uint8_t i = 0; i < nrOfPins; i++) { + PEX_SetPinDirectionOutput_Expect(PEX_PORT_EXPANDER3, PEX_PIN10 + i); + } + for (uint8_t i = 0; i < nrOfPins; i++) { + PEX_SetPin_Expect(PEX_PORT_EXPANDER3, PEX_PIN10 + i); + } + ADI_ActivateInterfaceBoard(); +} + +void testADI_MeasurementCycleAssertValidation(void) { + /* Invalid pointer test */ + TEST_ASSERT_FAIL_ASSERT(ADI_MeasurementCycle(NULL_PTR)); +} +void testADI_MeasurementCycleNoForever(void) { + FOREVER_ExpectAndReturn(0); + ADI_MeasurementCycle(&adi_stateBase); +} + +void testADI_MeasurementCycleMeasurementNotStartedCase0(void) { + /* 1. measurement not started */ + /* 1.1. request could not be retrieved - just wait */ + adi_stateBase.measurementStarted = false; + FOREVER_ExpectAndReturn(1); + ADI_Wait_Ignore(); + OS_ReceiveFromQueue_IgnoreAndReturn(OS_FAIL); + ADI_MeasurementCycle(&adi_stateBase); + TEST_ASSERT_FALSE(adi_stateBase.measurementStarted); /* start request has not been issued */ +} + +void testADI_MeasurementCycleMeasurementNotStartedCase1(void) { + /* 1. measurement not started */ + /* 1.2. request retrieved, but not the start request - therefore wait */ + adi_stateBase.measurementStarted = false; + FOREVER_ExpectAndReturn(1); + ADI_Wait_Ignore(); + OS_ReceiveFromQueue_IgnoreAndReturn(OS_SUCCESS); + ADI_MeasurementCycle(&adi_stateBase); + TEST_ASSERT_FALSE(adi_stateBase.measurementStarted); /* start request has not been issued */ +} + +void testADI_AccessToDatabase(void) { + /* Invalid pointer test */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_AccessToDatabase(NULL_PTR)); + + /* Write measured data */ + DATA_Write4DataBlocks_ExpectAndReturn( + adi_stateBase.data.cellVoltage, + adi_stateBase.data.cellVoltageFiltered, + adi_stateBase.data.allGpioVoltages, + adi_stateBase.data.cellTemperature, + STD_OK); + /* Leave some time for other tasks */ + ADI_Wait_Ignore(); + /* Read balancing orders */ + DATA_Read1DataBlock_ExpectAndReturn(adi_stateBase.data.balancingControl, STD_OK); + TEST_ADI_AccessToDatabase(&adi_stateBase); +} + +void testADI_ProcessMeasurementNotStartedState(void) { + AFE_REQUEST_e request = AFE_NO_REQUEST; + AFE_REQUEST_e requestValue = AFE_START_REQUEST; + + /* Invalid pointer test */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_ProcessMeasurementNotStartedState(NULL_PTR, &request)); + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_ProcessMeasurementNotStartedState(&adi_stateBase, NULL_PTR)); + + /* No request received */ + OS_ReceiveFromQueue_IgnoreAndReturn(OS_FAIL); + ADI_Wait_Expect(1u); + TEST_ADI_ProcessMeasurementNotStartedState(&adi_stateBase, &request); + + /* Request received, but not start */ + requestValue = AFE_STOP_REQUEST; + OS_ReceiveFromQueue_ExpectAndReturn(ftsk_afeRequestQueue, &request, ADI_QUEUE_TIMEOUT_MS, OS_SUCCESS); + OS_ReceiveFromQueue_IgnoreArg_pvBuffer(); + OS_ReceiveFromQueue_ReturnThruPtr_pvBuffer(&requestValue); + ADI_Wait_Expect(1u); + TEST_ADI_ProcessMeasurementNotStartedState(&adi_stateBase, &request); + TEST_ASSERT_EQUAL(AFE_STOP_REQUEST, request); + + /* Request received and is start request */ + requestValue = AFE_START_REQUEST; + OS_ReceiveFromQueue_ExpectAndReturn(ftsk_afeRequestQueue, &request, ADI_QUEUE_TIMEOUT_MS, OS_SUCCESS); + OS_ReceiveFromQueue_IgnoreArg_pvBuffer(); + OS_ReceiveFromQueue_ReturnThruPtr_pvBuffer(&requestValue); + ADI_InitializeMeasurement_Expect(&adi_stateBase); + TEST_ADI_ProcessMeasurementNotStartedState(&adi_stateBase, &request); + TEST_ASSERT_EQUAL(AFE_START_REQUEST, request); +} + +void testADI_BalanceControl(void) { + /* Invalid pointer test */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_BalanceControl(NULL_PTR)); + + /* Test for different balancing patterns */ + /* Enum to run through all balancing tests */ + typedef enum { + TEST_ADI_BALANCING_VALUE0, + TEST_ADI_BALANCING_VALUE1, + TEST_ADI_BALANCING_VALUE_E_MAX, + } TEST_ADI_BALANCING_e; + /* Test for 0xAA and 0x55 balancing patterns */ + for (TEST_ADI_BALANCING_e i = TEST_ADI_BALANCING_VALUE0; i < TEST_ADI_BALANCING_VALUE_E_MAX; i++) { + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + /* Mocks for unmute commands */ + ADI_CopyCommandBits_Expect(adi_cmdUnmute, adi_command); + ADI_TransmitCommand_Expect(adi_command, &adi_stateBase); + + /* actual register configuration for the specific AFE */ + ADI_DetermineBalancingRegisterConfiguration_Expect(&adi_stateBase); + + ADI_Wait_Ignore(); + + /* Mocks for mute commands */ + ADI_CopyCommandBits_Expect(adi_cmdMute, adi_command); + ADI_TransmitCommand_Expect(adi_command, &adi_stateBase); + TEST_ADI_BalanceControl(&adi_stateBase); + } + } +} + +void testADI_GetRequest(void) { + AFE_REQUEST_e request = AFE_NO_REQUEST; + AFE_REQUEST_e requestValue = AFE_START_REQUEST; + /* Invalid pointer test */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_GetRequest(NULL_PTR)); + + /* Request received from queue: function must return STD_OK */ + OS_ReceiveFromQueue_IgnoreAndReturn(OS_SUCCESS); + TEST_ASSERT_EQUAL(STD_OK, TEST_ADI_GetRequest(&request)); + /* No request received from queue: function must return STD_NOT_OK */ + OS_ReceiveFromQueue_IgnoreAndReturn(OS_FAIL); + TEST_ASSERT_EQUAL(STD_NOT_OK, TEST_ADI_GetRequest(&request)); + + /* Test setting value of request when a request is present in queue */ + OS_ReceiveFromQueue_ExpectAndReturn(ftsk_afeRequestQueue, &request, ADI_QUEUE_TIMEOUT_MS, OS_SUCCESS); + OS_ReceiveFromQueue_IgnoreArg_pvBuffer(); + OS_ReceiveFromQueue_ReturnThruPtr_pvBuffer(&requestValue); + TEST_ASSERT_EQUAL(AFE_NO_REQUEST, request); + TEST_ASSERT_EQUAL(STD_OK, TEST_ADI_GetRequest(&request)); + TEST_ASSERT_EQUAL(AFE_START_REQUEST, request); +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_balancing.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_balancing.c new file mode 100644 index 00000000..a84a1e10 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_balancing.c @@ -0,0 +1,220 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_balancing.c + * @author foxBMS Team + * @date 2019-08-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup SOME_GROUP + * @prefix ADI + * + * @brief Implementation of some software + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockadi_ades183x.h" +#include "Mockadi_ades183x_helpers.h" +#include "Mockadi_ades183x_pec.h" +#include "Mockadi_ades183x_voltages.h" +#include "Mockdatabase.h" +#include "Mockfassert.h" +#include "Mockftask.h" +#include "Mockio.h" +#include "Mockos.h" +#include "Mockpex.h" +#include "Mockspi.h" +#include "Mockspi_cfg.h" +#include "Mocktask.h" +#include "Mocktsi.h" + +#include "adi_ades183x_balancing.h" +#include "adi_ades183x_buffers.h" +#include "adi_ades183x_commands.h" /* use the real buffer configuration */ +#include "adi_ades183x_defs.h" +#include "spi_cfg-helper.h" +#include "test_assert_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades1830_balancing.c") +TEST_SOURCE_FILE("adi_ades1830_cfg.c") + +TEST_INCLUDE_PATH("../../src/app/application/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ +static DATA_BLOCK_BALANCING_CONTROL_s adi_balancingControl = {.header.uniqueId = DATA_BLOCK_ID_BALANCING_CONTROL}; + +ADI_STATE_s adi_stateBase = { + .data.balancingControl = &adi_balancingControl, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +/** + * @brief Testing ADI_DeactivateBalancing + * @details The following cases need to be tested: + * - Argument validation: + * - AT1/1: NULL_PTR for adiState -> assert + * - Routine validation: + * - RT1/1: Function calls expected subroutines + */ +void testADI_DeactivateBalancing(void) { + /* ======= Assertion tests ============================================= */ + /* ======= AT1/1 ======= */ + TEST_ASSERT_FAIL_ASSERT(ADI_DeactivateBalancing(NULL_PTR)); + + /* ======= Routine tests =============================================== */ + /* ======= RT1/1: Test implementation */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + const uint16_t reverseModuleNumber = BS_NR_OF_MODULES_PER_STRING - m - 1u; + ADI_WriteDataBits_Expect( + &adi_configurationRegisterBgroup[adi_stateBase.currentString] + [(reverseModuleNumber * ADI_WRCFGB_LEN) + ADI_REGISTER_OFFSET4], + 0u, + ADI_CFGRB4_DCC_1_8_POS, + ADI_CFGRB4_DCC_1_8_MASK); + ADI_WriteDataBits_Expect( + &adi_configurationRegisterBgroup[adi_stateBase.currentString] + [(reverseModuleNumber * ADI_WRCFGB_LEN) + ADI_REGISTER_OFFSET5], + 0u, + ADI_CFGRB5_DCC_9_16_POS, + ADI_CFGRB5_DCC_9_16_MASK); + } + ADI_StoredConfigurationWriteToAfeGlobal_Expect(&adi_stateBase); + + ADI_CopyCommandBits_Expect(adi_cmdUnmute, adi_command); + ADI_TransmitCommand_Expect(adi_command, &adi_stateBase); + + /* ======= RT1/1: call function under test */ + ADI_DeactivateBalancing(&adi_stateBase); + + /* ======= RT1/1: test output verification */ + /* nothing to be verified */ +} + +void testADI_DetermineBalancingRegisterConfiguration(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(ADI_DetermineBalancingRegisterConfiguration(NULL_PTR)); + + typedef enum { + TEST_ADI_BALANCING_VALUE0, + TEST_ADI_BALANCING_VALUE1, + TEST_ADI_BALANCING_VALUE_E_MAX, + } TEST_ADI_BALANCING_e; + uint8_t data = 0u; + /* Test for 0xAA and 0x55 balancing patterns */ + for (TEST_ADI_BALANCING_e i = TEST_ADI_BALANCING_VALUE0; i < TEST_ADI_BALANCING_VALUE_E_MAX; i++) { + switch (i) { + case TEST_ADI_BALANCING_VALUE0: + data = 0xAA; + break; + case TEST_ADI_BALANCING_VALUE1: + data = 0x55; + break; + default: + break; + } + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t c = 0u; c < ADI_MAX_SUPPORTED_CELLS; c++) { + if (adi_voltageInputsUsed[c] == 1u) { + /* All inputs used: function returns the cell index given as parameter */ + ADI_GetStoredVoltageIndex_IgnoreAndReturn(c); + } + /* Reset balancing control table */ + adi_stateBase.data.balancingControl + ->balancingState[s][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE)) + c] = 0u; + /* Set balancing control table values for 0xAA pattern */ + if (data == 0xAAu) { + if (c % 2u != 0u) { + adi_stateBase.data.balancingControl + ->balancingState[s][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE)) + c] = 1u; + } + } /* Set balancing control table values for 0x55 pattern */ + if (data == 0x55u) { + if (c % 2u == 0u) { + adi_stateBase.data.balancingControl + ->balancingState[s][(m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE)) + c] = 1u; + } + } + } + /* cell 1 to 8 bits must be set to the tested value */ + ADI_WriteDataBits_Expect(NULL_PTR, data, ADI_CFGRB4_DCC_1_8_POS, ADI_CFGRB4_DCC_1_8_MASK); + ADI_WriteDataBits_IgnoreArg_pSentData(); + /* cell 9 to 16 bits must be set to the tested value */ + ADI_WriteDataBits_Expect(NULL_PTR, data, ADI_CFGRB5_DCC_9_16_POS, ADI_CFGRB5_DCC_9_16_MASK); + ADI_WriteDataBits_IgnoreArg_pSentData(); + } + + ADI_StoredConfigurationWriteToAfeGlobal_Ignore(); + + /* ======= RT1/1: call function under test */ + ADI_DetermineBalancingRegisterConfiguration(&adi_stateBase); + } + } +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_buffers.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_buffers.c new file mode 100644 index 00000000..eb535090 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_buffers.c @@ -0,0 +1,80 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_buffers.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_buffers.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +/* nothing to test in this file */ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_commands.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_commands.c new file mode 100644 index 00000000..ff561ee0 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_commands.c @@ -0,0 +1,77 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_commands.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_commands.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +/* nothing to test in this file */ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_commands_voltages.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_commands_voltages.c new file mode 100644 index 00000000..9900a815 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_commands_voltages.c @@ -0,0 +1,78 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_commands_voltages.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_commands_voltages.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +/* nothing to test in this file */ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_diagnostic_w.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_diagnostic_w.c new file mode 100644 index 00000000..2f0cec47 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_diagnostic_w.c @@ -0,0 +1,74 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_diagnostic_w.c + * @author foxBMS Team + * @date 2023-10-09 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_diagnostic_w.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_gpio_voltages.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_gpio_voltages.c new file mode 100644 index 00000000..bf599c85 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_gpio_voltages.c @@ -0,0 +1,418 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_gpio_voltages.c + * @author foxBMS Team + * @date 2022-12-08 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockadi_ades183x_cfg.h" +#include "Mockos.h" +#include "Mockspi.h" + +#include "adi_ades1830_defs.h" +#include "adi_ades183x_buffers.h" /* use the real command config */ +#include "adi_ades183x_commands.h" /* use the real buffer configuration */ +#include "adi_ades183x_commands_voltages.h" +#include "adi_ades183x_defs.h" +#include "adi_ades183x_gpio_voltages.h" +#include "adi_ades183x_helpers.h" +#include "adi_ades183x_pec.h" +#include "spi_cfg-helper.h" +#include "test_assert_helper.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades1830_gpio_voltages.c") +TEST_SOURCE_FILE("adi_ades183x_buffers.c") +TEST_SOURCE_FILE("adi_ades183x_voltages.c") + +TEST_INCLUDE_PATH("../../src/app/application/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_ALL_GPIO_VOLTAGES_s adi_allGpioVoltage = {.header.uniqueId = DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE}; +static DATA_BLOCK_ALL_GPIO_VOLTAGES_s adi_allGpioVoltageRedundant = { + .header.uniqueId = DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE}; +static DATA_BLOCK_ALL_GPIO_VOLTAGES_s adi_allGpioVoltageOpenWire = { + .header.uniqueId = DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE}; +static ADI_ERROR_TABLE_s adi_errorTable = {0}; /*!< init in ADI_ResetErrorTable-function */ +static uint16_t adi_bufferRxPecTest[ADI_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; +static uint16_t adi_bufferTxPecTest[ADI_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; + +ADI_STATE_s adi_stateBase = { + .data.txBuffer = adi_bufferTxPecTest, + .data.rxBuffer = adi_bufferRxPecTest, + .data.allGpioVoltages = &adi_allGpioVoltage, + .data.allGpioVoltagesRedundant = &adi_allGpioVoltageRedundant, + .data.allGpioVoltageOpenWire = &adi_allGpioVoltageOpenWire, + .data.errorTable = &adi_errorTable, +}; + +/* If this configuration is changed, testADI_GetStoredVoltageIndex() must be adapted */ +const uint8_t adi_voltageInputsUsed[ADI_MAX_SUPPORTED_CELLS] = { + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; + +/** SPI data configuration struct for ADI communication */ +static spiDAT1_t spi_kAdiDataConfig[BS_NR_OF_STRINGS] = { + { /* struct is implemented in the TI HAL and uses uppercase true and false */ + .CS_HOLD = TRUE, /* If true, HW chip select kept active between words */ + .WDEL = FALSE, /* Activation of delay between words */ + .DFSEL = SPI_FMT_0, /* Data word format selection */ + .CSNR = SPI_HARDWARE_CHIP_SELECT_2_ACTIVE}, +}; + +/** + * SPI interface configuration for ADI communication + * This is a list of structs because of multi string + */ +SPI_INTERFACE_CONFIG_s spi_adiInterface[BS_NR_OF_STRINGS] = { + { + .pConfig = &spi_kAdiDataConfig[0u], + .pNode = spiREG1, + .pGioPort = &(spiREG1->PC3), + .csPin = 2u, + .csType = SPI_CHIP_SELECT_HARDWARE, + }, +}; + +#define TEST_ADI_AUXILIARY_RESULT_REGISTER_SET_INVALID_VALUE ((ADI_AUXILIARY_RESULT_REGISTER_SET_E) + 1u) + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testADI_GetGpioVoltages(void) { + /* Invalid state */ + TEST_ASSERT_FAIL_ASSERT(ADI_GetGpioVoltages(NULL_PTR, ADI_AUXILIARY_REGISTER, ADI_AUXILIARY_VOLTAGE)); + /* Invalid register type */ + TEST_ASSERT_FAIL_ASSERT( + ADI_GetGpioVoltages(&adi_stateBase, ADI_AUXILIARY_REGISTER_TYPE_E_MAX, ADI_AUXILIARY_VOLTAGE)); + /* Invalid store location */ + TEST_ASSERT_FAIL_ASSERT( + ADI_GetGpioVoltages(&adi_stateBase, ADI_AUXILIARY_REGISTER, ADI_AUXILIARY_STORE_LOCATION_E_MAX)); + + /* Test reading of GPIO voltages */ + + /* SPI and OS functions are ignored */ + SPI_TransmitDummyByte_IgnoreAndReturn(STD_OK); + SPI_TransmitReceiveDataDma_IgnoreAndReturn(STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + DATA_BLOCK_ALL_GPIO_VOLTAGES_s *pGpioVoltageTable = NULL_PTR; + + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + + /* Prepare voltage data to simulate data read from AFE registers */ + for (uint16_t i = 4u; i < ADI_N_BYTES_FOR_DATA_TRANSMISSION; i += 8) { + /* Set raw data, corresponds to a cell voltage of 1884mV */ + uint8_t bufferMSB = 0x0Au; + uint8_t bufferLSB = 0x01u; + /* Set receive buffer with raw data */ + adi_bufferRxPecTest[i] = bufferLSB; + adi_bufferRxPecTest[i + 1u] = bufferMSB; + adi_bufferRxPecTest[i + 2u] = bufferLSB; + adi_bufferRxPecTest[i + 3u] = bufferMSB; + adi_bufferRxPecTest[i + 4u] = bufferLSB; + adi_bufferRxPecTest[i + 5u] = bufferMSB; + /* Two PEC bytes */ + adi_bufferRxPecTest[i + 6u] = 0x00u; + adi_bufferRxPecTest[i + 7u] = 0x2Bu; + } + + for (ADI_AUXILIARY_STORE_LOCATION_e storeLocation = ADI_AUXILIARY_VOLTAGE; + storeLocation < ADI_AUXILIARY_STORE_LOCATION_E_MAX; + storeLocation++) { + for (ADI_AUXILIARY_REGISTER_TYPE_e registerType = ADI_AUXILIARY_REGISTER; + registerType < ADI_AUXILIARY_REGISTER_TYPE_E_MAX; + registerType++) { + /* Set store buffer with store location */ + switch (storeLocation) { + case ADI_AUXILIARY_VOLTAGE: + pGpioVoltageTable = adi_stateBase.data.allGpioVoltages; + break; + case ADI_REDUNDANT_AUXILIARY_VOLTAGE: + pGpioVoltageTable = adi_stateBase.data.allGpioVoltagesRedundant; + break; + case ADI_AUXILIARY_VOLTAGE_OPEN_WIRE: + pGpioVoltageTable = adi_stateBase.data.allGpioVoltageOpenWire; + break; + default: + break; + } + /* Reset cell voltage values */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t c = 0u; c < BS_NR_OF_GPIOS_PER_MODULE; c++) { + pGpioVoltageTable->gpioVoltages_mV[s][c + (m * BS_NR_OF_GPIOS_PER_MODULE)] = 0; + } + } + /* Reset PEC error flags */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + adi_stateBase.data.errorTable->crcIsOk[s][m] = true; + } + + /* Now get voltages by reading data (mocked) and storing it to the voltage table */ + ADI_GetGpioVoltages(&adi_stateBase, registerType, storeLocation); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t c = 0u; c < BS_NR_OF_GPIOS_PER_MODULE; c++) { + /* Everything OK, the values must be stored */ + TEST_ASSERT_EQUAL( + 1884, pGpioVoltageTable->gpioVoltages_mV[s][c + (m * BS_NR_OF_GPIOS_PER_MODULE)]); + } + } + } + } + } +} + +/* externalized static functions tests */ +void testADI_SaveRxToGpioVoltageBuffer(void) { + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_SaveRxToGpioVoltageBuffer( + NULL_PTR, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, ADI_AUXILIARY_VOLTAGE)); + /* Test invalid data */ + TEST_ASSERT_FAIL_ASSERT( + TEST_ADI_SaveRxToGpioVoltageBuffer(&adi_stateBase, NULL_PTR, ADI_RESULT_REGISTER_SET_A, ADI_AUXILIARY_VOLTAGE)); + /* Test invalid register set */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, (ADI_RESULT_REGISTER_SET_E + 1u), ADI_AUXILIARY_VOLTAGE)); + /* Test invalid store location */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, ADI_AUXILIARY_STORE_LOCATION_E_MAX)); + + DATA_BLOCK_ALL_GPIO_VOLTAGES_s *pGpioVoltageTable = NULL_PTR; + + /* Test three cases for each store location: + -raw buffer contains cleared values, values must not be stored + -PEC error set, values must not be stored + -everything OK, values must be stored */ + for (ADI_AUXILIARY_STORE_LOCATION_e storeLocation = ADI_AUXILIARY_VOLTAGE; + storeLocation < ADI_AUXILIARY_STORE_LOCATION_E_MAX; + storeLocation++) { + /* Set store buffer with store location */ + switch (storeLocation) { + case ADI_AUXILIARY_VOLTAGE: + pGpioVoltageTable = adi_stateBase.data.allGpioVoltages; + break; + case ADI_REDUNDANT_AUXILIARY_VOLTAGE: + pGpioVoltageTable = adi_stateBase.data.allGpioVoltagesRedundant; + break; + case ADI_AUXILIARY_VOLTAGE_OPEN_WIRE: + pGpioVoltageTable = adi_stateBase.data.allGpioVoltageOpenWire; + break; + default: + break; + } + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + /* First test: buffer contains cleared values */ + /* Prepare voltage data */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Parse all voltages contained in one register */ + for (uint16_t c = 0u; c < ADI_MAX_NUMBER_OF_GPIO_VOLTAGES_IN_REGISTER; c++) { + /* Set raw data, corresponds to cleared values */ + uint8_t bufferMSB = (ADI_REGISTER_CLEARED_VALUE & 0xFF00u) >> 8u; + uint8_t bufferLSB = ADI_REGISTER_CLEARED_VALUE & 0xFFu; + /* Set receive buffer with raw data */ + adi_dataReceive[(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES) + 1u] = + bufferMSB; + adi_dataReceive[(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = + bufferLSB; + } + } + /* Reset cell voltage values */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t c = 0u; c < BS_NR_OF_GPIOS_PER_MODULE; c++) { + pGpioVoltageTable->gpioVoltages_mV[s][c + (m * BS_NR_OF_GPIOS_PER_MODULE)] = 0; + } + } + /* Reset PEC error flags */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + adi_stateBase.data.errorTable->crcIsOk[s][m] = true; + } + /* Save buffer to store location */ + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, storeLocation); + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_B, storeLocation); + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_C, storeLocation); + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_D, storeLocation); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t c = 0u; c < BS_NR_OF_GPIOS_PER_MODULE; c++) { + /* As cleared value are stored in buffer, they must not be stored in the voltage table */ + TEST_ASSERT_EQUAL(0, pGpioVoltageTable->gpioVoltages_mV[s][c + (m * BS_NR_OF_GPIOS_PER_MODULE)]); + } + } + /* Second test: wrong PEC */ + /* Prepare voltage data */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Parse all voltages contained in one register */ + for (uint16_t c = 0u; c < ADI_MAX_NUMBER_OF_GPIO_VOLTAGES_IN_REGISTER; c++) { + /* Set raw data, corresponds to a cell voltage of 1884mV */ + uint8_t bufferMSB = 0x0Au; + uint8_t bufferLSB = 0x01u; + /* Set receive buffer with raw data */ + adi_dataReceive[(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES) + 1u] = + bufferMSB; + adi_dataReceive[(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = + bufferLSB; + } + } + /* Reset cell voltage values */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t c = 0u; c < BS_NR_OF_GPIOS_PER_MODULE; c++) { + pGpioVoltageTable->gpioVoltages_mV[s][c + (m * BS_NR_OF_GPIOS_PER_MODULE)] = 0; + } + } + /* Set PEC error flags */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + adi_stateBase.data.errorTable->crcIsOk[s][m] = false; + } + /* Save buffer to store location */ + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, storeLocation); + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_B, storeLocation); + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_C, storeLocation); + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_D, storeLocation); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t c = 0u; c < BS_NR_OF_GPIOS_PER_MODULE; c++) { + /* As PEC error is detected, the values must not be stored */ + TEST_ASSERT_EQUAL(0, pGpioVoltageTable->gpioVoltages_mV[s][c + (m * BS_NR_OF_GPIOS_PER_MODULE)]); + } + } + /* Third test: store values */ + /* Prepare voltage data */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Parse all voltages contained in one register */ + for (uint16_t c = 0u; c < ADI_MAX_NUMBER_OF_GPIO_VOLTAGES_IN_REGISTER; c++) { + /* Set raw data, corresponds to a cell voltage of 1884mV */ + uint8_t bufferMSB = 0x0Au; + uint8_t bufferLSB = 0x01u; + /* Set receive buffer with raw data */ + adi_dataReceive + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + (ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES)) + 1u] = bufferMSB; + adi_dataReceive + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + (ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = bufferLSB; + } + } + /* Reset cell voltage values */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t c = 0u; c < BS_NR_OF_GPIOS_PER_MODULE; c++) { + pGpioVoltageTable->gpioVoltages_mV[s][c + (m * BS_NR_OF_GPIOS_PER_MODULE)] = 0; + } + } + /* Reset PEC error flags */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + adi_stateBase.data.errorTable->crcIsOk[s][m] = true; + } + /* Save buffer to store location */ + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, storeLocation); + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_B, storeLocation); + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_C, storeLocation); + TEST_ADI_SaveRxToGpioVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_D, storeLocation); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t c = 0u; c < BS_NR_OF_GPIOS_PER_MODULE; c++) { + /* Everything OK, the values must be stored */ + TEST_ASSERT_EQUAL(1884, pGpioVoltageTable->gpioVoltages_mV[s][c + (m * BS_NR_OF_GPIOS_PER_MODULE)]); + } + } + } + } +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_helpers.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_helpers.c new file mode 100644 index 00000000..62a360ce --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_helpers.c @@ -0,0 +1,1140 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_helpers.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockos.h" +#include "Mockspi.h" + +#include "adi_ades1830_helpers_test-data-rdb.h" +#include "adi_ades1830_helpers_test-data-wdb.h" +#include "adi_ades183x_buffers.h" /* use the real buffer configuration */ +#include "adi_ades183x_commands.h" /* use the real command config */ +#include "adi_ades183x_commands_voltages.h" /* use the real command config */ +#include "adi_ades183x_defs.h" +#include "adi_ades183x_helpers.h" +#include "adi_ades183x_pec.h" +#include "spi_cfg-helper.h" +#include "test_assert_helper.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +/* contains the expected output matrix for ADI_ReadDataBits */ +TEST_SOURCE_FILE("adi_ades1830_helpers_test-data-rdb.c") +TEST_SOURCE_FILE("adi_ades1830_helpers_test-data-wdb.c") +TEST_SOURCE_FILE("adi_ades183x_buffers.c") +TEST_SOURCE_FILE("adi_ades183x_commands.c") +TEST_SOURCE_FILE("adi_ades183x_commands_voltages.c") +TEST_SOURCE_FILE("adi_ades183x_helpers.c") + +TEST_INCLUDE_PATH("../../src/app/application/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/* contains the expected output matrix for ADI_WriteDataBits */ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/** SPI data configuration struct for ADI communication */ +static spiDAT1_t spi_kAdiDataConfig[BS_NR_OF_STRINGS] = { + { /* struct is implemented in the TI HAL and uses uppercase true and false */ + .CS_HOLD = TRUE, /* If true, HW chip select kept active between words */ + .WDEL = FALSE, /* Activation of delay between words */ + .DFSEL = SPI_FMT_0, /* Data word format selection */ + .CSNR = SPI_HARDWARE_CHIP_SELECT_2_ACTIVE}, +}; + +/** + * SPI interface configuration for ADI communication + * This is a list of structs because of multi string + */ +SPI_INTERFACE_CONFIG_s spi_adiInterface[BS_NR_OF_STRINGS] = { + { + .pConfig = &spi_kAdiDataConfig[0u], + .pNode = spiREG1, + .pGioPort = &(spiREG1->PC3), + .csPin = 2u, + .csType = SPI_CHIP_SELECT_HARDWARE, + }, +}; + +static uint16_t adi_bufferRxPecTest[ADI_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; +static uint16_t adi_bufferTxPecTest[ADI_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; +static ADI_ERROR_TABLE_s adi_errorTableTest = {0}; + +static ADI_STATE_s adi_stateBaseTest = { + .data.txBuffer = adi_bufferTxPecTest, + .data.rxBuffer = adi_bufferRxPecTest, + .data.errorTable = &adi_errorTableTest, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +void testADI_TransmitCommand(void) { + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Initialize command counter to a definite value */ + adi_stateBaseTest.data.commandCounter[s][m] = 3u; + } + } + + SPI_TransmitDummyByte_IgnoreAndReturn(STD_OK); + SPI_TransmitData_IgnoreAndReturn(STD_OK); + + /* TransmitCommand(): used for commands without data */ + /* SNAP: command without data , must increase command counter */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + ADI_CopyCommandBits(adi_cmdSnap, adi_command); + ADI_TransmitCommand(adi_command, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Check that command counter was increased */ + TEST_ASSERT_EQUAL(4u, adi_stateBaseTest.data.commandCounter[s][m]); + } + } +} + +void testADI_CopyCommandBits(void) { + const uint16_t testSourceCommand[ADI_COMMAND_DEFINITION_LENGTH] = {1u, 2u, 3u, 4u}; + uint16_t testDestinationCommand[ADI_COMMAND_DEFINITION_LENGTH] = {0u, 0u, 0u, 0u}; + + /* invalid sourceCommand */ + TEST_ASSERT_FAIL_ASSERT(ADI_CopyCommandBits(NULL_PTR, NULL_PTR)); + /* invalid destinationCommand */ + TEST_ASSERT_FAIL_ASSERT(ADI_CopyCommandBits(testSourceCommand, NULL_PTR)); + + /* copy command and test that after calling the function both arrays have + the same values for each index */ + ADI_CopyCommandBits(testSourceCommand, testDestinationCommand); + for (uint8_t i = 0; i < ADI_COMMAND_DEFINITION_LENGTH; i++) { + TEST_ASSERT_EQUAL(testSourceCommand[i], testDestinationCommand[i]); + } +} + +void testADI_IncrementCommandCounter(void) { + /* Test increment without roll over */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Initialize command counter to a definite value */ + adi_stateBaseTest.data.commandCounter[s][m] = 3u; + } + /* Increment command counter */ + TEST_ADI_IncrementCommandCounter(&adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Check that command counter was incremented correctly */ + TEST_ASSERT_EQUAL(4u, adi_stateBaseTest.data.commandCounter[s][m]); + } + } + + /* Test increment with roll over */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Initialize command counter to maximum value */ + adi_stateBaseTest.data.commandCounter[s][m] = ADI_COMMAND_COUNTER_MAX_VALUE; + } + /* Increment command counter */ + TEST_ADI_IncrementCommandCounter(&adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Check that command counter was incremented correctly */ + TEST_ASSERT_EQUAL(ADI_COMMAND_COUNTER_RESTART_VALUE, adi_stateBaseTest.data.commandCounter[s][m]); + } + } +} + +void testADI_WriteCommandConfigurationBits(void) { + /* Start with ADCV command, store all command bytes in one variable */ + uint16_t modifiedCommand = (((uint16_t)ADI_ADCV_BYTE0) << 8u) | ADI_ADCV_BYTE1; + /* Modify configuration bits */ + modifiedCommand |= (uint16_t)((1u & ADI_ADCV_RD_LEN) << ADI_ADCV_RD_POS); + modifiedCommand |= (uint16_t)((1u & ADI_ADCV_CONT_LEN) << ADI_ADCV_CONT_POS); + modifiedCommand &= (uint16_t) ~((1u & ADI_ADCV_DCP_LEN) << ADI_ADCV_DCP_POS); + modifiedCommand |= (uint16_t)((1u & ADI_ADCV_RSTF_LEN) << ADI_ADCV_RSTF_POS); + modifiedCommand &= (uint16_t) ~((1u & ADI_ADCV_OW01_LEN) << ADI_ADCV_OW01_POS); + + /* Now modify same configuration bits with ADI_WriteCommandConfigurationBits() */ + ADI_CopyCommandBits(adi_cmdAdcv, adi_command); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RD_POS, ADI_ADCV_RD_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_CONT_POS, ADI_ADCV_CONT_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_DCP_POS, ADI_ADCV_DCP_LEN, 0u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_RSTF_POS, ADI_ADCV_RSTF_LEN, 1u); + ADI_WriteCommandConfigurationBits(adi_command, ADI_ADCV_OW01_POS, ADI_ADCV_OW01_LEN, 0u); + + /* Check that function produces the same command as the manual modification */ + TEST_ASSERT_EQUAL((modifiedCommand & 0xFF00u) >> 8u, adi_command[0u]); + TEST_ASSERT_EQUAL(modifiedCommand & 0xFFu, adi_command[1u]); +} + +void testADI_ReadDataBits(void) { + uint8_t dummyData = 0u; + uint8_t dummyDataStorage = 0u; + const uint8_t invalidPosition = ADI_MAX_BIT_POSITION_IN_BYTE + 1u; + const uint8_t validPosition = 0u; + const uint8_t invalidMask = 0u; + const uint8_t validMask = 1u; + /* first argument 'receivedData' accepts the whole parameter range */ + /* invalid 'pDataToRead' pointer (second argument, FIRST assert) */ + TEST_ASSERT_FAIL_ASSERT(ADI_ReadDataBits(dummyData, NULL_PTR, validPosition, validMask)); + /* invalid 'position' (third argument, SECOND assert) */ + TEST_ASSERT_FAIL_ASSERT(ADI_ReadDataBits(dummyData, &dummyDataStorage, invalidPosition, validMask)); + /* invalid 'mask' (fourth argument, THIRD assert) */ + TEST_ASSERT_FAIL_ASSERT(ADI_ReadDataBits(dummyData, &dummyDataStorage, validPosition, invalidMask)); + + /* tests with valid input */ + uint8_t result = 0u; + for (uint8_t i = 0; i < TEST_MATRIX_SIZE_READ_DATA_BITS; i++) { + for (uint8_t j = 0; j < TEST_MATRIX_SIZE_READ_DATA_BITS; j++) { + for (uint8_t k = 0; k < TEST_MATRIX_SIZE_READ_DATA_BITS; k++) { + ADI_ReadDataBits( + testReadDataBitsDataReceivedData[i], + &result, + testReadDataBitsDataPositions[j], + testReadDataBitsDataMasks[k]); + TEST_ASSERT_EQUAL(testReadDataBitsExpectedDataResults[i][j][k], result); + } + } + } +} + +void testADI_ReadRegister(void) { + SPI_TransmitDummyByte_IgnoreAndReturn(STD_OK); + SPI_TransmitReceiveDataDma_IgnoreAndReturn(STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + + /* Test when PEC corresponds to data: all flags in error table must indicate that PEC is OK */ + /* Prepare read data */ + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Six bytes of data */ + adi_bufferRxPecTest + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 0u + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = + 0x12u; + adi_bufferRxPecTest + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 1u + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = + 0x34u; + adi_bufferRxPecTest + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 2u + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = + 0x56u; + adi_bufferRxPecTest + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 3u + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = + 0x78u; + adi_bufferRxPecTest + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 4u + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = + 0x9Au; + adi_bufferRxPecTest + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 5u + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = + 0xBCu; + /* In first byte of PEC, command counter (first 6 bits) + two MSB bits of PEC*/ + adi_bufferRxPecTest + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 6u + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = + 0xDCu; + /* Second byte of PEC */ + adi_bufferRxPecTest + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 7u + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = + 0x53u; + } + /* Call read function */ + ADI_CopyCommandBits(adi_cmdRdcva, adi_command); + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + ADI_ReadRegister(adi_command, adi_dataReceive, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* All PEC values must be OK */ + TEST_ASSERT_EQUAL(true, adi_stateBaseTest.data.errorTable->crcIsOk[s][m]); + } + } + + /* Test with wrong PEC*/ + /* Modify data for module 0, without updating PEC; 0x78u is the correct value corresponding to the PEC */ + adi_bufferRxPecTest + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + 3u + (0u * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = + 0x78u + 1u; + /* Call read function */ + ADI_CopyCommandBits(adi_cmdRdcva, adi_command); + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + ADI_ReadRegister(adi_command, adi_dataReceive, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* All PEC values must be OK */ + if (m > 0u) { + /* All but first module: there must be no PEC error */ + TEST_ASSERT_EQUAL(true, adi_stateBaseTest.data.errorTable->crcIsOk[s][m]); + } else { + /* First module: there must be a PEC error */ + TEST_ASSERT_EQUAL(false, adi_stateBaseTest.data.errorTable->crcIsOk[s][m]); + } + } + } + + /* Test command counter correct value */ + /* Set value stored by driver */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* 0xDC is the value stored in the first PEC byte in the prepared received data. + There the first six bits corresponds to the command counter so the mask 0xFC + is used to extract the command counter bits. */ + adi_stateBaseTest.data.commandCounter[s][m] = (0xDCu & 0xFCu) >> 2u; + /* Command counter flags are set at initialization, so it must be done before the test */ + adi_stateBaseTest.data.errorTable->commandCounterIsOk[s][m] = true; + } + } + /* Call read function */ + ADI_CopyCommandBits(adi_cmdRdcva, adi_command); + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + ADI_ReadRegister(adi_command, adi_dataReceive, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* All command counter values must be OK */ + TEST_ASSERT_EQUAL(true, adi_stateBaseTest.data.errorTable->commandCounterIsOk[s][m]); + } + } + + /* Test command counter wrong value */ + /* Set value stored by driver */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* 0xDC is the value stored in the first PEC byte in the prepared received data. + There the first six bits corresponds to the command counter so the mask 0xFC + is used to extract the command counter bits. */ + adi_stateBaseTest.data.commandCounter[s][m] = (0xDCu & 0xFCu) >> 2u; + if (m == 0u) { + /* Set wrong command counter for first module */ + adi_stateBaseTest.data.commandCounter[s][m]++; + } + /* Command counter flags are set at initialization, so it must be done before the test */ + adi_stateBaseTest.data.errorTable->commandCounterIsOk[s][m] = true; + } + } + /* Call read function */ + ADI_CopyCommandBits(adi_cmdRdcva, adi_command); + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + ADI_ReadRegister(adi_command, adi_dataReceive, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Test command counter values */ + if (m > 0u) { + /* All but first module: there must be no command counter error */ + TEST_ASSERT_EQUAL(true, adi_stateBaseTest.data.errorTable->commandCounterIsOk[s][m]); + } else { + /* First module: there must be a command counter error */ + TEST_ASSERT_EQUAL(false, adi_stateBaseTest.data.errorTable->commandCounterIsOk[s][m]); + } + } + } +} + +void testADI_StoredConfigurationWriteToAfe(void) { + /* Test invalid register set */ + TEST_ASSERT_FAIL_ASSERT(ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_E_MAX, &adi_stateBaseTest)); + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT(ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_A, NULL_PTR)); + + uint8_t frameLength = ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + ((ADI_RDCFGA_LEN + ADI_PEC_SIZE_IN_BYTES) * ADI_N_ADI); + /* SPI functions called by write register */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + + /* First test: matching data in written and read configuration */ + + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t byte = 0; byte < ADI_MAX_REGISTER_SIZE_IN_BYTES; byte++) { + /* Write same data to both table for configuration register A */ + adi_configurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + adi_readConfigurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + /* Write same data to both table for configuration register B */ + adi_configurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte; + adi_readConfigurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte; + } + } + for (uint16_t i = 4u; i < ADI_N_BYTES_FOR_DATA_TRANSMISSION; i += 8) { + /* Set receive buffer with raw data */ + adi_bufferRxPecTest[i] = 0u; + adi_bufferRxPecTest[i + 1u] = 1u; + adi_bufferRxPecTest[i + 2u] = 2u; + adi_bufferRxPecTest[i + 3u] = 3u; + adi_bufferRxPecTest[i + 4u] = 4u; + adi_bufferRxPecTest[i + 5u] = 5u; + /* Two PEC bytes; check will fail but unused in this test */ + adi_bufferRxPecTest[i + 6u] = 0u; + adi_bufferRxPecTest[i + 7u] = 0u; + } + + /* SPI functions called by write register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by read register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* Matching written and read data: function must return STD_OK */ + TEST_ASSERT_EQUAL(STD_OK, ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_A, &adi_stateBaseTest)); + /* SPI functions called by write register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by read register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + /* Matching written and read data: function must return STD_OK */ + TEST_ASSERT_EQUAL(STD_OK, ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_B, &adi_stateBaseTest)); + + /* Second test: unmatching data in written and read configuration */ + + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t byte = 0; byte < ADI_MAX_REGISTER_SIZE_IN_BYTES; byte++) { + /* Write different data to tables for configuration register A */ + adi_configurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + adi_readConfigurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte + 1u; + /* Write different data to tables for configuration register B */ + adi_configurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte; + adi_readConfigurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte + 1u; + } + } + for (uint16_t i = 4u; i < ADI_N_BYTES_FOR_DATA_TRANSMISSION; i += 8) { + /* Set receive buffer with raw data */ + adi_bufferRxPecTest[i] = 0u + 1u; + adi_bufferRxPecTest[i + 1u] = 1u + 1u; + adi_bufferRxPecTest[i + 2u] = 2u + 1u; + adi_bufferRxPecTest[i + 3u] = 3u + 1u; + adi_bufferRxPecTest[i + 4u] = 4u + 1u; + adi_bufferRxPecTest[i + 5u] = 5u + 1u; + /* Two PEC bytes; check will fail but unused in this test */ + adi_bufferRxPecTest[i + 6u] = 0u; + adi_bufferRxPecTest[i + 7u] = 0u; + } + + /* SPI functions called by write register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by read register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* Mismatching written and read data: function must return STD_NOT_OK */ + TEST_ASSERT_EQUAL(STD_NOT_OK, ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_A, &adi_stateBaseTest)); + /* SPI functions called by write register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by read register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + /* Mismatching written and read data: function must return STD_NOT_OK */ + TEST_ASSERT_EQUAL(STD_NOT_OK, ADI_StoredConfigurationWriteToAfe(ADI_CFG_REGISTER_SET_B, &adi_stateBaseTest)); + } +} + +void testADI_StoredConfigurationWriteToAfeGlobal(void) { + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT(ADI_StoredConfigurationWriteToAfeGlobal(NULL_PTR)); + + uint8_t frameLength = ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + ((ADI_RDCFGA_LEN + ADI_PEC_SIZE_IN_BYTES) * ADI_N_ADI); + /* SPI functions called by write register */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + + /* First test: matching data in written and read configuration */ + + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Reset all configuration error flags to no error */ + adi_stateBaseTest.data.errorTable->configurationAIsOk[s][m] = true; + adi_stateBaseTest.data.errorTable->configurationBIsOk[s][m] = true; + for (uint8_t byte = 0; byte < ADI_MAX_REGISTER_SIZE_IN_BYTES; byte++) { + /* Write same data to both table for configuration register A */ + adi_configurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + adi_readConfigurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + /* Write same data to both table for configuration register B */ + adi_configurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte; + adi_readConfigurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte; + } + } + for (uint16_t i = 4u; i < ADI_N_BYTES_FOR_DATA_TRANSMISSION; i += 8) { + /* Set receive buffer with raw data */ + adi_bufferRxPecTest[i] = 0u; + adi_bufferRxPecTest[i + 1u] = 1u; + adi_bufferRxPecTest[i + 2u] = 2u; + adi_bufferRxPecTest[i + 3u] = 3u; + adi_bufferRxPecTest[i + 4u] = 4u; + adi_bufferRxPecTest[i + 5u] = 5u; + /* Two PEC bytes; check will fail but unused in this test */ + adi_bufferRxPecTest[i + 6u] = 0u; + adi_bufferRxPecTest[i + 7u] = 0u; + } + + /* SPI functions called by write register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by read register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by write register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by read register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + ADI_StoredConfigurationWriteToAfeGlobal(&adi_stateBaseTest); + /* Matching written and read data: error flags must not be set */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Reset all configuration error flags to no error */ + adi_stateBaseTest.data.errorTable->configurationAIsOk[s][m] = true; + adi_stateBaseTest.data.errorTable->configurationBIsOk[s][m] = true; + } + + /* Second test: unmatching data in written and read configuration */ + + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Reset all configuration error flags to no error */ + adi_stateBaseTest.data.errorTable->configurationAIsOk[s][m] = true; + adi_stateBaseTest.data.errorTable->configurationBIsOk[s][m] = true; + for (uint8_t byte = 0; byte < ADI_MAX_REGISTER_SIZE_IN_BYTES; byte++) { + /* Write different data to tables for configuration register A */ + adi_configurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + adi_readConfigurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte + 1u; + /* Write different data to tables for configuration register B */ + adi_configurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte; + adi_readConfigurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte + 1u; + } + } + for (uint16_t i = 4u; i < ADI_N_BYTES_FOR_DATA_TRANSMISSION; i += 8) { + /* Set receive buffer with raw data */ + adi_bufferRxPecTest[i] = 0u + 1u; + adi_bufferRxPecTest[i + 1u] = 1u + 1u; + adi_bufferRxPecTest[i + 2u] = 2u + 1u; + adi_bufferRxPecTest[i + 3u] = 3u + 1u; + adi_bufferRxPecTest[i + 4u] = 4u + 1u; + adi_bufferRxPecTest[i + 5u] = 5u + 1u; + /* Two PEC bytes; check will fail but unused in this test */ + adi_bufferRxPecTest[i + 6u] = 0u; + adi_bufferRxPecTest[i + 7u] = 0u; + } + + /* Mismatching written and read data: a retry is made once for each register + so the write and read functions are called twice */ + for (uint8_t try = 0u; try < 2u; try++) { /* SPI functions called by write register */ + /* SPI functions called by write register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by read register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by write register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* SPI functions called by read register */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + frameLength, + STD_OK); + } + ADI_StoredConfigurationWriteToAfeGlobal(&adi_stateBaseTest); + /* Mismatching written and read data: error flags must be set */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Reset all configuration error flags to no error */ + adi_stateBaseTest.data.errorTable->configurationAIsOk[s][m] = false; + adi_stateBaseTest.data.errorTable->configurationBIsOk[s][m] = false; + } + } +} + +void testADI_CheckConfigurationRegister(void) { + /* Test invalid register set */ + TEST_ASSERT_FAIL_ASSERT(ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_E_MAX, &adi_stateBaseTest)); + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT(ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_A, NULL_PTR)); + + /* adi_configurationRegisterAgroup[] and adi_configurationRegisterBgroup[] contain the driver copy + of the configuration register. The configuration must be read from the daisy-chain and stored in + adi_readConfigurationRegisterAgroup[] and adi_readConfigurationRegisterBgroup[]. + ADI_CheckConfigurationRegister() compares both tables for each configuration register. */ + + /* Test for identical data */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Reset all configuration error flags to no error */ + adi_stateBaseTest.data.errorTable->configurationAIsOk[s][m] = true; + adi_stateBaseTest.data.errorTable->configurationBIsOk[s][m] = true; + for (uint8_t byte = 0; byte < ADI_MAX_REGISTER_SIZE_IN_BYTES; byte++) { + /* Write same data to both table for configuration register A */ + adi_configurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + adi_readConfigurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + /* Write same data to both table for configuration register B */ + adi_configurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte; + adi_readConfigurationRegisterBgroup[s][byte + (m * ADI_WRCFGB_LEN)] = byte; + } + } + /* Call check function */ + ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_A, &adi_stateBaseTest); + ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_B, &adi_stateBaseTest); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* There must be no configuration error */ + TEST_ASSERT_EQUAL(true, adi_stateBaseTest.data.errorTable->configurationAIsOk[s][m]); + TEST_ASSERT_EQUAL(true, adi_stateBaseTest.data.errorTable->configurationBIsOk[s][m]); + } + } + + /* Test for mismatching data */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Reset all configuration error flags to no error */ + adi_stateBaseTest.data.errorTable->configurationAIsOk[s][m] = true; + adi_stateBaseTest.data.errorTable->configurationBIsOk[s][m] = true; + for (uint8_t byte = 0; byte < ADI_MAX_REGISTER_SIZE_IN_BYTES; byte++) { + if (m > 0u) { + /* Write matching data for all modules except the first 0 */ + /* Register A */ + adi_configurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + adi_readConfigurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + /* Register B */ + adi_configurationRegisterBgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + adi_readConfigurationRegisterBgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + } else { + /* Write mismatching data for module 0 */ + /* Register A */ + adi_configurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + adi_readConfigurationRegisterAgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte + 1u; + /* Register B */ + adi_configurationRegisterBgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte; + adi_readConfigurationRegisterBgroup[s][byte + (m * ADI_WRCFGA_LEN)] = byte + 1u; + } + } + } + /* Call check function */ + ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_A, &adi_stateBaseTest); + ADI_CheckConfigurationRegister(ADI_CFG_REGISTER_SET_B, &adi_stateBaseTest); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + if (m > 0u) { + /* There must be no configuration error for modules after module 0 */ + TEST_ASSERT_EQUAL(true, adi_stateBaseTest.data.errorTable->configurationAIsOk[s][m]); + TEST_ASSERT_EQUAL(true, adi_stateBaseTest.data.errorTable->configurationBIsOk[s][m]); + } else { + /* There must be a configuration error for module 0 */ + TEST_ASSERT_EQUAL(false, adi_stateBaseTest.data.errorTable->configurationAIsOk[s][m]); + TEST_ASSERT_EQUAL(false, adi_stateBaseTest.data.errorTable->configurationBIsOk[s][m]); + } + } + } +} + +void testADI_WriteRegisterGlobal(void) { + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT( + ADI_WriteRegisterGlobal(adi_cmdWrpwma, adi_writeGlobal, ADI_PEC_NO_FAULT_INJECTION, NULL_PTR)); + /* Test invalid data to write */ + TEST_ASSERT_FAIL_ASSERT( + ADI_WriteRegisterGlobal(adi_cmdWrpwma, NULL_PTR, ADI_PEC_NO_FAULT_INJECTION, &adi_stateBaseTest)); + /* Test invalid command */ + TEST_ASSERT_FAIL_ASSERT( + ADI_WriteRegisterGlobal(NULL_PTR, adi_writeGlobal, ADI_PEC_NO_FAULT_INJECTION, &adi_stateBaseTest)); + + /* Write register global calls write register for all module + Before calling, the byte in the passed data buffer (adi_writeGlobal, size = max_register_size) are copied + to the buffer for all modules (adi_dataTransmit, size = max_register_size * number_of_modules) */ + /* Test that the copy is made correctly */ + SPI_TransmitDummyByte_IgnoreAndReturn(STD_OK); + SPI_TransmitReceiveDataDma_IgnoreAndReturn(STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + /* Prepare global data */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint16_t byte = 0u; byte < adi_cmdWrpwma[ADI_COMMAND_DATA_LENGTH_POSITION]; byte++) { + adi_writeGlobal[byte] = byte; + } + ADI_WriteRegisterGlobal(adi_cmdWrpwma, adi_writeGlobal, ADI_PEC_NO_FAULT_INJECTION, &adi_stateBaseTest); + for (uint16_t i = 0u; i < BS_NR_OF_MODULES_PER_STRING; i++) { + for (uint8_t byte = 0; byte < adi_cmdWrpwma[ADI_COMMAND_DATA_LENGTH_POSITION]; byte++) { + /* Check that global data was copied successfully for all modules */ + TEST_ASSERT_EQUAL( + adi_writeGlobal[byte], + adi_dataTransmit[byte + (i * adi_cmdWrpwma[ADI_COMMAND_DATA_LENGTH_POSITION])]); + } + } + } +} + +void testADI_ClearCommandCounter(void) { + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT(ADI_ClearCommandCounter(NULL_PTR)); + + SPI_TransmitDummyByte_IgnoreAndReturn(STD_OK); + SPI_TransmitData_IgnoreAndReturn(STD_OK); + + /* Test command counter clear */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Set value stored by driver to a value different that reset value */ + adi_stateBaseTest.data.commandCounter[s][m] = ADI_COMMAND_COUNTER_RESET_VALUE + 1u; + /* Set command counter flags to error */ + adi_stateBaseTest.data.errorTable->commandCounterIsOk[s][m] = false; + } + } + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + /* Clear command counter */ + ADI_ClearCommandCounter(&adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Value stored by driver must be set to reset value */ + TEST_ASSERT_EQUAL(ADI_COMMAND_COUNTER_RESET_VALUE, adi_stateBaseTest.data.commandCounter[s][m]); + /* Flags must be reset to no error */ + TEST_ASSERT_EQUAL(true, adi_stateBaseTest.data.errorTable->commandCounterIsOk[s][m]); + } + } +} + +void testADI_SpiTransmitReceiveData(void) { + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT( + ADI_SpiTransmitReceiveData(NULL_PTR, adi_stateBaseTest.data.txBuffer, adi_stateBaseTest.data.rxBuffer, 1u)); + /* Test invalid Tx buffer */ + TEST_ASSERT_FAIL_ASSERT( + ADI_SpiTransmitReceiveData(&adi_stateBaseTest, NULL_PTR, adi_stateBaseTest.data.rxBuffer, 1u)); + + /* Test sending a dummy byte only */ + /* Rx = NULLPTR and length = 0u */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + /* Only send dummy byte */ + SPI_TransmitDummyByte_ExpectAndReturn(&spi_adiInterface[adi_stateBaseTest.currentString], 0u, STD_OK); + ADI_SpiTransmitReceiveData(&adi_stateBaseTest, adi_stateBaseTest.data.txBuffer, NULL_PTR, 0u); + } + + /* Test sending a command without data */ + /* Rx = NULLPTR and length > 0u */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + /* First send dummy byte */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + /* Then transmit command bytes, without using DMA */ + SPI_TransmitData_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], adi_stateBaseTest.data.txBuffer, 4u, STD_OK); + ADI_SpiTransmitReceiveData(&adi_stateBaseTest, adi_stateBaseTest.data.txBuffer, NULL_PTR, 4u); + } + + /* Test transmitting a command with data */ + /* Tx and Rx != NULLPTR, length > 0u */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + /* First send dummy byte */ + SPI_TransmitDummyByte_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], ADI_SPI_WAKEUP_WAIT_TIME_US, STD_OK); + /* Then transmit command bytes and data (4 bytes command, 6 bytes data, 2 bytes PEC), using DMA */ + SPI_TransmitReceiveDataDma_ExpectAndReturn( + &spi_adiInterface[adi_stateBaseTest.currentString], + adi_stateBaseTest.data.txBuffer, + adi_stateBaseTest.data.rxBuffer, + 4u + 6u + 2u, + STD_OK); + /* When using SPI with DMA, block task and wait for notification in DMA Rx complete interrupt */ + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + ADI_SpiTransmitReceiveData( + &adi_stateBaseTest, adi_stateBaseTest.data.txBuffer, adi_stateBaseTest.data.rxBuffer, 4u + 6u + 2u); + } +} + +void testADI_StoredConfigurationFillRegisterData(void) { + uint8_t module = 0u; + ADI_CFG_REGISTER_SET_e registerSet = ADI_CFG_REGISTER_SET_A; + uint8_t registerOffset = 0u; + uint8_t data = 0u; + uint8_t position = 0u; + uint8_t mask = 1u; + + /* Test invalid register set */ + registerSet = ADI_CFG_REGISTER_SET_E_MAX; + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_StoredConfigurationFillRegisterData( + module, registerSet, registerOffset, data, position, mask, &adi_stateBaseTest)); + /* Test invalid register offset */ + registerOffset = ADI_REGISTER_OFFSET5 + 1u; + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_StoredConfigurationFillRegisterData( + module, registerSet, registerOffset, data, position, mask, &adi_stateBaseTest)); + /* Test invalid position */ + position = ADI_MAX_BIT_POSITION_IN_BYTE + 1u; + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_StoredConfigurationFillRegisterData( + module, registerSet, registerOffset, data, position, mask, &adi_stateBaseTest)); + /* Test invalid mask */ + mask = 0u; + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_StoredConfigurationFillRegisterData( + module, registerSet, registerOffset, data, position, mask, &adi_stateBaseTest)); + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_StoredConfigurationFillRegisterData( + module, registerSet, registerOffset, data, position, mask, NULL_PTR)); + + /* Test writing value in configuration register values stored by driver */ + /* First prepare data */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t offset = 0u; offset <= ADI_REGISTER_OFFSET5; offset++) { + /* Set configuration values stored by driver to 0 */ + adi_configurationRegisterAgroup[s][(m * ADI_WRCFGA_LEN) + offset] = 0u; + adi_configurationRegisterBgroup[s][(m * ADI_WRCFGB_LEN) + offset] = 0u; + } + } + } + /* Write bit positions 0b00011100 with value 5 */ + data = 5u; + position = 2u; + mask = 0x1Cu; + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t offset = 0u; offset <= ADI_REGISTER_OFFSET5; offset++) { + /* Write for all modules, all offsets */ + TEST_ADI_StoredConfigurationFillRegisterData( + m, ADI_CFG_REGISTER_SET_A, offset, data, position, mask, &adi_stateBaseTest); + TEST_ADI_StoredConfigurationFillRegisterData( + m, ADI_CFG_REGISTER_SET_B, offset, data, position, mask, &adi_stateBaseTest); + /* Target bits must be changed, other unchanged */ + TEST_ASSERT_EQUAL(0x14u, adi_configurationRegisterAgroup[s][(m * ADI_WRCFGA_LEN) + offset]); + TEST_ASSERT_EQUAL(0x14u, adi_configurationRegisterBgroup[s][(m * ADI_WRCFGB_LEN) + offset]); + } + } + } + /* Now write 0 only to module 0 at offset 1 */ + module = 0u; + registerOffset = 1u; + data = 0; + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + /* Write data */ + TEST_ADI_StoredConfigurationFillRegisterData( + module, ADI_CFG_REGISTER_SET_A, registerOffset, data, position, mask, &adi_stateBaseTest); + TEST_ADI_StoredConfigurationFillRegisterData( + module, ADI_CFG_REGISTER_SET_B, registerOffset, data, position, mask, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t offset = 0u; offset <= ADI_REGISTER_OFFSET5; offset++) { + if ((m == 0u) && (offset == 1u)) { + /* Value must be set to 0 for module 0 and offset 1 */ + TEST_ASSERT_EQUAL(0u, adi_configurationRegisterAgroup[s][(m * ADI_WRCFGA_LEN) + offset]); + TEST_ASSERT_EQUAL(0u, adi_configurationRegisterBgroup[s][(m * ADI_WRCFGB_LEN) + offset]); + } else { + /* Value must be unchanged for other modules and offsets */ + TEST_ASSERT_EQUAL(0x14u, adi_configurationRegisterAgroup[s][(m * ADI_WRCFGA_LEN) + offset]); + TEST_ASSERT_EQUAL(0x14u, adi_configurationRegisterBgroup[s][(m * ADI_WRCFGB_LEN) + offset]); + } + } + } + } +} + +void testADI_StoredConfigurationFillRegisterDataGlobal(void) { + ADI_CFG_REGISTER_SET_e registerSet = ADI_CFG_REGISTER_SET_A; + uint8_t registerOffset = 0u; + uint8_t data = 0u; + uint8_t position = 0u; + uint8_t mask = 1u; + + /* Test invalid register set */ + registerSet = ADI_CFG_REGISTER_SET_E_MAX; + TEST_ASSERT_FAIL_ASSERT(ADI_StoredConfigurationFillRegisterDataGlobal( + registerSet, registerOffset, data, position, mask, &adi_stateBaseTest)); + /* Test invalid register offset */ + registerOffset = ADI_REGISTER_OFFSET5 + 1u; + TEST_ASSERT_FAIL_ASSERT(ADI_StoredConfigurationFillRegisterDataGlobal( + registerSet, registerOffset, data, position, mask, &adi_stateBaseTest)); + /* Test invalid position */ + position = ADI_MAX_BIT_POSITION_IN_BYTE + 1u; + TEST_ASSERT_FAIL_ASSERT(ADI_StoredConfigurationFillRegisterDataGlobal( + registerSet, registerOffset, data, position, mask, &adi_stateBaseTest)); + /* Test invalid mask */ + mask = 0u; + TEST_ASSERT_FAIL_ASSERT(ADI_StoredConfigurationFillRegisterDataGlobal( + registerSet, registerOffset, data, position, mask, &adi_stateBaseTest)); + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT( + ADI_StoredConfigurationFillRegisterDataGlobal(registerSet, registerOffset, data, position, mask, NULL_PTR)); + + /* Test writing value in configuration register values stored by driver */ + /* First prepare data */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t offset = 0u; offset <= ADI_REGISTER_OFFSET5; offset++) { + /* Set configuration values stored by driver to 0 */ + adi_configurationRegisterAgroup[s][(m * ADI_WRCFGA_LEN) + offset] = 0u; + adi_configurationRegisterBgroup[s][(m * ADI_WRCFGB_LEN) + offset] = 0u; + } + } + } + /* Write bit positions 0b00011100 with value 5 */ + data = 5u; + position = 2u; + mask = 0x1Cu; + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t offset = 0u; offset <= ADI_REGISTER_OFFSET5; offset++) { + /* Write for all modules, all offsets */ + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_A, offset, data, position, mask, &adi_stateBaseTest); + ADI_StoredConfigurationFillRegisterDataGlobal( + ADI_CFG_REGISTER_SET_B, offset, data, position, mask, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* For all modules, target bits must be changed and other bits unchanged */ + TEST_ASSERT_EQUAL(0x14u, adi_configurationRegisterAgroup[s][(m * ADI_WRCFGA_LEN) + offset]); + TEST_ASSERT_EQUAL(0x14u, adi_configurationRegisterBgroup[s][(m * ADI_WRCFGB_LEN) + offset]); + } + } + } +} + +void testADI_Wait(void) { + /* invalid wait time test */ + TEST_ASSERT_FAIL_ASSERT(ADI_Wait(0u)); + + /* dummy values */ + const uint32_t waitTime = 1u; + uint32_t currentTime = 2u; + OS_GetTickCount_ExpectAndReturn(currentTime); + OS_DelayTaskUntil_Expect(¤tTime, waitTime + 1); + ADI_Wait(waitTime); +} + +void testADI_WriteDataBits(void) { + uint8_t pSentData = 0u; + uint8_t dummyData = 0u; + const uint8_t invalidPosition = ADI_MAX_BIT_POSITION_IN_BYTE + 1u; + const uint8_t validPosition = 0u; + const uint8_t invalidMask = 0u; + const uint8_t validMask = 1u; + + /* invalid 'pSentData' pointer (first argument, first assert) */ + TEST_ASSERT_FAIL_ASSERT(ADI_WriteDataBits(NULL_PTR, dummyData, validPosition, validMask)); + /* second argument 'dataToWrite' accepts the whole parameter range */ + /* invalid 'position' (third argument, SECOND assert) */ + TEST_ASSERT_FAIL_ASSERT(ADI_WriteDataBits(&pSentData, dummyData, invalidPosition, validMask)); + /* invalid 'mask' (fourth argument, THIRD assert) */ + TEST_ASSERT_FAIL_ASSERT(ADI_WriteDataBits(&pSentData, dummyData, validPosition, invalidMask)); +} + +void testADI_WriteRegister(void) { + SPI_TransmitDummyByte_IgnoreAndReturn(STD_OK); + SPI_TransmitReceiveDataDma_IgnoreAndReturn(STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + + /* Test command counter increase */ + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Set value stored by driver */ + adi_stateBaseTest.data.commandCounter[s][m] = 13u; + } + } + /* Call write configuration register group A function, increases command counter */ + ADI_CopyCommandBits(adi_cmdWrcfga, adi_command); + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + /* No fault injection: command counter must increase */ + ADI_WriteRegister(adi_command, adi_dataTransmit, ADI_PEC_NO_FAULT_INJECTION, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Check that command counter was increased */ + TEST_ASSERT_EQUAL(14u, adi_stateBaseTest.data.commandCounter[s][m]); + } + } + + /* Test no command counter increase if command PEC fault injection */ + /* Call write configuration register group A function, increases command counter */ + ADI_CopyCommandBits(adi_cmdWrcfga, adi_command); + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + ADI_WriteRegister(adi_command, adi_dataTransmit, ADI_COMMAND_PEC_FAULT_INJECTION, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Check that command counter was increased */ + TEST_ASSERT_EQUAL(14u, adi_stateBaseTest.data.commandCounter[s][m]); + } + } + + /* Test no command counter increase if data PEC fault injection */ + /* Call write configuration register group A function, increases command counter */ + ADI_CopyCommandBits(adi_cmdWrcfga, adi_command); + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBaseTest.currentString = s; + ADI_WriteRegister(adi_command, adi_dataTransmit, ADI_DATA_PEC_FAULT_INJECTION, &adi_stateBaseTest); + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Check that command counter was increased */ + TEST_ASSERT_EQUAL(14u, adi_stateBaseTest.data.commandCounter[s][m]); + } + } +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_initialization.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_initialization.c new file mode 100644 index 00000000..d2edd6d7 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_initialization.c @@ -0,0 +1,417 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_initialization.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockadi_ades183x_helpers.h" + +#include "adi_ades183x_buffers.h" /* use the real command config */ +#include "adi_ades183x_commands.h" /* use the real buffer configuration */ +#include "adi_ades183x_initialization.h" +#include "test_assert_helper.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_buffers.c") +TEST_SOURCE_FILE("adi_ades183x_initialization.c") + +TEST_INCLUDE_PATH("../../src/app/application/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ +static ADI_ERROR_TABLE_s adi_errorTable = {0}; /*!< init in ADI_ResetErrorTable-function */ + +ADI_STATE_s adi_stateBase = { + .data.errorTable = &adi_errorTable, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +/*========== Externalized Static Function Test Cases ========================*/ +void testADI_ClearAllFlagsInStatusRegisterGroupC(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_ClearAllFlagsInStatusRegisterGroupC(NULL_PTR)); + + const uint8_t numberExpectedCalls = 4u * 8u; + for (uint8_t i = 0; i < numberExpectedCalls; i++) { + ADI_WriteDataBits_Ignore(); + } + ADI_WriteRegisterGlobal_Ignore(); + + TEST_ADI_ClearAllFlagsInStatusRegisterGroupC(&adi_stateBase); +} + +void testADI_DisableBalancingOnStartup(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_DisableBalancingOnStartup(NULL_PTR)); + + ADI_WriteRegisterGlobal_Ignore(); + ADI_WriteRegisterGlobal_Ignore(); + TEST_ADI_DisableBalancingOnStartup(&adi_stateBase); +} + +void testADI_GetSerialIdsOfAllIcsInString(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_GetSerialIdsOfAllIcsInString(NULL_PTR)); + + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + /* First test: buffer contains cleared values */ + /* Prepare voltage data */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Set receive buffer with raw data */ + adi_dataReceive[0u + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = 0xAAu; + adi_dataReceive[1u + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = 0xBBu; + adi_dataReceive[2u + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = 0xCCu; + adi_dataReceive[3u + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = 0xDDu; + adi_dataReceive[4u + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = 0xEEu; + adi_dataReceive[5u + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = 0xFFu; + ADI_CopyCommandBits_Ignore(); + ADI_ReadRegister_Ignore(); + TEST_ADI_GetSerialIdsOfAllIcsInString(&adi_stateBase); + /* Check that Serial ID was extracted correctly from raw data */ + TEST_ASSERT_EQUAL(0xFFEEDDCCBBAAu, adi_stateBase.serialId[s][m]); + } + } +} + +void testADI_GetRevisionOfAllIcsInString(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_GetRevisionOfAllIcsInString(NULL_PTR)); + + ADI_CopyCommandBits_Ignore(); + ADI_ReadRegister_Ignore(); + for (uint16_t m = 0; m < ADI_N_ADI; m++) { + ADI_ReadDataBits_Ignore(); + } + TEST_ADI_GetRevisionOfAllIcsInString(&adi_stateBase); +} + +void testADI_ResetIirFilterOnStartup(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_ResetIirFilterOnStartup(NULL_PTR)); + + ADI_StoredConfigurationFillRegisterDataGlobal_Ignore(); + ADI_StoredConfigurationWriteToAfe_IgnoreAndReturn(STD_OK); + TEST_ADI_ResetIirFilterOnStartup(&adi_stateBase); +} +void testADI_StartContinuousCellVoltageMeasurements(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_StartContinuousCellVoltageMeasurements(NULL_PTR)); + + ADI_CopyCommandBits_Ignore(); + ADI_WriteCommandConfigurationBits_Ignore(); + ADI_WriteCommandConfigurationBits_Ignore(); + ADI_WriteCommandConfigurationBits_Ignore(); + ADI_WriteCommandConfigurationBits_Ignore(); + ADI_WriteCommandConfigurationBits_Ignore(); + ADI_TransmitCommand_Ignore(); + ADI_Wait_Ignore(); + TEST_ADI_StartContinuousCellVoltageMeasurements(&adi_stateBase); +} + +void testADI_WakeUpDaisyChain(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_WakeUpDaisyChain(NULL_PTR)); + + ADI_SpiTransmitReceiveData_Ignore(); + ADI_Wait_Ignore(); + ADI_SpiTransmitReceiveData_Ignore(); + ADI_Wait_Ignore(); + TEST_ADI_WakeUpDaisyChain(&adi_stateBase); +} + +void testADI_InitializeConfiguration(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_InitializeConfiguration(NULL_PTR)); + + /* Configuration register A */ + const uint8_t numberExpectedRegisterACalls = 12u; + for (uint8_t i = 0; i < numberExpectedRegisterACalls; i++) { + ADI_StoredConfigurationFillRegisterDataGlobal_Ignore(); + } + /* Configuration register B */ + const uint8_t numberExpectedRegisterBCalls = 9u; + for (uint8_t i = 0; i < numberExpectedRegisterBCalls; i++) { + ADI_StoredConfigurationFillRegisterDataGlobal_Ignore(); + } + + TEST_ADI_InitializeConfiguration(&adi_stateBase); +} + +void testADI_ResetErrorTable(void) { + /* Set all error flags */ + for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) { + adi_stateBase.data.errorTable->spiIsOk[stringNumber] = false; + for (uint16_t m = 0; m < ADI_N_ADI; m++) { + adi_stateBase.data.errorTable->crcIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->commandCounterIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->configurationAIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->configurationBIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->voltageRegisterContentIsNotStuck[stringNumber][m] = false; + adi_stateBase.data.errorTable->auxiliaryRegisterContentIsNotStuck[stringNumber][m] = false; + adi_stateBase.data.errorTable->adcComparisonIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->compFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->spiFltFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->filteredVoltageRangeIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->evenWireIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->oddWireIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->evenWireHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->oddWireHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->adcCompFlagsHaveNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->auxComparisonIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->auxVoltageRangeIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->analogSupplyOvervoltageFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->analogSupplyUndervoltageFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->digitalSupplyOvervoltageFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->digitalSupplyUndervoltageFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->vdeFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->oscchkFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->analogSupplyOvervoltageFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->analogSupplyUndervoltageFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->digitalSupplyOvervoltageFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->digitalSupplyUndervoltageFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->vdeFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->vdelFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->analogSupplyRangeIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->digitalSupplyRangeIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->vresRangeIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->dieTemperatureIsOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->oscchkFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->ocCounterFasterFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->ocCounterSlowerFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->thsdFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->tmodchkFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->tmodchkFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->cmedFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->smedFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->sleepFlagIsCleared[stringNumber][m] = false; + adi_stateBase.data.errorTable->cmedFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->smedFlagHasNoLatentFault[stringNumber][m] = false; + adi_stateBase.data.errorTable->initResetAuxValuesAreOk[stringNumber][m] = false; + adi_stateBase.data.errorTable->initClearedAuxValuesAreOk[stringNumber][m] = false; + } + } + /* Reset error flags */ + TEST_ADI_ResetErrorTable(&adi_stateBase); + /* Check that error flags have been reset */ + for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) { + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->spiIsOk[stringNumber]); + for (uint16_t m = 0; m < ADI_N_ADI; m++) { + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->crcIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->commandCounterIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->configurationAIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->configurationBIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->voltageRegisterContentIsNotStuck[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->auxiliaryRegisterContentIsNotStuck[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->adcComparisonIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->compFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->spiFltFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->filteredVoltageRangeIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->evenWireIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->oddWireIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->evenWireHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->oddWireHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->adcCompFlagsHaveNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->auxComparisonIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->auxVoltageRangeIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->analogSupplyOvervoltageFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->analogSupplyUndervoltageFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->digitalSupplyOvervoltageFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->digitalSupplyUndervoltageFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->vdeFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->oscchkFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->analogSupplyOvervoltageFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->analogSupplyUndervoltageFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->digitalSupplyOvervoltageFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->digitalSupplyUndervoltageFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->vdeFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->vdelFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->analogSupplyRangeIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->digitalSupplyRangeIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->vresRangeIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->dieTemperatureIsOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->oscchkFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->ocCounterFasterFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL( + true, adi_stateBase.data.errorTable->ocCounterSlowerFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->thsdFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->tmodchkFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->tmodchkFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->cmedFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->smedFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->sleepFlagIsCleared[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->cmedFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->smedFlagHasNoLatentFault[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->initResetAuxValuesAreOk[stringNumber][m]); + TEST_ASSERT_EQUAL(true, adi_stateBase.data.errorTable->initClearedAuxValuesAreOk[stringNumber][m]); + } + } +} + +/*========== Extern Function Test Cases =====================================*/ + +void testADI_InitializeMeasurement(void) { + /* invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(ADI_InitializeMeasurement(NULL_PTR)); + + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + /* real test */ + /* first block */ + for (uint8_t i = 0; i < 2u; i++) { + ADI_SpiTransmitReceiveData_Ignore(); + ADI_Wait_Ignore(); + } + for (uint16_t i = 0u; i < ADI_N_ADI; i++) { + adi_stateBase.data.errorTable->commandCounterIsOk[adi_stateBase.currentString][i] = true; + adi_stateBase.data.commandCounter[adi_stateBase.currentString][i] = ADI_COMMAND_COUNTER_RESET_VALUE; + } + ADI_ClearCommandCounter_Expect(&adi_stateBase); + ADI_ClearCommandCounter_ReturnThruPtr_adiState(&adi_stateBase); + + ADI_StoredConfigurationFillRegisterDataGlobal_Ignore(); + ADI_StoredConfigurationWriteToAfeGlobal_Ignore(); + + ADI_Wait_Ignore(); + + ADI_CopyCommandBits_Ignore(); + ADI_TransmitCommand_Ignore(); + for (uint8_t i = 0; i < 2u; i++) { + ADI_CopyCommandBits_Ignore(); + ADI_ReadRegister_Ignore(); + } + + ADI_WriteRegisterGlobal_Ignore(); + ADI_WriteRegisterGlobal_Ignore(); + ADI_StoredConfigurationFillRegisterDataGlobal_Ignore(); + ADI_StoredConfigurationWriteToAfe_ExpectAndReturn(ADI_CFG_REGISTER_SET_A, &adi_stateBase, STD_OK); + for (uint8_t i = 0; i < 4u; i++) { + for (uint8_t j = 0; j < 8u; j++) { + ADI_WriteDataBits_Ignore(); + } + } + ADI_WriteRegisterGlobal_Ignore(); + ADI_CopyCommandBits_Ignore(); + ADI_ReadRegister_Ignore(); + + for (uint16_t m = 0u; m < ADI_N_ADI; m++) { + uint8_t statusData = adi_dataReceive[(m * ADI_RDSTATC_LEN) + ADI_REGISTER_OFFSET5]; + uint8_t flagComp = 0u; + if (flagComp != 1u) { + adi_stateBase.data.errorTable->compFlagIsCleared[adi_stateBase.currentString][m] = false; + } + ADI_ReadDataBits_Expect(statusData, &flagComp, ADI_STCR5_COMP_POS, ADI_STCR5_COMP_MASK); + ADI_ReadDataBits_ReturnArrayThruPtr_pDataToRead(&flagComp, 1); + } + + /* Start continuous cell voltage measurements */ + ADI_CopyCommandBits_Ignore(); + ADI_WriteCommandConfigurationBits_Expect(adi_command, ADI_ADCV_RD_POS, ADI_ADCV_RD_LEN, 1u); + ADI_WriteCommandConfigurationBits_Expect(adi_command, ADI_ADCV_CONT_POS, ADI_ADCV_CONT_LEN, 1u); + ADI_WriteCommandConfigurationBits_Expect(adi_command, ADI_ADCV_DCP_POS, ADI_ADCV_DCP_LEN, 0u); + ADI_WriteCommandConfigurationBits_Expect(adi_command, ADI_ADCV_RSTF_POS, ADI_ADCV_RSTF_LEN, 1u); + ADI_WriteCommandConfigurationBits_Expect(adi_command, ADI_ADCV_OW01_POS, ADI_ADCV_OW01_LEN, 0u); + ADI_TransmitCommand_Ignore(); + ADI_Wait_Ignore(); + + /* Read serial ID */ + ADI_CopyCommandBits_Ignore(); + ADI_ReadRegister_Ignore(); + + /* Read revision */ + ADI_CopyCommandBits_Ignore(); + ADI_ReadRegister_Ignore(); + for (uint16_t m = 0; m < ADI_N_ADI; m++) { + ADI_ReadDataBits_Expect( + adi_dataReceive[(m * ADI_RDSTATE_LEN) + ADI_REGISTER_OFFSET5], + &(adi_stateBase.revision[adi_stateBase.currentString][m]), + ADI_STER5_REV_0_3_POS, + ADI_STER5_REV_0_3_MASK); + } + } + ADI_InitializeMeasurement(&adi_stateBase); +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_temperatures.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_temperatures.c new file mode 100644 index 00000000..580ea209 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_temperatures.c @@ -0,0 +1,160 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_temperatures.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockadi_ades183x_cfg.h" +#include "Mockadi_ades183x_helpers.h" + +#include "adi_ades183x_buffers.h" /* use the real command config */ +#include "adi_ades183x_commands.h" /* use the real buffer configuration */ +#include "adi_ades183x_temperatures.h" +#include "test_assert_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_temperatures.c") + +TEST_INCLUDE_PATH("../../src/app/application/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ +static DATA_BLOCK_CELL_TEMPERATURE_s adi_cellTemperature = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE_BASE}; +static DATA_BLOCK_ALL_GPIO_VOLTAGES_s adi_allGpioVoltage = {.header.uniqueId = DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE}; + +ADI_STATE_s adi_stateBase = { + .currentString = 0, + .data.cellTemperature = &adi_cellTemperature, + .data.allGpioVoltages = &adi_allGpioVoltage, +}; +const uint8_t adi_temperatureInputsUsed[BS_NR_OF_GPIOS_PER_MODULE] = { + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint16_t registerGpioIndex = 0u; registerGpioIndex < BS_NR_OF_GPIOS_PER_MODULE; registerGpioIndex++) { + if (adi_temperatureInputsUsed[registerGpioIndex] == 1u) { + adi_stateBase.data.allGpioVoltages + ->gpioVoltages_mV[adi_stateBase.currentString] + [(m * BS_NR_OF_GPIOS_PER_MODULE) + registerGpioIndex] = 300.0; + } + } + } + } +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +/*========== Externalized Static Function Test Cases ========================*/ +void testADI_GetTemperatures(void) { + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint16_t registerGpioIndex = 0u; registerGpioIndex < BS_NR_OF_GPIOS_PER_MODULE; registerGpioIndex++) { + ADI_ConvertGpioVoltageToTemperature_ExpectAndReturn(300, 250); + } + } + ADI_GetTemperatures(&adi_stateBase); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint16_t registerGpioIndex = 0u; registerGpioIndex < BS_NR_OF_GPIOS_PER_MODULE; registerGpioIndex++) { + for (uint8_t ts = 0; ts < registerGpioIndex; ts++) { + TEST_ASSERT_EQUAL_INT16( + 250, + adi_stateBase.data.cellTemperature->cellTemperature_ddegC[adi_stateBase.currentString][m][ts]); + } + } + } + } +} + +/*========== Extern Function Test Cases =====================================*/ +void testADI_GetStoredTemperatureIndex(void) { + /* Invalid index */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_GetStoredTemperatureIndex(BS_NR_OF_GPIOS_PER_MODULE)); + + /* All inputs used, indices must be equal */ + for (uint8_t c = 0; c < BS_NR_OF_GPIOS_PER_MODULE; c++) { + TEST_ASSERT_EQUAL_UINT16(c, TEST_ADI_GetStoredTemperatureIndex(c)); + } +} diff --git a/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_voltages.c b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_voltages.c new file mode 100644 index 00000000..b3809b01 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_voltages.c @@ -0,0 +1,629 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades1830_voltages.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockadi_ades183x_cfg.h" +#include "Mockos.h" +#include "Mockspi.h" + +#include "adi_ades183x_buffers.h" /* use the real buffer configuration */ +#include "adi_ades183x_commands.h" +#include "adi_ades183x_commands_voltages.h" +#include "adi_ades183x_defs.h" +#include "adi_ades183x_helpers.h" +#include "adi_ades183x_pec.h" +#include "adi_ades183x_voltages.h" +#include "spi_cfg-helper.h" +#include "test_assert_helper.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("adi_ades183x_buffers.c") +TEST_SOURCE_FILE("adi_ades183x_voltages.c") + +TEST_INCLUDE_PATH("../../src/app/application/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/ades1830") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/adi/common/ades183x/pec") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/database") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageTable = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageAverageTable = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageFilteredTable = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageRedundantTable = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageOpenWireEvenTable = { + .header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageOpenWireOddTable = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageAverageOpenWireTable = { + .header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static DATA_BLOCK_CELL_VOLTAGE_s adi_cellVoltageRedundantOpenWireTable = { + .header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE}; +static ADI_ERROR_TABLE_s adi_errorTable = {0}; /*!< init in ADI_ResetErrorTable-function */ +static uint16_t adi_bufferRxPecTest[ADI_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; +static uint16_t adi_bufferTxPecTest[ADI_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; + +ADI_STATE_s adi_stateBase = { + .data.txBuffer = adi_bufferTxPecTest, + .data.rxBuffer = adi_bufferRxPecTest, + .data.cellVoltage = &adi_cellVoltageTable, + .data.cellVoltageAverage = &adi_cellVoltageAverageTable, + .data.cellVoltageFiltered = &adi_cellVoltageFilteredTable, + .data.cellVoltageRedundant = &adi_cellVoltageRedundantTable, + .data.cellVoltageOpenWireEven = &adi_cellVoltageOpenWireEvenTable, + .data.cellVoltageOpenWireOdd = &adi_cellVoltageOpenWireOddTable, + .data.cellVoltageAverageOpenWire = &adi_cellVoltageAverageOpenWireTable, + .data.cellVoltageRedundantOpenWire = &adi_cellVoltageRedundantOpenWireTable, + .data.errorTable = &adi_errorTable, +}; + +ADI_COMMAND_READ_REGISTERS_s commandBytes = { + .registerA = {0}, + .registerB = {0}, + .registerC = {0}, + .registerD = {0}, + .registerE = {0}, + .registerF = {0}, +}; + +/* If this configuration is changed, testADI_GetStoredVoltageIndex() must be adapted */ +const uint8_t adi_voltageInputsUsed[ADI_MAX_SUPPORTED_CELLS] = { + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; + +/** SPI data configuration struct for ADI communication */ +static spiDAT1_t spi_kAdiDataConfig[BS_NR_OF_STRINGS] = { + { /* struct is implemented in the TI HAL and uses uppercase true and false */ + .CS_HOLD = TRUE, /* If true, HW chip select kept active between words */ + .WDEL = FALSE, /* Activation of delay between words */ + .DFSEL = SPI_FMT_0, /* Data word format selection */ + .CSNR = SPI_HARDWARE_CHIP_SELECT_2_ACTIVE}, +}; + +/** + * SPI interface configuration for ADI communication + * This is a list of structs because of multi string + */ +SPI_INTERFACE_CONFIG_s spi_adiInterface[BS_NR_OF_STRINGS] = { + { + .pConfig = &spi_kAdiDataConfig[0u], + .pNode = spiREG1, + .pGioPort = &(spiREG1->PC3), + .csPin = 2u, + .csType = SPI_CHIP_SELECT_HARDWARE, + }, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +/*========== Externalized Static Function Test Cases ========================*/ +void testADI_CopyCommandBytesCellVoltageRegister(void) { + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_CopyCommandBytesCellVoltageRegister(NULL_PTR)); + + TEST_ADI_CopyCommandBytesCellVoltageRegister(&commandBytes); + for (uint8_t i = 0u; i < ADI_COMMAND_DEFINITION_LENGTH; i++) { + TEST_ASSERT_EQUAL(adi_cmdRdcva[i], commandBytes.registerA[i]); + TEST_ASSERT_EQUAL(adi_cmdRdcvb[i], commandBytes.registerB[i]); + TEST_ASSERT_EQUAL(adi_cmdRdcvc[i], commandBytes.registerC[i]); + TEST_ASSERT_EQUAL(adi_cmdRdcvd[i], commandBytes.registerD[i]); + TEST_ASSERT_EQUAL(adi_cmdRdcve[i], commandBytes.registerE[i]); + TEST_ASSERT_EQUAL(adi_cmdRdcvf[i], commandBytes.registerF[i]); + } +} +void testADI_CopyCommandBytesAverageCellVoltageRegisters(void) { + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_CopyCommandBytesAverageCellVoltageRegisters(NULL_PTR)); + + TEST_ADI_CopyCommandBytesAverageCellVoltageRegisters(&commandBytes); + for (uint8_t i = 0u; i < ADI_COMMAND_DEFINITION_LENGTH; i++) { + TEST_ASSERT_EQUAL(adi_cmdRdaca[i], commandBytes.registerA[i]); + TEST_ASSERT_EQUAL(adi_cmdRdacb[i], commandBytes.registerB[i]); + TEST_ASSERT_EQUAL(adi_cmdRdacc[i], commandBytes.registerC[i]); + TEST_ASSERT_EQUAL(adi_cmdRdacd[i], commandBytes.registerD[i]); + TEST_ASSERT_EQUAL(adi_cmdRdace[i], commandBytes.registerE[i]); + TEST_ASSERT_EQUAL(adi_cmdRdacf[i], commandBytes.registerF[i]); + } +} +void testADI_CopyCommandBytesFilteredCellVoltageRegisters(void) { + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_CopyCommandBytesFilteredCellVoltageRegisters(NULL_PTR)); + + TEST_ADI_CopyCommandBytesFilteredCellVoltageRegisters(&commandBytes); + for (uint8_t i = 0u; i < ADI_COMMAND_DEFINITION_LENGTH; i++) { + TEST_ASSERT_EQUAL(adi_cmdRdfca[i], commandBytes.registerA[i]); + TEST_ASSERT_EQUAL(adi_cmdRdfcb[i], commandBytes.registerB[i]); + TEST_ASSERT_EQUAL(adi_cmdRdfcc[i], commandBytes.registerC[i]); + TEST_ASSERT_EQUAL(adi_cmdRdfcd[i], commandBytes.registerD[i]); + TEST_ASSERT_EQUAL(adi_cmdRdfce[i], commandBytes.registerE[i]); + TEST_ASSERT_EQUAL(adi_cmdRdfcf[i], commandBytes.registerF[i]); + } +} +void testADI_CopyCommandBytesRedundantCellVoltageRegisters(void) { + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_CopyCommandBytesRedundantCellVoltageRegisters(NULL_PTR)); + + TEST_ADI_CopyCommandBytesRedundantCellVoltageRegisters(&commandBytes); + for (uint8_t i = 0u; i < ADI_COMMAND_DEFINITION_LENGTH; i++) { + TEST_ASSERT_EQUAL(adi_cmdRdsva[i], commandBytes.registerA[i]); + TEST_ASSERT_EQUAL(adi_cmdRdsvb[i], commandBytes.registerB[i]); + TEST_ASSERT_EQUAL(adi_cmdRdsvc[i], commandBytes.registerC[i]); + TEST_ASSERT_EQUAL(adi_cmdRdsvd[i], commandBytes.registerD[i]); + TEST_ASSERT_EQUAL(adi_cmdRdsve[i], commandBytes.registerE[i]); + TEST_ASSERT_EQUAL(adi_cmdRdsvf[i], commandBytes.registerF[i]); + } +} +void testADI_ReadAndStoreVoltages(void) { + /* Invalid state */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_ReadAndStoreVoltages(NULL_PTR, &commandBytes, ADI_CELL_VOLTAGE)); + /* Invalid command bytes */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_ReadAndStoreVoltages(&adi_stateBase, NULL_PTR, ADI_CELL_VOLTAGE)); + /* Invalid store location */ + TEST_ASSERT_FAIL_ASSERT( + TEST_ADI_ReadAndStoreVoltages(&adi_stateBase, &commandBytes, ADI_VOLTAGE_STORE_LOCATION_E_MAX)); + + /* Test storing of data */ + /* Command parameter changes the register read so this has no effet due to the mocking, + as the values in the read data register are simulated */ + DATA_BLOCK_CELL_VOLTAGE_s *pVoltageTable = NULL_PTR; + + for (ADI_VOLTAGE_STORE_LOCATION_e storeLocation = ADI_CELL_VOLTAGE; + storeLocation < ADI_VOLTAGE_STORE_LOCATION_E_MAX; + storeLocation++) { + for (uint8_t registerOffset = ADI_RESULT_REGISTER_SET_A; registerOffset <= ADI_RESULT_REGISTER_SET_F; + registerOffset++) { + SPI_TransmitDummyByte_IgnoreAndReturn(STD_OK); + SPI_TransmitReceiveDataDma_IgnoreAndReturn(STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + } + + /* Set store buffer with store location */ + switch (storeLocation) { + case ADI_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltage; + break; + case ADI_AVERAGE_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltageAverage; + break; + case ADI_FILTERED_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltageFiltered; + break; + case ADI_REDUNDANT_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltageRedundant; + break; + case ADI_CELL_VOLTAGE_OPEN_WIRE_EVEN: + pVoltageTable = adi_stateBase.data.cellVoltageOpenWireEven; + break; + case ADI_CELL_VOLTAGE_OPEN_WIRE_ODD: + pVoltageTable = adi_stateBase.data.cellVoltageOpenWireOdd; + break; + case ADI_CELL_VOLTAGE_AVERAGE_OPEN_WIRE: + pVoltageTable = adi_stateBase.data.cellVoltageAverageOpenWire; + break; + case ADI_CELL_VOLTAGE_REDUNDANT_OPEN_WIRE: + pVoltageTable = adi_stateBase.data.cellVoltageRedundantOpenWire; + break; + default: + break; + } + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + /* Prepare voltage data to simulate data read from AFE registers */ + for (uint16_t i = 4u; i < ADI_N_BYTES_FOR_DATA_TRANSMISSION; i += 8) { + /* Set raw data, corresponds to a cell voltage of 1884mV */ + uint8_t bufferMSB = 0x0Au; + uint8_t bufferLSB = 0x01u; + /* Set receive buffer with raw data */ + adi_bufferRxPecTest[i] = bufferLSB; + adi_bufferRxPecTest[i + 1u] = bufferMSB; + adi_bufferRxPecTest[i + 2u] = bufferLSB; + adi_bufferRxPecTest[i + 3u] = bufferMSB; + adi_bufferRxPecTest[i + 4u] = bufferLSB; + adi_bufferRxPecTest[i + 5u] = bufferMSB; + /* Two PEC bytes */ + adi_bufferRxPecTest[i + 6u] = 0x00u; + adi_bufferRxPecTest[i + 7u] = 0x2Bu; + } + /* Reset cell voltage values */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + pVoltageTable->cellVoltage_mV[s][m][cb] = 0; + } + } + /* Reset PEC error flags */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + adi_stateBase.data.errorTable->crcIsOk[s][m] = true; + } + TEST_ADI_ReadAndStoreVoltages(&adi_stateBase, &commandBytes, storeLocation); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + /* Check that stored values corresponds to raw values */ + TEST_ASSERT_EQUAL(1884, pVoltageTable->cellVoltage_mV[s][m][cb]); + } + } + } + } +} + +void testADI_SaveRxToCellVoltageBuffer(void) { + /* Test invalid state */ + TEST_ASSERT_FAIL_ASSERT( + TEST_ADI_SaveRxToCellVoltageBuffer(NULL_PTR, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, ADI_CELL_VOLTAGE)); + /* Test invalid data */ + TEST_ASSERT_FAIL_ASSERT( + TEST_ADI_SaveRxToCellVoltageBuffer(&adi_stateBase, NULL_PTR, ADI_RESULT_REGISTER_SET_A, ADI_CELL_VOLTAGE)); + /* Test invalid register set */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, (ADI_RESULT_REGISTER_SET_F + 1u), ADI_CELL_VOLTAGE)); + /* Test invalid store location */ + TEST_ASSERT_FAIL_ASSERT(TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, ADI_VOLTAGE_STORE_LOCATION_E_MAX)); + + DATA_BLOCK_CELL_VOLTAGE_s *pVoltageTable = NULL_PTR; + + /* Test three cases for each store location: + -raw buffer contains cleared values, values must not be stored + -PEC error set, values must not be stored + -everything OK, values must be stored */ + for (ADI_VOLTAGE_STORE_LOCATION_e storeLocation = ADI_CELL_VOLTAGE; + storeLocation < ADI_VOLTAGE_STORE_LOCATION_E_MAX; + storeLocation++) { + /* Set store buffer with store location */ + switch (storeLocation) { + case ADI_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltage; + break; + case ADI_AVERAGE_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltageAverage; + break; + case ADI_FILTERED_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltageFiltered; + break; + case ADI_REDUNDANT_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltageRedundant; + break; + case ADI_CELL_VOLTAGE_OPEN_WIRE_EVEN: + pVoltageTable = adi_stateBase.data.cellVoltageOpenWireEven; + break; + case ADI_CELL_VOLTAGE_OPEN_WIRE_ODD: + pVoltageTable = adi_stateBase.data.cellVoltageOpenWireOdd; + break; + case ADI_CELL_VOLTAGE_AVERAGE_OPEN_WIRE: + pVoltageTable = adi_stateBase.data.cellVoltageAverageOpenWire; + break; + case ADI_CELL_VOLTAGE_REDUNDANT_OPEN_WIRE: + pVoltageTable = adi_stateBase.data.cellVoltageRedundantOpenWire; + break; + default: + break; + } + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + /* First test: buffer contains cleared values */ + /* Prepare voltage data */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Parse all voltages contained in one register */ + for (uint16_t c = 0u; c < ADI_MAX_NUMBER_OF_VOLTAGES_IN_REGISTER; c++) { + /* Set raw data, corresponds to cleared values */ + uint8_t bufferMSB = (ADI_REGISTER_CLEARED_VALUE & 0xFF00u) >> 8u; + uint8_t bufferLSB = ADI_REGISTER_CLEARED_VALUE & 0xFFu; + /* Set receive buffer with raw data */ + adi_dataReceive[(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES) + 1u] = + bufferMSB; + adi_dataReceive[(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = + bufferLSB; + } + } + /* Reset cell voltage values */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_STRING; cb++) { + pVoltageTable->cellVoltage_mV[s][m][cb] = 0; + } + } + /* Reset PEC error flags */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + adi_stateBase.data.errorTable->crcIsOk[s][m] = true; + } + /* Save buffer to store location */ + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_B, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_C, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_D, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_E, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_F, storeLocation); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_STRING; cb++) { + /* As cleared value are stored in buffer, they must not be stored in the voltage table */ + TEST_ASSERT_EQUAL(0, pVoltageTable->cellVoltage_mV[s][m][cb]); + } + } + /* Second test: wrong PEC */ + /* Prepare voltage data */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Parse all voltages contained in one register */ + for (uint16_t c = 0u; c < ADI_MAX_NUMBER_OF_VOLTAGES_IN_REGISTER; c++) { + /* Set raw data, corresponds to a cell voltage of 1884mV */ + uint8_t bufferMSB = 0x0Au; + uint8_t bufferLSB = 0x01u; + /* Set receive buffer with raw data */ + adi_dataReceive[(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES) + 1u] = + bufferMSB; + adi_dataReceive[(ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + (m * ADI_MAX_REGISTER_SIZE_IN_BYTES)] = + bufferLSB; + } + } + /* Reset cell voltage values */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + pVoltageTable->cellVoltage_mV[s][m][cb] = 0; + } + } + /* Set PEC error flags */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + adi_stateBase.data.errorTable->crcIsOk[s][m] = false; + } + /* Save buffer to store location */ + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_B, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_C, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_D, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_E, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_F, storeLocation); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_STRING; cb++) { + /* As PEC error is detected, the values must not be stored */ + TEST_ASSERT_EQUAL(0, pVoltageTable->cellVoltage_mV[s][m][cb]); + } + } + /* Third test: store values */ + /* Prepare voltage data */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + /* Parse all voltages contained in one register */ + for (uint16_t c = 0u; c < ADI_MAX_NUMBER_OF_VOLTAGES_IN_REGISTER; c++) { + /* Set raw data, corresponds to a cell voltage of 1884mV */ + uint8_t bufferMSB = 0x0Au; + uint8_t bufferLSB = 0x01u; + /* Set receive buffer with raw data */ + adi_dataReceive + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + (ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES)) + 1u] = bufferMSB; + adi_dataReceive + [ADI_COMMAND_AND_PEC_SIZE_IN_BYTES + (ADI_RAW_VOLTAGE_SIZE_IN_BYTES * c) + + (m * (ADI_MAX_REGISTER_SIZE_IN_BYTES + ADI_PEC_SIZE_IN_BYTES))] = bufferLSB; + } + } + /* Reset cell voltage values */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + pVoltageTable->cellVoltage_mV[s][m][cb] = 0; + } + } + /* Reset PEC error flags */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + adi_stateBase.data.errorTable->crcIsOk[s][m] = true; + } + /* Save buffer to store location */ + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_A, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_B, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_C, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_D, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_E, storeLocation); + TEST_ADI_SaveRxToCellVoltageBuffer( + &adi_stateBase, adi_dataReceive, ADI_RESULT_REGISTER_SET_F, storeLocation); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + /* Everything OK, the values must be stored */ + TEST_ASSERT_EQUAL(1884, pVoltageTable->cellVoltage_mV[s][m][cb]); + } + } + } + } +} + +/*========== Extern Function Test Cases =====================================*/ +void testADI_GetStoredVoltageIndex(void) { + /* Invalid index */ + TEST_ASSERT_FAIL_ASSERT(ADI_GetStoredVoltageIndex(ADI_MAX_SUPPORTED_CELLS)); + + /* All inputs used, indices must be equal */ + for (uint8_t c = 0u; c < ADI_MAX_SUPPORTED_CELLS; c++) { + TEST_ASSERT_EQUAL(c, ADI_GetStoredVoltageIndex(c)); + } +} + +void testADI_GetVoltages(void) { + /* Invalid pointer */ + TEST_ASSERT_FAIL_ASSERT(ADI_GetVoltages(NULL_PTR, ADI_CELL_VOLTAGE_REGISTER, ADI_CELL_VOLTAGE)); + /* Invalid register type */ + TEST_ASSERT_FAIL_ASSERT(ADI_GetVoltages(&adi_stateBase, ADI_VOLTAGE_REGISTER_TYPE_E_MAX, ADI_CELL_VOLTAGE)); + /* Invalid store location */ + TEST_ASSERT_FAIL_ASSERT( + ADI_GetVoltages(&adi_stateBase, ADI_CELL_VOLTAGE_REGISTER, ADI_VOLTAGE_STORE_LOCATION_E_MAX)); + + /* Test reading of voltages */ + + /* SPI and OS functions are ignored */ + SPI_TransmitDummyByte_IgnoreAndReturn(STD_OK); + SPI_TransmitReceiveDataDma_IgnoreAndReturn(STD_OK); + OS_WaitForNotification_IgnoreAndReturn(OS_SUCCESS); + DATA_BLOCK_CELL_VOLTAGE_s *pVoltageTable = NULL_PTR; + + /* Prepare voltage data to simulate data read from AFE registers */ + for (uint16_t i = 4u; i < ADI_N_BYTES_FOR_DATA_TRANSMISSION; i += 8) { + /* Set raw data, corresponds to a cell voltage of 1884mV */ + uint8_t bufferMSB = 0x0Au; + uint8_t bufferLSB = 0x01u; + /* Set receive buffer with raw data */ + adi_bufferRxPecTest[i] = bufferLSB; + adi_bufferRxPecTest[i + 1u] = bufferMSB; + adi_bufferRxPecTest[i + 2u] = bufferLSB; + adi_bufferRxPecTest[i + 3u] = bufferMSB; + adi_bufferRxPecTest[i + 4u] = bufferLSB; + adi_bufferRxPecTest[i + 5u] = bufferMSB; + /* Two PEC bytes */ + adi_bufferRxPecTest[i + 6u] = 0x00u; + adi_bufferRxPecTest[i + 7u] = 0x2Bu; + } + + for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { + adi_stateBase.currentString = s; + + for (ADI_VOLTAGE_STORE_LOCATION_e storeLocation = ADI_CELL_VOLTAGE; + storeLocation < ADI_VOLTAGE_STORE_LOCATION_E_MAX; + storeLocation++) { + for (ADI_VOLTAGE_REGISTER_TYPE_e registerType = ADI_CELL_VOLTAGE_REGISTER; + registerType < ADI_VOLTAGE_REGISTER_TYPE_E_MAX; + registerType++) { + switch (storeLocation) { + case ADI_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltage; + break; + case ADI_AVERAGE_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltageAverage; + break; + case ADI_FILTERED_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltageFiltered; + break; + case ADI_REDUNDANT_CELL_VOLTAGE: + pVoltageTable = adi_stateBase.data.cellVoltageRedundant; + break; + case ADI_CELL_VOLTAGE_OPEN_WIRE_EVEN: + pVoltageTable = adi_stateBase.data.cellVoltageOpenWireEven; + break; + case ADI_CELL_VOLTAGE_OPEN_WIRE_ODD: + pVoltageTable = adi_stateBase.data.cellVoltageOpenWireOdd; + break; + case ADI_CELL_VOLTAGE_AVERAGE_OPEN_WIRE: + pVoltageTable = adi_stateBase.data.cellVoltageAverageOpenWire; + break; + case ADI_CELL_VOLTAGE_REDUNDANT_OPEN_WIRE: + pVoltageTable = adi_stateBase.data.cellVoltageRedundantOpenWire; + break; + default: + break; + } + /* Reset cell voltage values */ + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + pVoltageTable->cellVoltage_mV[s][m][cb] = 0; + } + } + /* Reset PEC error flags */ + for (uint16_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) { + adi_stateBase.data.errorTable->crcIsOk[s][m] = true; + } + + /* Now get voltages by reading data (mocked) and storing it to the voltage table */ + ADI_GetVoltages(&adi_stateBase, registerType, storeLocation); + for (uint16_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + /* As cleared values are stored in buffer, they must not be stored in the voltage table */ + TEST_ASSERT_EQUAL(1884, pVoltageTable->cellVoltage_mV[s][m][cb]); + } + } + } + } + } +} diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/README.md b/tests/unit/app/driver/afe/adi/common/ades183x/README.md new file mode 100644 index 00000000..9b33d729 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/README.md @@ -0,0 +1,8 @@ +# ADI ADES183x Test Files + +**All test files in this directory are dummy test files**. + +The actual test are implemented for a specific IC of this family in the +specific directories: + +- ADES1830: ``tests/unit/app/driver/afe/adi/ades1830/*`` diff --git a/tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting_cfg.c b/tests/unit/app/driver/afe/adi/common/ades183x/api/test_adi_ades183x_afe.c similarity index 87% rename from tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting_cfg.c rename to tests/unit/app/driver/afe/adi/common/ades183x/api/test_adi_ades183x_afe.c index ad3ca0c0..b5d01e87 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting_cfg.c +++ b/tests/unit/app/driver/afe/adi/common/ades183x/api/test_adi_ades183x_afe.c @@ -40,33 +40,26 @@ */ /** - * @file test_soe_counting_cfg.c + * @file test_adi_ades183x_afe.c * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * - * @brief Test for the configuration for SOE + * @brief Test of some module * */ /*========== Includes =======================================================*/ -#include "unity.h" -#include "soe_counting_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -void testDummy(void) { -} /*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/api/test_adi_ades183x_afe_dma.c b/tests/unit/app/driver/afe/adi/common/ades183x/api/test_adi_ades183x_afe_dma.c new file mode 100644 index 00000000..cbe91d0f --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/api/test_adi_ades183x_afe_dma.c @@ -0,0 +1,65 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades183x_afe_dma.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ + +/*========== Unit Testing Framework Directives ==============================*/ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug_cfg.c b/tests/unit/app/driver/afe/adi/common/ades183x/config/test_adi_ades183x_cfg.c similarity index 87% rename from tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug_cfg.c rename to tests/unit/app/driver/afe/adi/common/ades183x/config/test_adi_ades183x_cfg.c index 7d64d69b..f47d842d 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug_cfg.c +++ b/tests/unit/app/driver/afe/adi/common/ades183x/config/test_adi_ades183x_cfg.c @@ -40,33 +40,26 @@ */ /** - * @file test_soc_debug_cfg.c + * @file test_adi_ades183x_cfg.c * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * - * @brief Test for the configuration for SOC + * @brief Test of some module * */ /*========== Includes =======================================================*/ -#include "unity.h" -#include "soc_debug_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -void testDummy(void) { -} /*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting_cfg.c b/tests/unit/app/driver/afe/adi/common/ades183x/pec/test_adi_ades183x_pec.c similarity index 87% rename from tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting_cfg.c rename to tests/unit/app/driver/afe/adi/common/ades183x/pec/test_adi_ades183x_pec.c index bf1cfa19..95d77478 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting_cfg.c +++ b/tests/unit/app/driver/afe/adi/common/ades183x/pec/test_adi_ades183x_pec.c @@ -40,33 +40,26 @@ */ /** - * @file test_soc_counting_cfg.c + * @file test_adi_ades183x_pec.c * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * - * @brief Test for the configuration for SOC + * @brief Test of some module * */ /*========== Includes =======================================================*/ -#include "unity.h" -#include "soc_counting_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -void testDummy(void) { -} /*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none_cfg.c b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x.c similarity index 87% rename from tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none_cfg.c rename to tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x.c index dd0f5a91..77211d84 100644 --- a/tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none_cfg.c +++ b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x.c @@ -40,33 +40,26 @@ */ /** - * @file test_soc_none_cfg.c + * @file test_adi_ades183x.c * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * - * @brief Test for the configuration for SOC + * @brief Test of some module * */ /*========== Includes =======================================================*/ -#include "unity.h" -#include "soc_none_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -void testDummy(void) { -} /*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_buffers.c b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_buffers.c new file mode 100644 index 00000000..353a1b46 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_buffers.c @@ -0,0 +1,65 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades183x_buffers.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ + +/*========== Unit Testing Framework Directives ==============================*/ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_commands.c b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_commands.c new file mode 100644 index 00000000..7251b714 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_commands.c @@ -0,0 +1,65 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades183x_commands.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ + +/*========== Unit Testing Framework Directives ==============================*/ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_commands_voltages.c b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_commands_voltages.c new file mode 100644 index 00000000..8d021dbb --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_commands_voltages.c @@ -0,0 +1,65 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades183x_commands_voltages.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ + +/*========== Unit Testing Framework Directives ==============================*/ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_diagnostic_w.c b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_diagnostic_w.c new file mode 100644 index 00000000..343ceb34 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_diagnostic_w.c @@ -0,0 +1,65 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades183x_diagnostic_w.c + * @author foxBMS Team + * @date 2023-10-09 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ + +/*========== Unit Testing Framework Directives ==============================*/ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_helpers.c b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_helpers.c new file mode 100644 index 00000000..83ab524d --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_helpers.c @@ -0,0 +1,65 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades183x_helpers.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ + +/*========== Unit Testing Framework Directives ==============================*/ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_initialization.c b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_initialization.c new file mode 100644 index 00000000..b870bb69 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_initialization.c @@ -0,0 +1,65 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades183x_initialization.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ + +/*========== Unit Testing Framework Directives ==============================*/ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_temperatures.c b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_temperatures.c new file mode 100644 index 00000000..3b3ebbbd --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_temperatures.c @@ -0,0 +1,65 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades183x_temperatures.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ + +/*========== Unit Testing Framework Directives ==============================*/ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_voltages.c b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_voltages.c new file mode 100644 index 00000000..2183fec5 --- /dev/null +++ b/tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_voltages.c @@ -0,0 +1,65 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_adi_ades183x_voltages.c + * @author foxBMS Team + * @date 2022-12-07 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ + +/*========== Unit Testing Framework Directives ==============================*/ + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ + +/*========== Test Cases =====================================================*/ +/* this is a dummy test file */ +/* tests/unit/app/driver/afe/adi/common/ades183x/README.md */ diff --git a/tests/unit/app/driver/afe/api/test_afe_plausibility.c b/tests/unit/app/driver/afe/api/test_afe_plausibility.c index a4b44ee5..78d99eb0 100644 --- a/tests/unit/app/driver/afe/api/test_afe_plausibility.c +++ b/tests/unit/app/driver/afe/api/test_afe_plausibility.c @@ -43,8 +43,8 @@ * @file test_afe_plausibility.c * @author foxBMS Team * @date 2020-07-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,6 +59,10 @@ #include "afe_plausibility.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") + /*========== Definitions and Implementations for Unit Test ==================*/ /** generic implementation of cell voltage limits */ diff --git a/tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe.c b/tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe.c index 9a5c3ceb..a174e08b 100644 --- a/tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe.c +++ b/tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe.c @@ -43,8 +43,8 @@ * @file test_debug_default_afe.c * @author foxBMS Team * @date 2020-05-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,13 +58,13 @@ #include "Mockdatabase.h" #include "Mockdebug_default.h" -#include "debug_default_cfg.h" - #include "afe.h" -/* it's important to mention the implementation in debug_default_afe.c -here in order to test the correct implementation */ -TEST_FILE("debug_default_afe.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("debug_default_afe.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/debug/default") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -83,7 +83,7 @@ void testAFE_TriggerIcAlwaysOk(void) { TEST_ASSERT_EQUAL(STD_OK, AFE_TriggerIc()); } -void testAFE_InitializeializeDummy(void) { +void testAFE_InitializeDummy(void) { FAKE_Initialize_ExpectAndReturn(STD_OK); TEST_ASSERT_EQUAL(STD_OK, AFE_Initialize()); } diff --git a/tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe_dma.c b/tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe_dma.c index 0e1faad4..ec3c5b80 100644 --- a/tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe_dma.c +++ b/tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe_dma.c @@ -43,8 +43,8 @@ * @file test_debug_default_afe_dma.c * @author foxBMS Team * @date 2020-06-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,13 +57,14 @@ #include "Mockdebug_default.h" #include "Mockfassert.h" -#include "debug_default_cfg.h" +#include "afe_dma.h" -#include "debug_default_afe_dma.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("debug_default_afe_dma.c") -/* it's important to mention the implementation in debug_default_afe_dma.c -here in order to test the correct implementation */ -TEST_FILE("debug_default_afe_dma.c") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/debug/default") +TEST_INCLUDE_PATH("../../src/app/driver/config") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/afe/debug/default/test_debug_default.c b/tests/unit/app/driver/afe/debug/default/test_debug_default.c index 9b034c9b..cec17342 100644 --- a/tests/unit/app/driver/afe/debug/default/test_debug_default.c +++ b/tests/unit/app/driver/afe/debug/default/test_debug_default.c @@ -43,8 +43,8 @@ * @file test_debug_default.c * @author foxBMS Team * @date 2020-09-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,6 @@ #include "Mockos.h" #include "battery_cell_cfg.h" -#include "debug_default_cfg.h" #include "afe.h" #include "debug_default.h" @@ -67,9 +66,12 @@ #include #include -/* it's important to mention the implementation in debug_default.c -here in order to test the correct implementation */ -TEST_FILE("debug_default.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("debug_default.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/debug/default") +TEST_INCLUDE_PATH("../../src/app/engine/diag") /*========== Definitions and Implementations for Unit Test ==================*/ #define FAKE_CELL_VOLTAGE_mV (BC_VOLTAGE_NOMINAL_mV) @@ -205,17 +207,20 @@ void testFAKE_SetFirstMeasurementCycleFinished(void) { .data.slaveControl = &test_fake_slaveControlCompare, }; - uint16_t i = 0; - for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { - for (i = 0; i < BS_NR_OF_CELL_BLOCKS_PER_STRING; i++) { - test_fake_stateCompare.data.cellVoltage->cellVoltage_mV[s][i] = FAKE_CELL_VOLTAGE_mV; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + test_fake_stateCompare.data.cellVoltage->cellVoltage_mV[s][m][cb] = FAKE_CELL_VOLTAGE_mV; + } } test_fake_stateCompare.data.cellVoltage->stringVoltage_mV[s] = FAKE_CELL_VOLTAGE_mV * BS_NR_OF_CELL_BLOCKS_PER_STRING; - for (i = 0; i < BS_NR_OF_TEMP_SENSORS_PER_STRING; i++) { - test_fake_stateCompare.data.cellTemperature->cellTemperature_ddegC[s][i] = FAKE_CELL_TEMPERATURE_ddegC; + for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { + for (uint8_t ts = 0; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) { + test_fake_stateCompare.data.cellTemperature->cellTemperature_ddegC[s][m][ts] = + FAKE_CELL_TEMPERATURE_ddegC; + } } test_fake_stateCompare.data.slaveControl->eepromReadAddressLastUsed = 0xFFFFFFFF; diff --git a/tests/unit/app/driver/afe/ltc/6806/config/test_ltc_6806_cfg.c b/tests/unit/app/driver/afe/ltc/6806/config/test_ltc_6806_cfg.c index 3889d7c7..ec9a3784 100644 --- a/tests/unit/app/driver/afe/ltc/6806/config/test_ltc_6806_cfg.c +++ b/tests/unit/app/driver/afe/ltc/6806/config/test_ltc_6806_cfg.c @@ -43,8 +43,8 @@ * @file test_ltc_6806_cfg.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,14 @@ #include "ltc_6806_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/6806/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/afe/ltc/6806/test_ltc_6806.c b/tests/unit/app/driver/afe/ltc/6806/test_ltc_6806.c index acafecb6..006c7a8a 100644 --- a/tests/unit/app/driver/afe/ltc/6806/test_ltc_6806.c +++ b/tests/unit/app/driver/afe/ltc/6806/test_ltc_6806.c @@ -43,12 +43,12 @@ * @file test_ltc_6806.c * @author foxBMS Team * @date 2020-07-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * - * @brief Test of the ltc.c module + * @brief Test of the LTC LTC6806 driver * */ @@ -74,7 +74,21 @@ #include #include -TEST_FILE("ltc_6806.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ltc_6806.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/6806/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/engine/diag") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -103,16 +117,6 @@ SPI_INTERFACE_CONFIG_s spi_ltcInterface[BS_NR_OF_STRINGS] = { }, }; -SPI_INTERFACE_CONFIG_s spi_ltcInterfaceSecondary[BS_NR_OF_STRINGS] = { - { - .pConfig = &spi_kLtcDataConfig[0u], - .pNode = spiREG1, - .pGioPort = &(spiREG1->PC3), - .csPin = 2u, - .csType = SPI_CHIP_SELECT_HARDWARE, - }, -}; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/afe/ltc/6806/test_ltc_6806_pec_in_arrays.c b/tests/unit/app/driver/afe/ltc/6806/test_ltc_6806_pec_in_arrays.c index 97f82162..c5950d52 100644 --- a/tests/unit/app/driver/afe/ltc/6806/test_ltc_6806_pec_in_arrays.c +++ b/tests/unit/app/driver/afe/ltc/6806/test_ltc_6806_pec_in_arrays.c @@ -43,8 +43,8 @@ * @file test_ltc_6806_pec_in_arrays.c * @author foxBMS Team * @date 2020-12-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -70,11 +70,25 @@ #include "ltc_pec.h" #include "test_pec_helper.h" -TEST_FILE("ltc_6806.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ltc_6806.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/6806/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/engine/diag") /*========== Definitions and Implementations for Unit Test ==================*/ /* SPI data configuration struct for LTC communication */ -static const spiDAT1_t spi_kLtcDataConfig = { +static spiDAT1_t spi_kLtcDataConfig = { /* struct is implemented in the TI HAL and uses uppercase true and false */ .CS_HOLD = FALSE, /* The HW chip select signal is deactivated */ .WDEL = TRUE, /* No delay will be inserted */ @@ -92,15 +106,6 @@ SPI_INTERFACE_CONFIG_s spi_ltcInterface[BS_NR_OF_STRINGS] = { }, }; -SPI_INTERFACE_CONFIG_s spi_ltcInterfaceSecondary[BS_NR_OF_STRINGS] = { - { - .pConfig = &spi_kLtcDataConfig, - .pNode = spiREG1, - .pGioPort = &(spiREG1->PC3), - .csPin = 2u, - }, -}; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/afe/ltc/6813-1/config/test_ltc_6813-1_cfg.c b/tests/unit/app/driver/afe/ltc/6813-1/config/test_ltc_6813-1_cfg.c index 5deda1d1..b3c10e78 100644 --- a/tests/unit/app/driver/afe/ltc/6813-1/config/test_ltc_6813-1_cfg.c +++ b/tests/unit/app/driver/afe/ltc/6813-1/config/test_ltc_6813-1_cfg.c @@ -43,8 +43,8 @@ * @file test_ltc_6813-1_cfg.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,6 +58,15 @@ #include "ltc_6813-1_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/6813-1/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/afe/ltc/6813-1/test_ltc_6813-1.c b/tests/unit/app/driver/afe/ltc/6813-1/test_ltc_6813-1.c index 9a4f18d8..33f23d9b 100644 --- a/tests/unit/app/driver/afe/ltc/6813-1/test_ltc_6813-1.c +++ b/tests/unit/app/driver/afe/ltc/6813-1/test_ltc_6813-1.c @@ -43,8 +43,8 @@ * @file test_ltc_6813-1.c * @author foxBMS Team * @date 2020-03-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -74,11 +74,26 @@ #include #include -TEST_FILE("ltc_6813-1.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ltc_6813-1.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/6813-1/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/diag") /*========== Definitions and Implementations for Unit Test ==================*/ /* SPI data configuration struct for LTC communication */ -static const spiDAT1_t spi_kLtcDataConfig = { +static spiDAT1_t spi_kLtcDataConfig = { /* struct is implemented in the TI HAL and uses uppercase true and false */ .CS_HOLD = FALSE, /* The HW chip select signal is deactivated */ .WDEL = TRUE, /* No delay will be inserted */ @@ -96,15 +111,6 @@ SPI_INTERFACE_CONFIG_s spi_ltcInterface[BS_NR_OF_STRINGS] = { }, }; -SPI_INTERFACE_CONFIG_s spi_ltcInterfaceSecondary[BS_NR_OF_STRINGS] = { - { - .pConfig = &spi_kLtcDataConfig, - .pNode = spiREG1, - .pGioPort = &(spiREG1->PC3), - .csPin = 2u, - }, -}; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } @@ -138,7 +144,7 @@ void testLTC_SetFirstMeasurementCycleFinished(void) { TEST_ASSERT_EQUAL_UINT8(true, test_ltc_state.first_measurement_made); } -void testLTC_ConvertMuxVoltagesToTemperatures() { +void testLTC_ConvertMuxVoltagesToTemperatures(void) { TSI_GetTemperature_ExpectAndReturn(0, 0u); int16_t x = 0; x = LTC_ConvertMuxVoltagesToTemperatures(0); diff --git a/tests/unit/app/driver/afe/ltc/6813-1/test_ltc_6813-1_pec_in_arrays.c b/tests/unit/app/driver/afe/ltc/6813-1/test_ltc_6813-1_pec_in_arrays.c index e11d8674..644482a5 100644 --- a/tests/unit/app/driver/afe/ltc/6813-1/test_ltc_6813-1_pec_in_arrays.c +++ b/tests/unit/app/driver/afe/ltc/6813-1/test_ltc_6813-1_pec_in_arrays.c @@ -43,8 +43,8 @@ * @file test_ltc_6813-1_pec_in_arrays.c * @author foxBMS Team * @date 2020-03-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -72,11 +72,26 @@ #include "ltc_pec.h" #include "test_pec_helper.h" -TEST_FILE("ltc_6813-1.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ltc_6813-1.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/6813-1/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/diag") /*========== Definitions and Implementations for Unit Test ==================*/ /* SPI data configuration struct for LTC communication */ -static const spiDAT1_t spi_kLtcDataConfig = { +static spiDAT1_t spi_kLtcDataConfig = { /* struct is implemented in the TI HAL and uses uppercase true and false */ .CS_HOLD = FALSE, /* The HW chip select signal is deactivated */ .WDEL = TRUE, /* No delay will be inserted */ @@ -94,15 +109,6 @@ SPI_INTERFACE_CONFIG_s spi_ltcInterface[BS_NR_OF_STRINGS] = { }, }; -SPI_INTERFACE_CONFIG_s spi_ltcInterfaceSecondary[BS_NR_OF_STRINGS] = { - { - .pConfig = &spi_kLtcDataConfig, - .pNode = spiREG1, - .pGioPort = &(spiREG1->PC3), - .csPin = 2u, - }, -}; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/afe/ltc/api/test_ltc_afe.c b/tests/unit/app/driver/afe/ltc/api/test_ltc_afe.c index f8fa0eea..bf503d9a 100644 --- a/tests/unit/app/driver/afe/ltc/api/test_ltc_afe.c +++ b/tests/unit/app/driver/afe/ltc/api/test_ltc_afe.c @@ -43,8 +43,8 @@ * @file test_ltc_afe.c * @author foxBMS Team * @date 2020-05-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,9 +62,14 @@ #include "afe.h" -/* it's important to mention the implementation in ltc_afe.c -here in order to test the correct implementation */ -TEST_FILE("ltc_afe.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ltc_afe.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") /*========== Definitions and Implementations for Unit Test ==================*/ uint8_t ltc_RXPECbuffer[LTC_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; diff --git a/tests/unit/app/driver/afe/ltc/common/config/test_ltc_afe_dma_cfg.c b/tests/unit/app/driver/afe/ltc/common/config/test_ltc_afe_dma_cfg.c deleted file mode 100644 index 18b24afb..00000000 --- a/tests/unit/app/driver/afe/ltc/common/config/test_ltc_afe_dma_cfg.c +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_ltc_afe_dma_cfg.c - * @author foxBMS Team - * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Tests for the CAN driver - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" - -#include "ltc_afe_dma_cfg.h" - -/*========== Definitions and Implementations for Unit Test ==================*/ - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -/*========== Test Cases =====================================================*/ - -void testDummy(void) { -} diff --git a/tests/unit/app/driver/afe/ltc/common/test_ltc_afe_dma.c b/tests/unit/app/driver/afe/ltc/common/test_ltc_afe_dma.c index c0991c51..286af9b5 100644 --- a/tests/unit/app/driver/afe/ltc/common/test_ltc_afe_dma.c +++ b/tests/unit/app/driver/afe/ltc/common/test_ltc_afe_dma.c @@ -43,8 +43,8 @@ * @file test_ltc_afe_dma.c * @author foxBMS Team * @date 2020-06-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -68,7 +68,15 @@ #include #include -TEST_FILE("ltc_afe_dma.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ltc_afe_dma.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/spi") /*========== Definitions and Implementations for Unit Test ==================*/ uint8_t ltc_RXPECbuffer[LTC_N_BYTES_FOR_DATA_TRANSMISSION] = {0}; diff --git a/tests/unit/app/driver/afe/ltc/common/test_ltc_pec.c b/tests/unit/app/driver/afe/ltc/common/test_ltc_pec.c index 21cfe4dd..a8a7ad68 100644 --- a/tests/unit/app/driver/afe/ltc/common/test_ltc_pec.c +++ b/tests/unit/app/driver/afe/ltc/common/test_ltc_pec.c @@ -43,8 +43,8 @@ * @file test_ltc_pec.c * @author foxBMS Team * @date 2022-11-04 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "ltc_pec.h" #include "test_assert_helper.h" -TEST_FILE("ltc_pec.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ltc_pec.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/ltc/common") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/afe/maxim/api/test_mxm_afe.c b/tests/unit/app/driver/afe/maxim/api/test_mxm_afe.c index b4ef1ea4..c23310d9 100644 --- a/tests/unit/app/driver/afe/maxim/api/test_mxm_afe.c +++ b/tests/unit/app/driver/afe/maxim/api/test_mxm_afe.c @@ -43,8 +43,8 @@ * @file test_mxm_afe.c * @author foxBMS Team * @date 2020-06-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -64,9 +64,14 @@ #include "afe.h" -/* it's important to mention the implementation in mxm_afe.c -here in order to test the correct implementation */ -TEST_FILE("mxm_afe.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("mxm_afe.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/afe/maxim/common/config/test_mxm_cfg.c b/tests/unit/app/driver/afe/maxim/common/config/test_mxm_cfg.c index 206fc091..fd9fc614 100644 --- a/tests/unit/app/driver/afe/maxim/common/config/test_mxm_cfg.c +++ b/tests/unit/app/driver/afe/maxim/common/config/test_mxm_cfg.c @@ -43,8 +43,8 @@ * @file test_mxm_cfg.c * @author foxBMS Team * @date 2020-06-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -65,6 +65,13 @@ #include #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/engine/diag") + /*========== Definitions and Implementations for Unit Test ==================*/ /* SPI interface configuration for MXM communication */ SPI_INTERFACE_CONFIG_s spi_mxmInterface = { diff --git a/tests/unit/app/driver/afe/maxim/common/test_mxm_17841b.c b/tests/unit/app/driver/afe/maxim/common/test_mxm_17841b.c index ef7248cd..a5b87ebf 100644 --- a/tests/unit/app/driver/afe/maxim/common/test_mxm_17841b.c +++ b/tests/unit/app/driver/afe/maxim/common/test_mxm_17841b.c @@ -43,8 +43,8 @@ * @file test_mxm_17841b.c * @author foxBMS Team * @date 2020-06-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix MXM * @@ -67,28 +67,34 @@ #include #include -TEST_FILE("mxm_17841b.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("mxm_17841b.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") /*========== Definitions and Implementations for Unit Test ==================*/ /** replicating the config register length in the driver */ #define MXM_41B_CONFIG_REGISTER_LENGTH (7u) static MXM_41B_INSTANCE_s mxm_41bState = { - .state = MXM_STATEMACH_41B_UNINITIALIZED, - .substate = MXM_41B_ENTRY_SUBSTATE, - .extendMessageBytes = 0, - .waitCounter = 0, - .regRXIntEnable = 0x00u, - .regTXIntEnable = 0x00u, - .regRXStatus = 0x00u, - .regTXStatus = 0x00u, - .regConfig1 = MXM_41B_CONFIG_1_DEFAULT_VALUE, - .regConfig2 = MXM_41B_CONFIG_2_DEFAULT_VALUE, - .regConfig3 = MXM_41B_CONFIG_3_DEFAULT_VALUE, - .hwModel = 0, - .hwMaskRevision = 0, - .spiRXBuffer = {0}, - .spiTXBuffer = {0}, + .state = MXM_STATEMACH_41B_UNINITIALIZED, + .substate = MXM_41B_ENTRY_SUBSTATE, + .extendMessageBytes = 0, + .waitCounter = 0, + .regRxIntEnable = 0x00u, + .regTxIntEnable = 0x00u, + .regRxStatus = 0x00u, + .regTxStatus = 0x00u, + .regConfig1 = MXM_41B_CONFIG_1_DEFAULT_VALUE, + .regConfig2 = MXM_41B_CONFIG_2_DEFAULT_VALUE, + .regConfig3 = MXM_41B_CONFIG_3_DEFAULT_VALUE, + .hardwareModel = 0, + .hardwareMaskRevision = 0, + .spiRxBuffer = {0}, + .spiTxBuffer = {0}, }; uint16_t commandBuffer[10] = {0}; @@ -268,30 +274,30 @@ void testWriteRegisterFunctionWithLegalValues(void) { TEST_ASSERT_EQUAL(0xFu, mxm_41bState.regConfig3); /* standard state should be zero */ - TEST_ASSERT_EQUAL(0x0u, mxm_41bState.regRXIntEnable); + TEST_ASSERT_EQUAL(0x0u, mxm_41bState.regRxIntEnable); /* rx error int on --> 0x80 */ TEST_ASSERT_EQUAL( STD_OK, MXM_41BWriteRegisterFunction(&mxm_41bState, MXM_41B_REG_FUNCTION_RX_ERROR_INT, MXM_41B_REG_TRUE)); - TEST_ASSERT_EQUAL(0x80u, mxm_41bState.regRXIntEnable); + TEST_ASSERT_EQUAL(0x80u, mxm_41bState.regRxIntEnable); /* rx error int off --> 0 */ TEST_ASSERT_EQUAL( STD_OK, MXM_41BWriteRegisterFunction(&mxm_41bState, MXM_41B_REG_FUNCTION_RX_ERROR_INT, MXM_41B_REG_FALSE)); - TEST_ASSERT_EQUAL(0x0u, mxm_41bState.regRXIntEnable); + TEST_ASSERT_EQUAL(0x0u, mxm_41bState.regRxIntEnable); /* standard state should be zero */ - TEST_ASSERT_EQUAL(0x0u, mxm_41bState.regRXIntEnable); + TEST_ASSERT_EQUAL(0x0u, mxm_41bState.regRxIntEnable); /* rx overflow int on --> 0x8 */ TEST_ASSERT_EQUAL( STD_OK, MXM_41BWriteRegisterFunction(&mxm_41bState, MXM_41B_REG_FUNCTION_RX_OVERFLOW_INT, MXM_41B_REG_TRUE)); - TEST_ASSERT_EQUAL(0x8u, mxm_41bState.regRXIntEnable); + TEST_ASSERT_EQUAL(0x8u, mxm_41bState.regRxIntEnable); /* rx overflow int off --> 0 */ TEST_ASSERT_EQUAL( STD_OK, MXM_41BWriteRegisterFunction(&mxm_41bState, MXM_41B_REG_FUNCTION_RX_OVERFLOW_INT, MXM_41B_REG_FALSE)); - TEST_ASSERT_EQUAL(0x0u, mxm_41bState.regRXIntEnable); + TEST_ASSERT_EQUAL(0x0u, mxm_41bState.regRxIntEnable); } /** @} * end of tests for function MXM_41BWriteRegisterFunction */ @@ -309,7 +315,7 @@ void testReadRegisterFunctionWithIllegalValues(void) { void testReadRegisterFunctionWithLegalValues(void) { MXM_41B_REG_BIT_VALUE result = 42; /* set register */ - mxm_41bState.regRXStatus = 0u; + mxm_41bState.regRxStatus = 0u; /* read all functions in this register */ TEST_ASSERT_EQUAL(STD_OK, MXM_41BReadRegisterFunction(&mxm_41bState, MXM_41B_REG_FUNCTION_RX_BUSY_STATUS, &result)); @@ -320,7 +326,7 @@ void testReadRegisterFunctionWithLegalValues(void) { TEST_ASSERT_EQUAL(MXM_41B_REG_FALSE, result); /* set register with bit RX_EMPTY */ - mxm_41bState.regRXStatus = 1u; + mxm_41bState.regRxStatus = 1u; /* read all functions in this register */ TEST_ASSERT_EQUAL(STD_OK, MXM_41BReadRegisterFunction(&mxm_41bState, MXM_41B_REG_FUNCTION_RX_BUSY_STATUS, &result)); @@ -331,7 +337,7 @@ void testReadRegisterFunctionWithLegalValues(void) { TEST_ASSERT_EQUAL(MXM_41B_REG_TRUE, result); /* set register with bit RX_BUSY */ - mxm_41bState.regRXStatus = 0x20u; + mxm_41bState.regRxStatus = 0x20u; /* read all functions in this register */ TEST_ASSERT_EQUAL(STD_OK, MXM_41BReadRegisterFunction(&mxm_41bState, MXM_41B_REG_FUNCTION_RX_BUSY_STATUS, &result)); @@ -385,7 +391,7 @@ void testStateCheckFMEA(void) { /* create a buffer with the assumed output of the ASCI and inject into SPI read */ uint16_t rxBuffer[10] = {0x13u, 0x00u}; - MXM_ReceiveData_ExpectAndReturn(mxm_41bState.spiTXBuffer, mxm_41bState.spiRXBuffer, 2, STD_OK); + MXM_ReceiveData_ExpectAndReturn(mxm_41bState.spiTxBuffer, mxm_41bState.spiRxBuffer, 2, STD_OK); MXM_ReceiveData_ReturnArrayThruPtr_rxBuffer(rxBuffer, 2); MXM_41BStateMachine(&mxm_41bState); TEST_ASSERT_EQUAL(MXM_STATEMACH_41B_CHECK_FMEA, mxm_41bState.state); @@ -406,7 +412,7 @@ void testStateCheckFmeaGNDLAlert(void) { /* create a buffer with the assumed output of the ASCI and inject into SPI read */ /* simulate an GNDL Alert in FMEA register */ uint16_t rxBuffer[10] = {0x13u, 0x01u}; - MXM_ReceiveData_ExpectAndReturn(mxm_41bState.spiTXBuffer, mxm_41bState.spiRXBuffer, 2, STD_OK); + MXM_ReceiveData_ExpectAndReturn(mxm_41bState.spiTxBuffer, mxm_41bState.spiRxBuffer, 2, STD_OK); MXM_ReceiveData_ReturnArrayThruPtr_rxBuffer(rxBuffer, 2); MXM_41BStateMachine(&mxm_41bState); TEST_ASSERT_EQUAL(MXM_STATEMACH_41B_CHECK_FMEA, mxm_41bState.state); @@ -426,7 +432,7 @@ void testStateGetVersion(void) { /* create a buffer with the assumed output of the ASCI and inject into SPI read */ uint16_t rxBuffer[10] = {0x15u, 0x84u, 0x12u}; - MXM_ReceiveData_ExpectAndReturn(mxm_41bState.spiTXBuffer, mxm_41bState.spiRXBuffer, 3, STD_OK); + MXM_ReceiveData_ExpectAndReturn(mxm_41bState.spiTxBuffer, mxm_41bState.spiRxBuffer, 3, STD_OK); MXM_ReceiveData_ReturnArrayThruPtr_rxBuffer(rxBuffer, 3); MXM_41BStateMachine(&mxm_41bState); TEST_ASSERT_EQUAL(MXM_STATEMACH_41B_GET_VERSION, mxm_41bState.state); @@ -434,8 +440,8 @@ void testStateGetVersion(void) { /* check if the values are parsed correctly */ MXM_GetSPIStateReady_ExpectAndReturn(STD_OK); MXM_41BStateMachine(&mxm_41bState); - TEST_ASSERT_EQUAL(0x841u, mxm_41bState.hwModel); - TEST_ASSERT_EQUAL(0x2u, mxm_41bState.hwMaskRevision); + TEST_ASSERT_EQUAL(0x841u, mxm_41bState.hardwareModel); + TEST_ASSERT_EQUAL(0x2u, mxm_41bState.hardwareMaskRevision); } void testStateClearReceiveBuffer(void) { @@ -509,7 +515,7 @@ void testStateUARTWaitForRXStatusChangeFail(void) { mxm_41bState.state = MXM_STATEMACH_41B_UART_TRANSACTION; mxm_41bState.substate = MXM_41B_UART_WAIT_FOR_RX_STATUS_CHANGE_READ_AND_READ_BACK_RCV_BUF; /* prepare RX buffer with not received RX_Stop_Status bit */ - mxm_41bState.spiRXBuffer[1] = 0; + mxm_41bState.spiRxBuffer[1] = 0; /* transition */ MXM_41BStateMachine(&mxm_41bState); @@ -522,7 +528,7 @@ void testStateUARTWaitForRXStatusChangeSuccess(void) { mxm_41bState.state = MXM_STATEMACH_41B_UART_TRANSACTION; mxm_41bState.substate = MXM_41B_UART_WAIT_FOR_RX_STATUS_CHANGE_READ_AND_READ_BACK_RCV_BUF; /* prepare RX buffer with received RX_Stop_Status bit */ - mxm_41bState.spiRXBuffer[1] |= (0x01u << 1u); + mxm_41bState.spiRxBuffer[1] |= (0x01u << 1u); /* transition */ MXM_ReceiveData_IgnoreAndReturn(STD_OK); @@ -569,7 +575,7 @@ void testStateInitNormalFlow(void) { MXM_41BStateMachine(&mxm_41bState); /* now the default configuration should be sent to the bridge IC */ - MXM_SendData_ExpectAndReturn(mxm_41bState.spiTXBuffer, 8, STD_OK); + MXM_SendData_ExpectAndReturn(mxm_41bState.spiTxBuffer, 8, STD_OK); MXM_41BStateMachine(&mxm_41bState); /* default values to check against */ @@ -582,12 +588,12 @@ void testStateInitNormalFlow(void) { MXM_41B_CONFIG_2_DEFAULT_VALUE, MXM_41B_CONFIG_3_DEFAULT_VALUE}; MXM_ReceiveData_ExpectAndReturn( - mxm_41bState.spiTXBuffer, mxm_41bState.spiRXBuffer, MXM_41B_CONFIG_REGISTER_LENGTH + 1, STD_OK); + mxm_41bState.spiTxBuffer, mxm_41bState.spiRxBuffer, MXM_41B_CONFIG_REGISTER_LENGTH + 1, STD_OK); MXM_41BStateMachine(&mxm_41bState); /* inject the values by copying into the pointer (can be done since we know the address) */ for (uint8_t i = 0u; i < MXM_41B_CONFIG_REGISTER_LENGTH; i++) { - mxm_41bState.spiRXBuffer[i + 1u] = mxm_41B_reg_default_values[i]; + mxm_41bState.spiRxBuffer[i + 1u] = mxm_41B_reg_default_values[i]; } MXM_GetSPIStateReady_ExpectAndReturn(STD_OK); diff --git a/tests/unit/app/driver/afe/maxim/common/test_mxm_1785x.c b/tests/unit/app/driver/afe/maxim/common/test_mxm_1785x.c index d4a05bc1..d53adc11 100644 --- a/tests/unit/app/driver/afe/maxim/common/test_mxm_1785x.c +++ b/tests/unit/app/driver/afe/maxim/common/test_mxm_1785x.c @@ -43,8 +43,8 @@ * @file test_mxm_1785x.c * @author foxBMS Team * @date 2020-07-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix MXM * @@ -78,7 +78,16 @@ #include #include -TEST_FILE("test_mxm_1785x") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("test_mxm_1785x") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/diag") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/afe/maxim/common/test_mxm_1785x_tools.c b/tests/unit/app/driver/afe/maxim/common/test_mxm_1785x_tools.c index f5c0001c..301cfd5d 100644 --- a/tests/unit/app/driver/afe/maxim/common/test_mxm_1785x_tools.c +++ b/tests/unit/app/driver/afe/maxim/common/test_mxm_1785x_tools.c @@ -43,8 +43,8 @@ * @file test_mxm_1785x_tools.c * @author foxBMS Team * @date 2020-07-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix MXM * @@ -55,6 +55,10 @@ */ /*========== Includes =======================================================*/ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic ignored "-Wuninitialized" + #include "unity.h" #include "Mockfassert.h" #include "Mockmxm_cfg.h" @@ -62,6 +66,12 @@ #include "mxm_1785x_tools.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/afe/maxim/common/test_mxm_afe_dma.c b/tests/unit/app/driver/afe/maxim/common/test_mxm_afe_dma.c index 8549d638..e3cca6c2 100644 --- a/tests/unit/app/driver/afe/maxim/common/test_mxm_afe_dma.c +++ b/tests/unit/app/driver/afe/maxim/common/test_mxm_afe_dma.c @@ -43,8 +43,8 @@ * @file test_mxm_afe_dma.c * @author foxBMS Team * @date 2020-06-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,9 +57,15 @@ #include "MockHL_sys_dma.h" #include "Mockfassert.h" -#include "mxm_afe_dma.h" +#include "afe_dma.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("mxm_afe_dma.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/afe/maxim/common/test_mxm_battery_management.c b/tests/unit/app/driver/afe/maxim/common/test_mxm_battery_management.c index d410609b..561d5f8a 100644 --- a/tests/unit/app/driver/afe/maxim/common/test_mxm_battery_management.c +++ b/tests/unit/app/driver/afe/maxim/common/test_mxm_battery_management.c @@ -43,8 +43,8 @@ * @file test_mxm_battery_management.c * @author foxBMS Team * @date 2020-07-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix MXM * @@ -66,6 +66,14 @@ #include "mxm_battery_management.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/engine/diag") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/afe/maxim/common/test_mxm_bitextract.c b/tests/unit/app/driver/afe/maxim/common/test_mxm_bitextract.c index a171bef3..cbd51b2f 100644 --- a/tests/unit/app/driver/afe/maxim/common/test_mxm_bitextract.c +++ b/tests/unit/app/driver/afe/maxim/common/test_mxm_bitextract.c @@ -43,8 +43,8 @@ * @file test_mxm_bitextract.c * @author foxBMS Team * @date 2020-04-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,6 +59,9 @@ #include "mxm_bitextract.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ @@ -131,41 +134,41 @@ void testReadValuePositionOneWithMoreBits(void) { } void testReadValueTXPreambles(void) { - uint8_t reg = 0b100000; + uint8_t reg = 0x20u; TEST_ASSERT_EQUAL(1u, mxm_41bReadValue(reg, 1, MXM_41B_TX_PREAMBLES)); } void testReadValueKeepAlive(void) { - uint8_t reg = 0b1111; + uint8_t reg = 0x0Fu; TEST_ASSERT_EQUAL(0xFu, mxm_41bReadValue(reg, 4, MXM_41B_KEEP_ALIVE)); } void testReadValueKeepAliveOne(void) { - uint8_t reg = 0b1; + uint8_t reg = 0x01u; TEST_ASSERT_EQUAL(0x1u, mxm_41bReadValue(reg, 4, MXM_41B_KEEP_ALIVE)); } void testReadValueKeepAliveFiveBits(void) { - uint8_t reg = 0b11111; + uint8_t reg = 0x1Fu; TEST_ASSERT_EQUAL(0xFu, mxm_41bReadValue(reg, 4, MXM_41B_KEEP_ALIVE)); } void testReadValueRXError(void) { - uint8_t reg = 0b10000000; + uint8_t reg = 0x80u; TEST_ASSERT_EQUAL(1u, mxm_41bReadValue(reg, 1, MXM_41B_RX_ERROR)); } void testReadValueRXOverflowStatus(void) { - uint8_t reg = 0b1000; + uint8_t reg = 0x08u; TEST_ASSERT_EQUAL(1u, mxm_41bReadValue(reg, 1, MXM_41B_RX_OVERFLOW_INT_ENABLE)); } void testReadValueRXBusy(void) { - uint8_t reg = 0b100000; + uint8_t reg = 0x20u; TEST_ASSERT_EQUAL(1u, mxm_41bReadValue(reg, 1, MXM_41B_RX_BUSY_STATUS)); } void testReadValueRXEmptyStatus(void) { - uint8_t reg = 0b1; + uint8_t reg = 0x01u; TEST_ASSERT_EQUAL(1u, mxm_41bReadValue(reg, 1, MXM_41B_RX_EMPTY_STATUS)); } diff --git a/tests/unit/app/driver/afe/maxim/common/test_mxm_crc8.c b/tests/unit/app/driver/afe/maxim/common/test_mxm_crc8.c index ab326ca3..ed3c8c6c 100644 --- a/tests/unit/app/driver/afe/maxim/common/test_mxm_crc8.c +++ b/tests/unit/app/driver/afe/maxim/common/test_mxm_crc8.c @@ -43,8 +43,8 @@ * @file test_mxm_crc8.c * @author foxBMS Team * @date 2020-03-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix MXM * @@ -60,6 +60,9 @@ #include "mxm_crc8.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/afe/maxim/common/test_mxm_register_map.c b/tests/unit/app/driver/afe/maxim/common/test_mxm_register_map.c index d28f9097..9cf127b0 100644 --- a/tests/unit/app/driver/afe/maxim/common/test_mxm_register_map.c +++ b/tests/unit/app/driver/afe/maxim/common/test_mxm_register_map.c @@ -43,8 +43,8 @@ * @file test_mxm_register_map.c * @author foxBMS Team * @date 2020-04-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,7 +58,9 @@ #include "unity.h" #include "mxm_register_map.h" -TEST_FILE("mxm_register_map.h") + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -71,11 +73,11 @@ void tearDown(void) { /*========== Test Cases =====================================================*/ void testMXMRegisterMapExamplesForMASK(void) { - TEST_ASSERT_EQUAL(1u, MXM_REG_BIT_DEFN(0, 0)); + TEST_ASSERT_EQUAL(0x01u, MXM_REG_BIT_DEFN(0, 0)); - TEST_ASSERT_EQUAL(0b1000u, MXM_REG_BIT_DEFN(3, 3)); + TEST_ASSERT_EQUAL(0x08u, MXM_REG_BIT_DEFN(3, 3)); - TEST_ASSERT_EQUAL(0b00111000u, MXM_REG_BIT_DEFN(3, 5)); + TEST_ASSERT_EQUAL(0x38u, MXM_REG_BIT_DEFN(3, 5)); TEST_ASSERT_EQUAL(0xFFFFu, MXM_REG_BIT_DEFN(0u, 15u)); } diff --git a/tests/unit/app/driver/afe/maxim/common/test_mxm_registry.c b/tests/unit/app/driver/afe/maxim/common/test_mxm_registry.c index 0b68111e..3fe94bf0 100644 --- a/tests/unit/app/driver/afe/maxim/common/test_mxm_registry.c +++ b/tests/unit/app/driver/afe/maxim/common/test_mxm_registry.c @@ -43,8 +43,8 @@ * @file test_mxm_registry.c * @author foxBMS Team * @date 2020-07-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix MXM * @@ -68,6 +68,13 @@ #include #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + /*========== Definitions and Implementations for Unit Test ==================*/ static MXM_MONITORING_INSTANCE_s mxm_state = { .state = MXM_STATEMACHINE_STATES_UNINITIALIZED, diff --git a/tests/unit/app/driver/afe/maxim/max17852/test_mxm_17852.c b/tests/unit/app/driver/afe/maxim/max17852/test_mxm_17852.c index cb3fccaf..f4a14517 100644 --- a/tests/unit/app/driver/afe/maxim/max17852/test_mxm_17852.c +++ b/tests/unit/app/driver/afe/maxim/max17852/test_mxm_17852.c @@ -43,8 +43,8 @@ * @file test_mxm_17852.c * @author foxBMS Team * @date 2021-11-30 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix MXM * @@ -78,7 +78,16 @@ #include #include -TEST_FILE("mxm_17852.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("mxm_17852.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common") +TEST_INCLUDE_PATH("../../src/app/driver/afe/maxim/common/config") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/engine/diag") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/afe/nxp/api/test_nxp_afe.c b/tests/unit/app/driver/afe/nxp/api/test_nxp_afe.c index 67264879..f69812d5 100644 --- a/tests/unit/app/driver/afe/nxp/api/test_nxp_afe.c +++ b/tests/unit/app/driver/afe/nxp/api/test_nxp_afe.c @@ -43,8 +43,8 @@ * @file test_nxp_afe.c * @author foxBMS Team * @date 2020-06-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -60,9 +60,11 @@ #include "afe.h" -/* it's important to mention the implementation in nxp_afe.c -here in order to test the correct implementation */ -TEST_FILE("nxp_afe.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("nxp_afe.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/api") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/afe/nxp/mc33775a/api/test_nxp_mc33775a_afe.c b/tests/unit/app/driver/afe/nxp/mc33775a/api/test_nxp_mc33775a_afe.c index 7f4d894e..bd15b33a 100644 --- a/tests/unit/app/driver/afe/nxp/mc33775a/api/test_nxp_mc33775a_afe.c +++ b/tests/unit/app/driver/afe/nxp/mc33775a/api/test_nxp_mc33775a_afe.c @@ -43,8 +43,8 @@ * @file test_nxp_mc33775a_afe.c * @author foxBMS Team * @date 2020-06-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -64,7 +64,18 @@ #include #include -TEST_FILE("nxp_mc33775a_afe.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("nxp_mc33775a_afe.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a/vendor") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/spi") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -78,7 +89,7 @@ static DATA_BLOCK_BALANCING_FEEDBACK_s n775_balancingFeedback = { static DATA_BLOCK_SLAVE_CONTROL_s n775_slaveControl = {.header.uniqueId = DATA_BLOCK_ID_SLAVE_CONTROL}; static DATA_BLOCK_OPEN_WIRE_s n775_openWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; static N775_SUPPLY_CURRENT_s n775_supplyCurrent = {0}; -static N775_ERRORTABLE_s n775_errorTable = {0}; +static N775_ERROR_TABLE_s n775_errorTable = {0}; N775_STATE_s n775_stateBase = { .firstMeasurementMade = false, diff --git a/tests/unit/app/driver/afe/nxp/mc33775a/config/test_nxp_afe_dma_cfg.c b/tests/unit/app/driver/afe/nxp/mc33775a/config/test_nxp_afe_dma_cfg.c deleted file mode 100644 index 2da9329d..00000000 --- a/tests/unit/app/driver/afe/nxp/mc33775a/config/test_nxp_afe_dma_cfg.c +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_nxp_afe_dma_cfg.c - * @author foxBMS Team - * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Tests for the CAN driver - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" - -#include "nxp_afe_dma_cfg.h" - -/*========== Definitions and Implementations for Unit Test ==================*/ - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -/*========== Test Cases =====================================================*/ - -void testDummy(void) { -} diff --git a/tests/unit/app/driver/afe/nxp/mc33775a/config/test_nxp_mc33775a_cfg.c b/tests/unit/app/driver/afe/nxp/mc33775a/config/test_nxp_mc33775a_cfg.c index 2979a986..ca29f41b 100644 --- a/tests/unit/app/driver/afe/nxp/mc33775a/config/test_nxp_mc33775a_cfg.c +++ b/tests/unit/app/driver/afe/nxp/mc33775a/config/test_nxp_mc33775a_cfg.c @@ -43,8 +43,8 @@ * @file test_nxp_mc33775a_cfg.c * @author foxBMS Team * @date 2020-06-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -56,7 +56,14 @@ #include "unity.h" #include "Mocktsi.h" -TEST_FILE("nxp_mc33775a_cfg.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("nxp_mc33775a_cfg.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_afe_dma.c b/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_afe_dma.c index 90148e47..3d862f21 100644 --- a/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_afe_dma.c +++ b/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_afe_dma.c @@ -43,8 +43,8 @@ * @file test_nxp_afe_dma.c * @author foxBMS Team * @date 2020-06-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,32 +57,136 @@ #include "Mockdma.h" #include "Mockio.h" #include "Mockmcu.h" -#include "Mocknxp_afe_dma.h" #include "Mocknxp_mc33775a-ll.h" #include "Mocknxp_mc33775a.h" #include "Mockos.h" #include "Mockspi.h" #include "Mocktask.h" -TEST_FILE("nxp_afe_dma.c") +#include "nxp_afe_dma.h" +#include "test_assert_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("nxp_afe_dma.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a/vendor") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ OS_TASK_HANDLE ftsk_taskHandleAfe; +#define TEST_SPI_INTERFACE_1 (0u) +#define TEST_SPI_INTERFACE_2 (1u) +#define TEST_SPI_INTERFACE_3 (2u) +#define TEST_SPI_INTERFACE_4 (3u) +#define TEST_SPI_INTERFACE_5 (4u) + +/* clang-format off */ +spiBASE_t spiReg1 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +spiBASE_t spiReg2 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +spiBASE_t spiReg3 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +spiBASE_t spiReg4 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +spiBASE_t spiReg5 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +/* clang-format on */ + spiBASE_t *dma_spiInterfaces[DMA_NUMBER_SPI_INTERFACES] = { - spiREG1, /* SPI1 */ - spiREG2, /* SPI2 */ - spiREG3, /* SPI3 */ - spiREG4, /* SPI4 */ - spiREG5, /* SPI5 */ + NULL_PTR, /* SPI1 */ + NULL_PTR, /* SPI2 */ + NULL_PTR, /* SPI3 */ + NULL_PTR, /* SPI4 */ + NULL_PTR, /* SPI5 */ }; /*========== Setup and Teardown =============================================*/ void setUp(void) { + dma_spiInterfaces[TEST_SPI_INTERFACE_1] = &spiReg1; + dma_spiInterfaces[TEST_SPI_INTERFACE_2] = &spiReg2; + dma_spiInterfaces[TEST_SPI_INTERFACE_3] = &spiReg3; + dma_spiInterfaces[TEST_SPI_INTERFACE_4] = &spiReg4; + dma_spiInterfaces[TEST_SPI_INTERFACE_5] = &spiReg5; } void tearDown(void) { } +/** + * @brief Testing AFE_DmaCallback for the NXP MC33775A driver + * @details The following cases need to be tested: + * - Argument validation: + * - AT1/1: invalid SPI choice -> assert + * - Routine validation: + * - RT1/2: Function calls expected subroutines based on provided + * index + * - RT1/2: Function calls expected subroutines based on provided + * index + */ +void test_AFE_DmaCallback(void) { + /* ======= Assertion tests ============================================= */ + /* ======= AT1/1 ======= */ + TEST_ASSERT_FAIL_ASSERT(AFE_DmaCallback(10u)); + + /* ======= Routine tests =============================================== */ + /* ======= RT1/2: Test implementation */ + OS_NotifyIndexedFromIsr_ExpectAndReturn( + ftsk_taskHandleAfe, N775_NOTIFICATION_TX_INDEX, N775_TX_NOTIFIED_VALUE, OS_SUCCESS); + /* ======= RT1/2: call function under test */ + AFE_DmaCallback(0u); + /* ======= RT1/2: test output verification */ + /* nothing to be verified */ + + /* ======= RT1/2: Test implementation */ + + OS_NotifyIndexedFromIsr_ExpectAndReturn( + ftsk_taskHandleAfe, N775_NOTIFICATION_RX_INDEX, N775_RX_NOTIFIED_VALUE, OS_SUCCESS); + /* ======= RT1/2: call function under test */ + AFE_DmaCallback(3u); + /* ======= RT1/2: test output verification */ + /* nothing to be verified */ +} + /*========== Test Cases =====================================================*/ diff --git a/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a-ll.c b/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a-ll.c index 9e94614a..9852a414 100644 --- a/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a-ll.c +++ b/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a-ll.c @@ -43,8 +43,8 @@ * @file test_nxp_mc33775a-ll.c * @author foxBMS Team * @date 2021-10-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -64,7 +64,17 @@ #include "nxp_mc33775a-ll.h" #include "uc_msg_t.h" -TEST_FILE("nxp_mc33775a-ll.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("nxp_mc33775a-ll.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a/vendor") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/spi") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a.c b/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a.c index 55e57b6b..3f9785f2 100644 --- a/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a.c +++ b/tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a.c @@ -43,8 +43,8 @@ * @file test_nxp_mc33775a.c * @author foxBMS Team * @date 2021-10-20 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -75,7 +75,21 @@ #include #include -TEST_FILE("nxp_mc33775a.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("nxp_mc33775a.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a/config") +TEST_INCLUDE_PATH("../../src/app/driver/afe/nxp/mc33775a/vendor") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/afe/ti/api/test_ti_afe.c b/tests/unit/app/driver/afe/ti/api/test_ti_afe.c new file mode 100644 index 00000000..406abd45 --- /dev/null +++ b/tests/unit/app/driver/afe/ti/api/test_ti_afe.c @@ -0,0 +1,83 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_ti_afe.c + * @author foxBMS Team + * @date 2023-09-11 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of the TI AFE API implementation of the AFE API + * + */ + +/*========== Includes =======================================================*/ + +#include "unity.h" + +#include "ti_dummy.h" /* use the dummy implementation to test the interface */ + +#include "afe.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ti_afe.c") +TEST_SOURCE_FILE("ti_dummy_afe.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ti/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ti/dummy") +TEST_INCLUDE_PATH("../../src/app/driver/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/afe/ti/common/api/test_ti_bq79xxx_afe_dma.c b/tests/unit/app/driver/afe/ti/common/api/test_ti_bq79xxx_afe_dma.c new file mode 100644 index 00000000..b7ae66d1 --- /dev/null +++ b/tests/unit/app/driver/afe/ti/common/api/test_ti_bq79xxx_afe_dma.c @@ -0,0 +1,154 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_ti_bq79xxx_afe_dma.c + * @author foxBMS Team + * @date 2023-09-11 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of TI BQ97XXX AFE DMA API implementation of the TI AFE DMA API + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockdma.h" +#include "Mockio.h" +#include "Mockmcu.h" +#include "Mockos.h" +#include "Mockspi.h" +#include "Mocktask.h" + +#include "test_assert_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ti_bq79xxx_afe_dma.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/mcu") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") +TEST_INCLUDE_PATH("../../src/app/task/os") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +OS_TASK_HANDLE ftsk_taskHandleAfe; + +#define TEST_SPI_INTERFACE_1 (0u) +#define TEST_SPI_INTERFACE_2 (1u) +#define TEST_SPI_INTERFACE_3 (2u) +#define TEST_SPI_INTERFACE_4 (3u) +#define TEST_SPI_INTERFACE_5 (4u) + +/* clang-format off */ +spiBASE_t spiReg1 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +spiBASE_t spiReg2 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +spiBASE_t spiReg3 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +spiBASE_t spiReg4 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +spiBASE_t spiReg5 = { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + { + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + }, + 0u +}; +/* clang-format on */ + +spiBASE_t *dma_spiInterfaces[DMA_NUMBER_SPI_INTERFACES] = { + NULL_PTR, /* SPI1 */ + NULL_PTR, /* SPI2 */ + NULL_PTR, /* SPI3 */ + NULL_PTR, /* SPI4 */ + NULL_PTR, /* SPI5 */ +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { + dma_spiInterfaces[TEST_SPI_INTERFACE_1] = &spiReg1; + dma_spiInterfaces[TEST_SPI_INTERFACE_2] = &spiReg2; + dma_spiInterfaces[TEST_SPI_INTERFACE_3] = &spiReg3; + dma_spiInterfaces[TEST_SPI_INTERFACE_4] = &spiReg4; + dma_spiInterfaces[TEST_SPI_INTERFACE_5] = &spiReg5; +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/afe/debug/default/config/test_debug_default_cfg.c b/tests/unit/app/driver/afe/ti/dummy/api/test_ti_dummy_afe.c similarity index 81% rename from tests/unit/app/driver/afe/debug/default/config/test_debug_default_cfg.c rename to tests/unit/app/driver/afe/ti/dummy/api/test_ti_dummy_afe.c index 489a384f..342f15bc 100644 --- a/tests/unit/app/driver/afe/debug/default/config/test_debug_default_cfg.c +++ b/tests/unit/app/driver/afe/ti/dummy/api/test_ti_dummy_afe.c @@ -40,27 +40,30 @@ */ /** - * @file test_debug_default_cfg.c + * @file test_ti_dummy_afe.c * @author foxBMS Team - * @date 2020-09-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2023-09-11 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * - * @brief Test of the debug_default_cfg.c module - * + * @brief Test of the wrapper of the TI dummy AFE API implementation of the + * TI AFE API */ /*========== Includes =======================================================*/ #include "unity.h" -#include "debug_default_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ti_dummy.c") +TEST_SOURCE_FILE("ti_dummy_afe.c") -/* it's important to mention the implementation in debug_default.c -here in order to test the correct implementation */ -TEST_FILE("debug_default_cfg.c") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ti/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ti/dummy") +TEST_INCLUDE_PATH("../../src/app/driver/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -72,6 +75,5 @@ void tearDown(void) { } /*========== Test Cases =====================================================*/ - void testDummy(void) { } diff --git a/tests/unit/app/driver/afe/ti/dummy/test_ti_dummy.c b/tests/unit/app/driver/afe/ti/dummy/test_ti_dummy.c new file mode 100644 index 00000000..73f538cf --- /dev/null +++ b/tests/unit/app/driver/afe/ti/dummy/test_ti_dummy.c @@ -0,0 +1,74 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_ti_dummy.c + * @author foxBMS Team + * @date 2023-09-11 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of TI dummy AFE API implementation of the TI AFE API + */ + +/*========== Includes =======================================================*/ +#include "unity.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ti_dummy.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/afe/ti/api") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_aerosol-sensor.c b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_aerosol-sensor.c new file mode 100644 index 00000000..8fdff0ca --- /dev/null +++ b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_aerosol-sensor.c @@ -0,0 +1,343 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_rx_aerosol-sensor.c + * @author foxBMS Team + * @date 2023-08-31 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" + +#include "database_cfg.h" + +#include "can_cbs_rx.h" +#include "can_cfg_rx-message-definitions.h" +#include "can_helper.h" +#include "test_assert_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_rx_aerosol-sensor.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/rx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; +static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { + .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, + .pTablePackValues = &can_tablePackValues, + .pTableSof = &can_tableSof, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMsl = &can_tableMslFlags, + .pTableRsl = &can_tableRslFlags, + .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { + can_tableAerosolSensor.sensorStatus = 0u; + can_tableAerosolSensor.photoelectricError = false; + can_tableAerosolSensor.supplyOvervoltageError = false; + can_tableAerosolSensor.supplyUndervoltageError = false; + can_tableAerosolSensor.particulateMatterConcentration = 0u; + can_tableAerosolSensor.crcCheckCode = 0u; +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +/** + * @brief Testing CANRX_HandleAerosolSensorErrors + * @details The following cases need to be tested: + * - Argument validation: + * - AT1/2: NULL_PTR for kpkCanShim -> assert + * - AT2/2: invalid value for signalData -> assert + * - Routine validation: + * - RT1/4: Function sets expected values in the struct + * - RT2/4: Function sets expected values in the struct + * - RT3/4: Function sets expected values in the struct + * - RT4/4: Function sets expected values in the struct + */ +void testCANRX_HandleAerosolSensorErrors(void) { + /* ======= Assertion tests ============================================= */ + /* ======= AT1/2 ======= */ + TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_HandleAerosolSensorErrors(NULL_PTR, 0u)); + /* ======= AT2/2 ======= */ + TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_HandleAerosolSensorErrors(&can_kShim, 100u)); + + /* ======= Routine tests =============================================== */ + /* reset the error table from previous test */ + can_kShim.pTableAerosolSensor->photoelectricError = false; + can_kShim.pTableAerosolSensor->supplyOvervoltageError = false; + can_kShim.pTableAerosolSensor->supplyUndervoltageError = false; + + /* ======= RT1/4: Test implementation */ + /* ======= RT1/4: call function under test */ + TEST_CANRX_HandleAerosolSensorErrors(&can_kShim, 0u); + /* ======= RT1/4: test output verification */ + TEST_ASSERT_FALSE(can_kShim.pTableAerosolSensor->photoelectricError); + TEST_ASSERT_FALSE(can_kShim.pTableAerosolSensor->supplyOvervoltageError); + TEST_ASSERT_FALSE(can_kShim.pTableAerosolSensor->supplyUndervoltageError); + + /* ======= RT2/4: Test implementation */ + /* ======= RT2/4: call function under test */ + TEST_CANRX_HandleAerosolSensorErrors(&can_kShim, 1u); + /* ======= RT2/4: test output verification */ + TEST_ASSERT_TRUE(can_kShim.pTableAerosolSensor->photoelectricError); + TEST_ASSERT_FALSE(can_kShim.pTableAerosolSensor->supplyOvervoltageError); + TEST_ASSERT_FALSE(can_kShim.pTableAerosolSensor->supplyUndervoltageError); + + /* ======= RT3/4: Test implementation */ + /* reset the error table from previous test */ + can_kShim.pTableAerosolSensor->photoelectricError = false; + can_kShim.pTableAerosolSensor->supplyOvervoltageError = false; + can_kShim.pTableAerosolSensor->supplyUndervoltageError = false; + /* ======= RT3/4: call function under test */ + TEST_CANRX_HandleAerosolSensorErrors(&can_kShim, 2u); + /* ======= RT3/4: test output verification */ + TEST_ASSERT_FALSE(can_kShim.pTableAerosolSensor->photoelectricError); + TEST_ASSERT_TRUE(can_kShim.pTableAerosolSensor->supplyOvervoltageError); + TEST_ASSERT_FALSE(can_kShim.pTableAerosolSensor->supplyUndervoltageError); + + /* ======= RT4/4: Test implementation */ + /* reset the error table from previous test */ + can_kShim.pTableAerosolSensor->photoelectricError = false; + can_kShim.pTableAerosolSensor->supplyOvervoltageError = false; + can_kShim.pTableAerosolSensor->supplyUndervoltageError = false; + /* ======= RT4/4: call function under test */ + TEST_CANRX_HandleAerosolSensorErrors(&can_kShim, 3u); + /* ======= RT4/4: test output verification */ + TEST_ASSERT_FALSE(can_kShim.pTableAerosolSensor->photoelectricError); + TEST_ASSERT_FALSE(can_kShim.pTableAerosolSensor->supplyOvervoltageError); + TEST_ASSERT_TRUE(can_kShim.pTableAerosolSensor->supplyUndervoltageError); +} + +/** + * @brief Testing CANRX_HandleAerosolSensorStatus + * @details The following cases need to be tested: + * - Argument validation: + * - AT1/2: NULL_PTR for kpkCanShim -> assert + * - AT2/2: invalid value for signalData -> assert + * - Routine validation: + * - RT1/2: Function calls expected subroutines + * - RT2/2: Function sets expected values in the struct and calls + * expected subroutines + */ +void testCANRX_HandleAerosolSensorStatus(void) { + /* ======= Assertion tests ============================================= */ + /* ======= AT1/2 ======= */ + TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_HandleAerosolSensorStatus(NULL_PTR, 0u)); + /* ======= AT2/2 ======= */ + TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_HandleAerosolSensorStatus(&can_kShim, 100u)); + + /* ======= Routine tests =============================================== */ + /* ======= RT1/2: Test implementation */ + /* ======= RT1/2: call function under test */ + TEST_CANRX_HandleAerosolSensorStatus(&can_kShim, 0u); + /* ======= RT1/2: test output verification */ + TEST_ASSERT_EQUAL(0, can_kShim.pTableAerosolSensor->sensorStatus); + + /* ======= RT2/2: Test implementation */ + DIAG_Handler_ExpectAndReturn(DIAG_ID_AEROSOL_ALERT, DIAG_EVENT_NOT_OK, DIAG_SYSTEM, 0u, DIAG_HANDLER_RETURN_OK); + /* ======= RT2/2: call function under test */ + TEST_CANRX_HandleAerosolSensorStatus(&can_kShim, 1u); + /* ======= RT2/2: test output verification */ + TEST_ASSERT_EQUAL(1u, can_kShim.pTableAerosolSensor->sensorStatus); +} + +/** + * @brief Testing CANRX_SetParticulateMatterConcentration + * @details The following cases need to be tested: + * - Argument validation: + * - AT1/1: NULL_PTR for kpkCanShim -> assert + * - Routine validation: + * - RT1/1: Function sets expected values in the struct + */ +void testCANRX_SetParticulateMatterConcentration(void) { + /* ======= Assertion tests ============================================= */ + /* ======= AT1/1 ======= */ + TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_SetParticulateMatterConcentration(NULL_PTR, 0u)); + + /* ======= Routine tests =============================================== */ + /* ======= RT1/1: Test implementation */ + /* ======= RT1/1: call function under test */ + TEST_CANRX_SetParticulateMatterConcentration(&can_kShim, 4u); + /* ======= RT1/1: test output verification */ + TEST_ASSERT_EQUAL(4u, can_kShim.pTableAerosolSensor->particulateMatterConcentration); +} + +/** + * @brief Testing CANRX_SetAerosolSensorCrcCheckCode + * @details The following cases need to be tested: + * - Argument validation: + * - AT1/1: NULL_PTR for kpkCanShim -> assert + * - Routine validation: + * - RT1/1: Function calls expected subroutines + */ +void test_CANRX_SetAerosolSensorCrcCheckCode(void) { + /* ======= Assertion tests ============================================= */ + /* ======= AT1/1 ======= */ + TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_SetAerosolSensorCrcCheckCode(NULL_PTR, 0u)); + + /* ======= Routine tests =============================================== */ + /* ======= RT1/1: Test implementation */ + /* ======= RT1/1: call function under test */ + TEST_CANRX_SetAerosolSensorCrcCheckCode(&can_kShim, 4); + /* ======= RT1/1: test output verification */ + TEST_ASSERT_EQUAL(4u, can_kShim.pTableAerosolSensor->crcCheckCode); +} + +/** + * @brief Testing CANRX_AerosolSensor + * @details The following cases need to be tested: + * - Argument validation: + * - AT1/5: invalid message id for message -> assert + * - AT2/5: invalid message idType for message -> assert + * - AT3/5: invalid message DLC for message -> assert + * - AT4/5: NULL_PTR for kpkCanData -> assert + * - AT5/5: NULL_PTR for kpkCanShim -> assert + * - Routine validation: + * - RT1/1: Function calls expected subroutines + */ +void testCANRX_AerosolSensor(void) { + /* ======= Assertion tests ============================================= */ + uint8_t canData[CAN_MAX_DLC] = {0}; + + /* ======= AT1/5 ======= */ + CAN_MESSAGE_PROPERTIES_s testMessageInvalidId = { + .id = CAN_MAX_11BIT_ID, /* invalid message id */ + .idType = CANRX_AEROSOL_SENSOR_ID_TYPE, /* valid id type */ + .dlc = CAN_DEFAULT_DLC, /* valid dlc */ + .endianness = CANRX_AEROSOL_SENSOR_ENDIANNESS, /* valid endianness */ + }; + TEST_ASSERT_FAIL_ASSERT(CANRX_AerosolSensor(testMessageInvalidId, canData, &can_kShim)); + + /* ======= AT2/5 ======= */ + CAN_MESSAGE_PROPERTIES_s testMessageInvalidIdType = { + .id = CANRX_AEROSOL_SENSOR_ID, /* valid message id */ + .idType = CAN_EXTENDED_IDENTIFIER_29_BIT, /* invalid id type */ + .dlc = CAN_DEFAULT_DLC, /* valid dlc */ + .endianness = CANRX_AEROSOL_SENSOR_ENDIANNESS, /* valid endianness */ + }; + TEST_ASSERT_FAIL_ASSERT(CANRX_AerosolSensor(testMessageInvalidIdType, canData, &can_kShim)); + + /* ======= AT3/5 ======= */ + CAN_MESSAGE_PROPERTIES_s testMessageInvalidDlc = { + .id = CANRX_AEROSOL_SENSOR_ID, /* valid message id */ + .idType = CANRX_AEROSOL_SENSOR_ID_TYPE, /* valid id type */ + .dlc = CAN_DEFAULT_DLC + 1u, /* invalid dlc */ + .endianness = CANRX_AEROSOL_SENSOR_ENDIANNESS, /* valid endianness */ + }; + TEST_ASSERT_FAIL_ASSERT(CANRX_AerosolSensor(testMessageInvalidDlc, canData, &can_kShim)); + + /* ======= AT4/5 ======= */ + CAN_MESSAGE_PROPERTIES_s validTestMessage = { + .id = CANRX_AEROSOL_SENSOR_ID, /* valid message id */ + .idType = CANRX_AEROSOL_SENSOR_ID_TYPE, /* valid id type */ + .dlc = CAN_DEFAULT_DLC, /* valid dlc */ + .endianness = CANRX_AEROSOL_SENSOR_ENDIANNESS, /* valid endianness */ + }; + TEST_ASSERT_FAIL_ASSERT(CANRX_AerosolSensor(validTestMessage, NULL_PTR, &can_kShim)); + + /* ======= AT5/5 ======= */ + TEST_ASSERT_FAIL_ASSERT(CANRX_AerosolSensor(validTestMessage, canData, NULL_PTR)); + + /* ======= Routine tests =============================================== */ + /* ======= RT1/1: Test implementation */ + /* ignore reads that are not used in this test */ + DATA_Read1DataBlock_IgnoreAndReturn(STD_OK); + DATA_Write1DataBlock_IgnoreAndReturn(STD_OK); + /* ======= RT1/1: call function under test */ + CANRX_AerosolSensor(validTestMessage, canData, &can_kShim); +} diff --git a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_bms-state-request.c b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_bms-state-request.c new file mode 100644 index 00000000..287504f3 --- /dev/null +++ b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_bms-state-request.c @@ -0,0 +1,148 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_rx_bms-state-request.c + * @author foxBMS Team + * @date 2021-07-28 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockbal.h" +#include "Mockbal_cfg.h" +#include "Mockbms_cfg.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" +#include "Mocksys_mon.h" + +#include "database_cfg.h" + +#include "can_cbs_rx.h" +#include "can_cfg_rx-message-definitions.h" +#include "can_helper.h" +#include "test_assert_helper.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_rx_bms-state-request.c") + +TEST_INCLUDE_PATH("../../src/app/application/bal") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/rx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/sys_mon") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; +static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { + .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, + .pTablePackValues = &can_tablePackValues, + .pTableSof = &can_tableSof, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMsl = &can_tableMslFlags, + .pTableRsl = &can_tableRslFlags, + .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { + can_tableStateRequest.previousStateRequestViaCan = 0u; + can_tableStateRequest.stateRequestViaCan = 0u; + can_tableStateRequest.stateRequestViaCanPending = 0u; + can_tableStateRequest.stateCounter = 0u; +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_current-sensor.c b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_current-sensor.c index 825a3bf2..16736702 100644 --- a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_current-sensor.c +++ b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_current-sensor.c @@ -43,8 +43,8 @@ * @file test_can_cbs_rx_current-sensor.c * @author foxBMS Team * @date 2021-04-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -66,7 +66,17 @@ #include "can_cbs_rx.h" #include "can_helper.h" -TEST_FILE("can_cbs_rx_current-sensor.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_rx_current-sensor.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/rx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -78,13 +88,15 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; OS_QUEUE imd_canDataQueue = NULL_PTR; @@ -98,16 +110,16 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; -static uint8_t muxId = 0u; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_debug.c b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_debug.c index 94b5dfcc..2174a270 100644 --- a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_debug.c +++ b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_debug.c @@ -43,8 +43,8 @@ * @file test_can_cbs_rx_debug.c * @author foxBMS Team * @date 2021-04-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -56,7 +56,7 @@ #include "unity.h" #include "Mockcan.h" #include "Mockcan_cbs_tx_debug-response.h" -#include "Mockcan_cbs_tx_unsupported-message.h" +#include "Mockcan_cbs_tx_debug-unsupported-multiplexer-values.h" #include "Mockdatabase.h" #include "Mockdiag.h" #include "Mockfoxmath.h" @@ -75,7 +75,22 @@ #include #include -TEST_FILE("can_cbs_rx_debug.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_rx_debug.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/rx") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/sys") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -107,13 +122,15 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; OS_QUEUE imd_canDataQueue = NULL_PTR; OS_QUEUE ftsk_rtcSetTimeQueue = NULL_PTR; @@ -128,12 +145,14 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; /*========== Setup and Teardown =============================================*/ @@ -325,6 +344,16 @@ void testCANRX_TriggerMcuWaferInformationMessage(void) { TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_TriggerMcuWaferInformationMessage()); } +void testCANRX_TriggerCommitHashMessage(void) { + /* sending response message works as expected */ + CANTX_DebugResponse_IgnoreAndReturn(STD_OK); + TEST_CANRX_TriggerCommitHashMessage(); + + /* sending response message does not work as expected */ + CANTX_DebugResponse_IgnoreAndReturn(STD_NOT_OK); + TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_TriggerCommitHashMessage()); +} + void testCANRX_TriggerTimeInfoMessage(void) { /* sending response message works as expected */ CANTX_DebugResponse_IgnoreAndReturn(STD_OK); @@ -377,6 +406,17 @@ void testCANRX_CheckIfMcuWaferInformationIsRequested(void) { TEST_ASSERT_TRUE(isRequested); } +void testCANRX_CheckIfCommitHashIsRequested(void) { + /* test endianness assertion */ + TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_CheckIfCommitHashIsRequested(testMessageDataZero, invalidEndianness)); + + /* test correct message -> return true */ + /* set bit to indicate that the MCU wafer information is requested */ + uint64_t testMessageData = ((uint64_t)1u) << 52u; + bool isRequested = TEST_CANRX_CheckIfCommitHashIsRequested(testMessageData, validEndianness); + TEST_ASSERT_TRUE(isRequested); +} + void testCANRX_CheckIfSoftwareResetIsRequested(void) { /* test endianness assertion */ TEST_ASSERT_FAIL_ASSERT(TEST_CANRX_CheckIfSoftwareResetIsRequested(testMessageDataZero, invalidEndianness)); diff --git a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-info.c b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-info.c new file mode 100644 index 00000000..b163e176 --- /dev/null +++ b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-info.c @@ -0,0 +1,132 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_rx_imd-info.c + * @author foxBMS Team + * @date 2021-04-22 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" + +#include "database_cfg.h" + +#include "can_cbs_rx.h" +#include "can_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_rx_imd-info.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/rx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; +static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { + .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, + .pTablePackValues = &can_tablePackValues, + .pTableSof = &can_tableSof, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMsl = &can_tableMslFlags, + .pTableRsl = &can_tableRslFlags, + .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd.c b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-response.c similarity index 84% rename from tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd.c rename to tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-response.c index ec13e127..53f77a5c 100644 --- a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd.c +++ b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-response.c @@ -40,11 +40,11 @@ */ /** - * @file test_can_cbs_rx_imd.c + * @file test_can_cbs_rx_imd-response.c * @author foxBMS Team * @date 2021-04-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -66,7 +66,17 @@ #include "can_cbs_rx.h" #include "can_helper.h" -TEST_FILE("can_cbs_rx_imd.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_rx_imd-response.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/rx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -78,7 +88,8 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; @@ -98,7 +109,8 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, @@ -106,8 +118,6 @@ const CAN_SHIM_s can_kShim = { .pTableMol = &can_tableMolFlags, }; -static uint8_t muxId = 0u; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_state-request.c b/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_state-request.c deleted file mode 100644 index 18daf797..00000000 --- a/tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_state-request.c +++ /dev/null @@ -1,285 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_can_cbs_rx_state-request.c - * @author foxBMS Team - * @date 2021-07-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Tests for the CAN driver callbacks - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" -#include "Mockbal.h" -#include "Mockbal_cfg.h" -#include "Mockbms_cfg.h" -#include "Mockcan.h" -#include "Mockdatabase.h" -#include "Mockdiag.h" -#include "Mockfoxmath.h" -#include "Mockimd.h" -#include "Mockos.h" -#include "Mocksys_mon.h" - -#include "database_cfg.h" - -#include "can_cbs_rx.h" -#include "can_cfg_rx-message-definitions.h" -#include "can_helper.h" -#include "test_assert_helper.h" - -#include -#include - -TEST_FILE("can_cbs_rx_state-request.c") - -/*========== Definitions and Implementations for Unit Test ==================*/ - -static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; -static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; -static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; -static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; -static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; -static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; -static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; -static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; -static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; -static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { - .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; - -OS_QUEUE imd_canDataQueue = NULL_PTR; - -const CAN_SHIM_s can_kShim = { - .pQueueImd = &imd_canDataQueue, - .pTableCellVoltage = &can_tableCellVoltages, - .pTableCellTemperature = &can_tableTemperatures, - .pTableMinMax = &can_tableMinimumMaximumValues, - .pTableCurrentSensor = &can_tableCurrentSensor, - .pTableOpenWire = &can_tableOpenWire, - .pTableStateRequest = &can_tableStateRequest, - .pTablePackValues = &can_tablePackValues, - .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, - .pTableErrorState = &can_tableErrorState, - .pTableInsulation = &can_tableInsulation, - .pTableMsl = &can_tableMslFlags, - .pTableRsl = &can_tableRslFlags, - .pTableMol = &can_tableMolFlags, -}; - -static uint8_t muxId = 0u; - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { - can_tableStateRequest.previousStateRequestViaCan = 0u; - can_tableStateRequest.stateRequestViaCan = 0u; - can_tableStateRequest.stateRequestViaCanPending = 0u; - can_tableStateRequest.stateCounter = 0u; -} - -void tearDown(void) { -} - -/*========== Test Cases =====================================================*/ -/** test the handling of illegal input by callback */ -void testRxRequestIllegalInput(void) { - CAN_MESSAGE_PROPERTIES_s testMessage = { - .id = CAN_MAX_11BIT_ID, - .idType = CAN_STANDARD_IDENTIFIER_11_BIT, - .dlc = 0u, - .endianness = CAN_LITTLE_ENDIAN, - }; - - uint8_t canData[CAN_MAX_DLC] = {0}; - - /* test 0 */ - TEST_ASSERT_FAIL_ASSERT(CANRX_BmsStateRequest(testMessage, canData, &can_kShim)); - - /* test 1 */ - testMessage.id = 0u; - testMessage.dlc = CAN_DEFAULT_DLC + 1u; - - TEST_ASSERT_FAIL_ASSERT(CANRX_BmsStateRequest(testMessage, canData, &can_kShim)); - - /* test 2 */ - TEST_ASSERT_FAIL_ASSERT(CANRX_BmsStateRequest(testMessage, NULL_PTR, &can_kShim)); - - /* test 3 */ - TEST_ASSERT_FAIL_ASSERT(CANRX_BmsStateRequest(testMessage, canData, NULL_PTR)); -} - -/** test mode request */ -void testRxRequestModeRequest(void) { - CAN_MESSAGE_PROPERTIES_s testMessage = { - .id = CANRX_BMS_STATE_REQUEST_ID, - .idType = CANRX_BMS_STATE_REQUEST_ID_TYPE, - .dlc = CAN_FOXBMS_MESSAGES_DEFAULT_DLC, - .endianness = CANRX_BMS_STATE_REQUEST_ENDIANNESS, - }; - - uint8_t canData[CAN_MAX_DLC] = {0}; - - /* ignore reads that are not used in this test */ - DATA_Read1DataBlock_IgnoreAndReturn(STD_OK); - BAL_GetInitializationState_IgnoreAndReturn(STD_NOT_OK); - BAL_SetBalancingThreshold_Ignore(); - DATA_Write1DataBlock_IgnoreAndReturn(STD_OK); - - /* request disconnect (STANDBY) */ - canData[0u] = 0u; - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); - TEST_ASSERT_EQUAL(BMS_REQ_ID_STANDBY, can_tableStateRequest.stateRequestViaCan); - - /* request discharge (NORMAL) */ - canData[0u] = 1u; - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); - TEST_ASSERT_EQUAL(BMS_REQ_ID_NORMAL, can_tableStateRequest.stateRequestViaCan); - - /* request charge (CHARGE) */ - canData[0u] = 2u; - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); - TEST_ASSERT_EQUAL(BMS_REQ_ID_CHARGE, can_tableStateRequest.stateRequestViaCan); - - /* no valid request */ - canData[0u] = 3u; - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); - TEST_ASSERT_EQUAL(BMS_REQ_ID_NOREQ, can_tableStateRequest.stateRequestViaCan); - - /* state counter overflow */ - can_tableStateRequest.stateCounter = UINT8_MAX; - canData[0u] = 0u; - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); - TEST_ASSERT_EQUAL(0u, can_tableStateRequest.stateCounter); - - /* state: no update without change an no time */ - canData[0u] = 0u; - OS_CheckTimeHasPassed_ExpectAndReturn(0u, 0u, false); - OS_CheckTimeHasPassed_IgnoreArg_oldTimeStamp_ms(); - OS_CheckTimeHasPassed_IgnoreArg_timeToPass_ms(); - can_tableStateRequest.stateRequestViaCanPending = 42u; - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); - TEST_ASSERT_EQUAL(42u, can_tableStateRequest.stateRequestViaCanPending); - - /* state: update with change of time */ - canData[0u] = 0u; - OS_CheckTimeHasPassed_ExpectAndReturn(0u, 0u, true); - OS_CheckTimeHasPassed_IgnoreArg_oldTimeStamp_ms(); - OS_CheckTimeHasPassed_IgnoreArg_timeToPass_ms(); - can_tableStateRequest.stateRequestViaCanPending = 42u; - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); - TEST_ASSERT_EQUAL(BMS_REQ_ID_STANDBY, can_tableStateRequest.stateRequestViaCanPending); -} - -/** test balancing request */ -void testRxRequestBalancingRequest(void) { - CAN_MESSAGE_PROPERTIES_s testMessage = { - .id = CANRX_BMS_STATE_REQUEST_ID, - .idType = CANRX_BMS_STATE_REQUEST_ID_TYPE, - .dlc = CAN_FOXBMS_MESSAGES_DEFAULT_DLC, - .endianness = CANRX_BMS_STATE_REQUEST_ENDIANNESS, - }; - uint8_t canData[CAN_MAX_DLC] = {0}; - - /* ignore reads that are not used in this test */ - DATA_Read1DataBlock_IgnoreAndReturn(STD_OK); - DATA_Write1DataBlock_IgnoreAndReturn(STD_OK); - OS_CheckTimeHasPassed_IgnoreAndReturn(false); - - /* request no balancing */ - canData[1u] = 0u; - canData[2u] = 0u; - BAL_GetInitializationState_ExpectAndReturn(STD_OK); - BAL_SetStateRequest_ExpectAndReturn(BAL_STATE_GLOBAL_DISABLE_REQUEST, BAL_OK); - BAL_SetBalancingThreshold_Expect(0u); - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); - - /* request balancing */ - canData[1u] = 1u; - canData[2u] = 0x42; - BAL_GetInitializationState_ExpectAndReturn(STD_OK); - BAL_SetStateRequest_ExpectAndReturn(BAL_STATE_GLOBAL_ENABLE_REQUEST, BAL_OK); - BAL_SetBalancingThreshold_Expect(0x42u); - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); - - /* balancing not initialized */ - canData[1u] = 1u; - canData[2u] = 0x33u; - BAL_GetInitializationState_ExpectAndReturn(STD_NOT_OK); - BAL_SetBalancingThreshold_Expect(0x33u); - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); -} - -/** test reset flags request */ -void testRxRequestResetFlags(void) { - CAN_MESSAGE_PROPERTIES_s testMessage = { - .id = CANRX_BMS_STATE_REQUEST_ID, - .idType = CANRX_BMS_STATE_REQUEST_ID_TYPE, - .dlc = CAN_FOXBMS_MESSAGES_DEFAULT_DLC, - .endianness = CANRX_BMS_STATE_REQUEST_ENDIANNESS, - }; - uint8_t canData[CAN_MAX_DLC] = {0}; - - /* ignore reads that are not used in this test */ - DATA_Read1DataBlock_IgnoreAndReturn(STD_OK); - DATA_Write1DataBlock_IgnoreAndReturn(STD_OK); - OS_CheckTimeHasPassed_IgnoreAndReturn(false); - BAL_SetBalancingThreshold_Ignore(); - BAL_GetInitializationState_IgnoreAndReturn(STD_NOT_OK); - - /* request to reset flags */ - canData[0u] = 4u; - for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { - DIAG_Handler_ExpectAndReturn( - DIAG_ID_DEEP_DISCHARGE_DETECTED, DIAG_EVENT_OK, DIAG_STRING, s, DIAG_HANDLER_RETURN_OK); - } - SYSM_ClearAllTimingViolations_Expect(); - CANRX_BmsStateRequest(testMessage, canData, &can_kShim); -} diff --git a/tests/unit/app/driver/can/cbs/test_can_helper.c b/tests/unit/app/driver/can/cbs/test_can_helper.c index 106d88df..33c99592 100644 --- a/tests/unit/app/driver/can/cbs/test_can_helper.c +++ b/tests/unit/app/driver/can/cbs/test_can_helper.c @@ -43,8 +43,8 @@ * @file test_can_helper.c * @author foxBMS Team * @date 2021-04-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -70,6 +70,16 @@ #include #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state-details.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state-details.c new file mode 100644 index 00000000..238b28cf --- /dev/null +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state-details.c @@ -0,0 +1,137 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_tx_bms-state-details.c + * @author foxBMS Team + * @date 2021-07-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockbms.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" +#include "Mocksys_mon.h" + +#include "database_cfg.h" + +#include "can_cbs_tx.h" +#include "can_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_bms-state-details.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/sys_mon") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; +static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { + .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, + .pTablePackValues = &can_tablePackValues, + .pTableSof = &can_tableSof, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMsl = &can_tableMslFlags, + .pTableRsl = &can_tableRslFlags, + .pTableMol = &can_tableMolFlags, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state.c new file mode 100644 index 00000000..453088aa --- /dev/null +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state.c @@ -0,0 +1,139 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_tx_bms-state.c + * @author foxBMS Team + * @date 2021-07-27 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockbms.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" +#include "Mocksys_mon.h" + +#include "database_cfg.h" + +#include "can_cbs_tx.h" +#include "can_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_bms-state.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/sys_mon") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; +static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { + .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, + .pTablePackValues = &can_tablePackValues, + .pTableSof = &can_tableSof, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMsl = &can_tableMslFlags, + .pTableRsl = &can_tableRslFlags, + .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-temperatures.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-temperatures.c index 4abbb970..fb029486 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-temperatures.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-temperatures.c @@ -43,8 +43,8 @@ * @file test_can_cbs_tx_cell-temperatures.c * @author foxBMS Team * @date 2021-04-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -68,7 +68,18 @@ #include "can_helper.h" #include "database_helper.h" -TEST_FILE("can_cbs_tx_cell-temperatures.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_cell-temperatures.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -80,13 +91,15 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; OS_QUEUE imd_canDataQueue = NULL_PTR; @@ -100,12 +113,14 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; static uint8_t muxId = 0u; @@ -130,12 +145,12 @@ void testCAN_TxCellTemperature(void) { DATA_Read1DataBlock_IgnoreAndReturn(0u); for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { - can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][0] = 100; - can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][1] = 110; - can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][2] = 120; - can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][3] = 250; - can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][4] = 400; - can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][5] = -100; + can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][0u][0u] = 100; + can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][0u][1u] = 110; + can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][0u][2u] = 120; + can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][0u][3u] = 250; + can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][0u][4u] = 400; + can_kShim.pTableCellTemperature->cellTemperature_ddegC[s][0u][5u] = -100; } CANTX_CellTemperatures(testMessage, data, &muxId, &can_kShim); diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-voltages.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-voltages.c index 5fa8d566..5ddb42d4 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-voltages.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-voltages.c @@ -43,8 +43,8 @@ * @file test_can_cbs_tx_cell-voltages.c * @author foxBMS Team * @date 2021-04-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -68,7 +68,18 @@ #include "can_helper.h" #include "database_helper.h" -TEST_FILE("can_cbs_tx_cell-voltages.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_cell-voltages.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -80,13 +91,15 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; OS_QUEUE imd_canDataQueue = NULL_PTR; @@ -100,12 +113,14 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; static uint8_t muxId = 0u; @@ -130,10 +145,10 @@ void testCAN_TxVoltage(void) { DATA_Read1DataBlock_IgnoreAndReturn(0u); for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { - can_kShim.pTableCellVoltage->cellVoltage_mV[s][0] = 2000; - can_kShim.pTableCellVoltage->cellVoltage_mV[s][1] = 2100; - can_kShim.pTableCellVoltage->cellVoltage_mV[s][2] = 3000; - can_kShim.pTableCellVoltage->cellVoltage_mV[s][3] = 3700; + can_kShim.pTableCellVoltage->cellVoltage_mV[s][0u][0u] = 2000; + can_kShim.pTableCellVoltage->cellVoltage_mV[s][0u][1u] = 2100; + can_kShim.pTableCellVoltage->cellVoltage_mV[s][0u][2u] = 3000; + can_kShim.pTableCellVoltage->cellVoltage_mV[s][0u][3u] = 3700; } CANTX_CellVoltages(testMessage, data, &muxId, &can_kShim); diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_crash-dump.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_crash-dump.c new file mode 100644 index 00000000..73027073 --- /dev/null +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_crash-dump.c @@ -0,0 +1,91 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_tx_crash-dump.c + * @author foxBMS Team + * @date 2023-02-09 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of some module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockcan.h" + +#include "can_cfg.h" + +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_crash-dump.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +OS_QUEUE ftsk_imdCanDataQueue = NULL_PTR; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +void testCANTX_CrashDump(void) { +} diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-response.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-response.c index f9e526e6..880f74b9 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-response.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-response.c @@ -43,8 +43,8 @@ * @file test_can_cbs_tx_debug-response.c * @author foxBMS Team * @date 2022-08-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -55,6 +55,7 @@ /*========== Includes =======================================================*/ #include "unity.h" #include "Mockcan.h" +#include "Mockcan_helper.h" #include "Mockfoxmath.h" #include "Mockrtc.h" @@ -62,11 +63,20 @@ #include "version_cfg.h" #include "can_cbs_tx.h" -#include "can_helper.h" +#include "can_cbs_tx_debug-response.h" +#include "can_cfg_tx-message-definitions.h" #include -TEST_FILE("can_cbs_tx_debug-response.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_debug-response.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") /*========== Definitions and Implementations for Unit Test ==================*/ const CAN_NODE_s can_node1 = { @@ -97,5 +107,20 @@ void tearDown(void) { } /*========== Test Cases =====================================================*/ -void testDummy(void) { +void testTransmitCommitHash(void) { + uint8_t testData[CAN_MAX_DLC] = {0}; + + uint64_t testMessage = 0; + CAN_TxSetMessageDataWithSignalData_Expect(&testMessage, 7u, 8u, 0x0005u, CAN_BIG_ENDIAN); + CAN_TxSetMessageDataWithSignalData_Expect(&testMessage, 15u, 8u, 0x0064u, CAN_BIG_ENDIAN); + CAN_TxSetMessageDataWithSignalData_Expect(&testMessage, 23u, 8u, 0x0065u, CAN_BIG_ENDIAN); + CAN_TxSetMessageDataWithSignalData_Expect(&testMessage, 31u, 8u, 0x0061u, CAN_BIG_ENDIAN); + CAN_TxSetMessageDataWithSignalData_Expect(&testMessage, 39u, 8u, 0x0064u, CAN_BIG_ENDIAN); + CAN_TxSetMessageDataWithSignalData_Expect(&testMessage, 47u, 8u, 0x0062u, CAN_BIG_ENDIAN); + CAN_TxSetMessageDataWithSignalData_Expect(&testMessage, 55u, 8u, 0x0065u, CAN_BIG_ENDIAN); + CAN_TxSetMessageDataWithSignalData_Expect(&testMessage, 63u, 8u, 0x0065u, CAN_BIG_ENDIAN); + CAN_TxSetCanDataWithMessageData_Expect(testMessage, &testData[0], CAN_BIG_ENDIAN); + CAN_DataSend_ExpectAndReturn( + CAN_NODE_1, CANTX_DEBUG_RESPONSE_ID, CAN_STANDARD_IDENTIFIER_11_BIT, &testData[0], STD_OK); + CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_TRANSMIT_COMMIT_HASH); } diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_unsupported-message.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-unsupported-multiplexer-values.c similarity index 78% rename from tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_unsupported-message.c rename to tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-unsupported-multiplexer-values.c index a50dd98d..6d033079 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_unsupported-message.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-unsupported-multiplexer-values.c @@ -40,11 +40,11 @@ */ /** - * @file test_can_cbs_tx_unsupported-message.c + * @file test_can_cbs_tx_debug-unsupported-multiplexer-values.c * @author foxBMS Team * @date 2022-11-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -65,20 +65,31 @@ #include "database_cfg.h" #include "can_cbs_tx.h" -#include "can_cbs_tx_unsupported-message.h" +#include "can_cbs_tx_debug-unsupported-multiplexer-values.h" -TEST_FILE("can_cbs_tx_unsupported-message.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_debug-unsupported-multiplexer-values.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ #define TEST_UNSUPPORTED_MULTIPLEXER 0x201 #define TEST_UNSUPPORTED_MULTIPLEXER_IDENTIFIER_TYPE (CAN_STANDARD_IDENTIFIER_11_BIT) -extern const CAN_NODE_s can_node1 = { +const CAN_NODE_s can_node1 = { .canNodeRegister = canREG1, }; -extern const CAN_NODE_s can_node2Isolated = { +const CAN_NODE_s can_node2Isolated = { .canNodeRegister = canREG2, }; @@ -90,13 +101,15 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; OS_QUEUE imd_canDataQueue = NULL_PTR; OS_QUEUE ftsk_rtcSetTimeQueue = NULL_PTR; @@ -111,16 +124,16 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; -static uint8_t muxId = 0u; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_imd-request.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_imd-request.c new file mode 100644 index 00000000..32c37329 --- /dev/null +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_imd-request.c @@ -0,0 +1,93 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_tx_imd-request.c + * @author foxBMS Team + * @date 2023-06-14 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" + +#include "database_cfg.h" + +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_imd-request.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_limit-values.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-limits.c similarity index 80% rename from tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_limit-values.c rename to tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-limits.c index 7167a8bc..cb757d0d 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_limit-values.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-limits.c @@ -40,11 +40,11 @@ */ /** - * @file test_can_cbs_tx_limit-values.c + * @file test_can_cbs_tx_pack-limits.c * @author foxBMS Team * @date 2021-07-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -68,7 +68,18 @@ #include "can_cfg_tx-message-definitions.h" #include "can_helper.h" -TEST_FILE("can_cbs_tx_limit-values.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_pack-limits.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -80,18 +91,20 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; -OS_QUEUE imd_canDataQueue = NULL_PTR; +OS_QUEUE ftsk_imdCanDataQueue = NULL_PTR; const CAN_SHIM_s can_kShim = { - .pQueueImd = &imd_canDataQueue, + .pQueueImd = &ftsk_imdCanDataQueue, .pTableCellVoltage = &can_tableCellVoltages, .pTableCellTemperature = &can_tableTemperatures, .pTableMinMax = &can_tableMinimumMaximumValues, @@ -100,16 +113,16 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; -static uint8_t muxId = 0u; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_minimum-maximum-values.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-minimum-maximum-values.c similarity index 83% rename from tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_minimum-maximum-values.c rename to tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-minimum-maximum-values.c index 53b6247b..7e327db9 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_minimum-maximum-values.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-minimum-maximum-values.c @@ -40,11 +40,11 @@ */ /** - * @file test_can_cbs_tx_minimum-maximum-values.c + * @file test_can_cbs_tx_pack-minimum-maximum-values.c * @author foxBMS Team * @date 2021-04-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -70,7 +70,21 @@ #include -TEST_FILE("can_cbs_tx_minimum-maximum-values.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_pack-minimum-maximum-values.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -82,13 +96,14 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; OS_QUEUE imd_canDataQueue = NULL_PTR; @@ -102,16 +117,15 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; -static uint8_t muxId = 0u; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-state-estimation.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-state-estimation.c index 6eb38486..ebd81a74 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-state-estimation.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-state-estimation.c @@ -43,8 +43,8 @@ * @file test_can_cbs_tx_pack-state-estimation.c * @author foxBMS Team * @date 2021-07-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -70,7 +70,20 @@ #include -TEST_FILE("can_cbs_tx_pack-state-estimation.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_pack-state-estimation.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -82,13 +95,15 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; OS_QUEUE imd_canDataQueue = NULL_PTR; @@ -102,16 +117,16 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; -static uint8_t muxId = 0u; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } @@ -130,14 +145,14 @@ void testCAN_TxStateEstimationCharging(void) { uint8_t data[8] = {0}; for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { - can_kShim.pTableSox->minimumSoc_perc[s] = 71.2f; - can_kShim.pTableSox->maximumSoc_perc[s] = 74.2f; - can_kShim.pTableSox->minimumSoe_perc[s] = 74.6f; - can_kShim.pTableSox->maximumSoe_perc[s] = 78.1f; - can_kShim.pTableSox->minimumSoe_Wh[s] = 19200 / BS_NR_OF_STRINGS; + can_kShim.pTableSoc->minimumSoc_perc[s] = 71.2f; + can_kShim.pTableSoc->maximumSoc_perc[s] = 74.2f; + can_kShim.pTableSoe->minimumSoe_perc[s] = 74.6f; + can_kShim.pTableSoe->maximumSoe_perc[s] = 78.1f; + can_kShim.pTableSoe->minimumSoe_Wh[s] = 19200 / BS_NR_OF_STRINGS; } - DATA_Read1DataBlock_IgnoreAndReturn(0u); + DATA_Read2DataBlocks_IgnoreAndReturn(0u); /* System is currently charging */ BMS_GetBatterySystemState_IgnoreAndReturn(BMS_CHARGING); /* All strings connected */ @@ -179,14 +194,14 @@ void testCAN_TxStateEstimationDischarging(void) { uint8_t data[8] = {0}; for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) { - can_kShim.pTableSox->minimumSoc_perc[s] = 74.2f; - can_kShim.pTableSox->maximumSoc_perc[s] = 78.2f; - can_kShim.pTableSox->minimumSoe_perc[s] = 78.1f; - can_kShim.pTableSox->maximumSoe_perc[s] = 83.1f; - can_kShim.pTableSox->minimumSoe_Wh[s] = 19200 / BS_NR_OF_STRINGS; + can_kShim.pTableSoc->minimumSoc_perc[s] = 74.2f; + can_kShim.pTableSoc->maximumSoc_perc[s] = 78.2f; + can_kShim.pTableSoe->minimumSoe_perc[s] = 78.1f; + can_kShim.pTableSoe->maximumSoe_perc[s] = 83.1f; + can_kShim.pTableSoe->minimumSoe_Wh[s] = 19200 / BS_NR_OF_STRINGS; } - DATA_Read1DataBlock_IgnoreAndReturn(0u); + DATA_Read2DataBlocks_IgnoreAndReturn(0u); /* System is currently charging */ BMS_GetBatterySystemState_IgnoreAndReturn(BMS_DISCHARGING); /* All strings connected */ diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_system-values.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values-p0.c similarity index 80% rename from tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_system-values.c rename to tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values-p0.c index b9fd7f4c..bdce1a09 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_system-values.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values-p0.c @@ -40,11 +40,11 @@ */ /** - * @file test_can_cbs_tx_system-values.c + * @file test_can_cbs_tx_pack-values-p0.c * @author foxBMS Team * @date 2021-07-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -67,7 +67,18 @@ #include "can_cfg_tx-message-definitions.h" #include "can_helper.h" -TEST_FILE("can_cbs_tx_system-values.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_pack-values-p0.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -79,13 +90,15 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; OS_QUEUE imd_canDataQueue = NULL_PTR; @@ -99,16 +112,16 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; -static uint8_t muxId = 0u; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_state.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values-p1.c similarity index 82% rename from tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_state.c rename to tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values-p1.c index 27dbc668..535fa10a 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_state.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values-p1.c @@ -40,11 +40,11 @@ */ /** - * @file test_can_cbs_tx_state.c + * @file test_can_cbs_tx_pack-values-p1.c * @author foxBMS Team - * @date 2021-07-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @date 2023-05-31 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -54,21 +54,31 @@ /*========== Includes =======================================================*/ #include "unity.h" -#include "Mockbms.h" #include "Mockcan.h" #include "Mockdatabase.h" #include "Mockdiag.h" #include "Mockfoxmath.h" #include "Mockimd.h" #include "Mockos.h" -#include "Mocksys_mon.h" #include "database_cfg.h" #include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" #include "can_helper.h" -TEST_FILE("can_cbs_tx_state.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_pack-values-p1.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -80,7 +90,8 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; @@ -100,7 +111,8 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, @@ -108,8 +120,6 @@ const CAN_SHIM_s can_kShim = { .pTableMol = &can_tableMolFlags, }; -static uint8_t muxId = 0u; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-minimum-maximum-values.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-minimum-maximum-values.c new file mode 100644 index 00000000..9c59299a --- /dev/null +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-minimum-maximum-values.c @@ -0,0 +1,100 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_tx_string-minimum-maximum-values.c + * @author foxBMS Team + * @date 2021-04-22 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockbms.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" + +#include "database_cfg.h" + +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" + +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_string-minimum-maximum-values.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state-estimation.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state-estimation.c index 52ee643a..37eff60d 100644 --- a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state-estimation.c +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state-estimation.c @@ -43,8 +43,8 @@ * @file test_can_cbs_tx_string-state-estimation.c * @author foxBMS Team * @date 2021-07-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -68,7 +68,20 @@ #include "can_cfg_tx-message-definitions.h" #include "can_helper.h" -TEST_FILE("can_cbs_tx_string-state-estimation.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_string-state-estimation.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -80,13 +93,15 @@ static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueI static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; -static DATA_BLOCK_SOX_s can_tableSox = {.header.uniqueId = DATA_BLOCK_ID_SOX}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; -static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; -static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; -static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_AEROSOL_SENSOR_s can_tableAerosolSensor = {.header.uniqueId = DATA_BLOCK_ID_AEROSOL_SENSOR}; OS_QUEUE imd_canDataQueue = NULL_PTR; @@ -100,16 +115,16 @@ const CAN_SHIM_s can_kShim = { .pTableStateRequest = &can_tableStateRequest, .pTablePackValues = &can_tablePackValues, .pTableSof = &can_tableSof, - .pTableSox = &can_tableSox, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, .pTableErrorState = &can_tableErrorState, .pTableInsulation = &can_tableInsulation, .pTableMsl = &can_tableMslFlags, .pTableRsl = &can_tableRslFlags, .pTableMol = &can_tableMolFlags, + .pTableAerosolSensor = &can_tableAerosolSensor, }; -static uint8_t muxId = 0u; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state.c new file mode 100644 index 00000000..ef091808 --- /dev/null +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state.c @@ -0,0 +1,137 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_tx_string-state.c + * @author foxBMS Team + * @date 2023-05-31 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockbms.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" +#include "Mocksys_mon.h" + +#include "database_cfg.h" + +#include "can_cbs_tx.h" +#include "can_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_string-state.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/sys_mon") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; +static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { + .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, + .pTablePackValues = &can_tablePackValues, + .pTableSof = &can_tableSof, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMsl = &can_tableMslFlags, + .pTableRsl = &can_tableRslFlags, + .pTableMol = &can_tableMolFlags, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values-p0.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values-p0.c new file mode 100644 index 00000000..d4cdae64 --- /dev/null +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values-p0.c @@ -0,0 +1,132 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_tx_string-values-p0.c + * @author foxBMS Team + * @date 2023-05-31 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" + +#include "database_cfg.h" + +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_string-values-p0.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; +static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { + .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, + .pTablePackValues = &can_tablePackValues, + .pTableSof = &can_tableSof, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMsl = &can_tableMslFlags, + .pTableRsl = &can_tableRslFlags, + .pTableMol = &can_tableMolFlags, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values-p1.c b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values-p1.c new file mode 100644 index 00000000..f2575202 --- /dev/null +++ b/tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values-p1.c @@ -0,0 +1,132 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_cbs_tx_string-values-p1.c + * @author foxBMS Team + * @date 2023-05-31 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the CAN driver callbacks + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockcan.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockimd.h" +#include "Mockos.h" + +#include "database_cfg.h" + +#include "can_cbs_tx.h" +#include "can_cfg_tx-message-definitions.h" +#include "can_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cbs_tx_string-values-p1.c") + +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_SOF_s can_tableSof = {.header.uniqueId = DATA_BLOCK_ID_SOF}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; +static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { + .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, + .pTablePackValues = &can_tablePackValues, + .pTableSof = &can_tableSof, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMsl = &can_tableMslFlags, + .pTableRsl = &can_tableRslFlags, + .pTableMol = &can_tableMolFlags, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testDummy(void) { +} diff --git a/tests/unit/app/driver/can/test_can.c b/tests/unit/app/driver/can/test_can.c index 495e3492..2fea1f91 100644 --- a/tests/unit/app/driver/can/test_can.c +++ b/tests/unit/app/driver/can/test_can.c @@ -43,13 +43,16 @@ * @file test_can.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * * @brief Tests for the CAN driver - * + * @details This file implements the test of the validation functions for tx message + * configuration with correct configuration for message period and phase. + * Both functions are tested to not assert an error with valid configuration. + * Invalid configurations are tested in test_can_1 and test_can_2. */ /*========== Includes =======================================================*/ @@ -76,6 +79,19 @@ #include #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + /*========== Definitions and Implementations for Unit Test ==================*/ /* see src/app/driver/config/can_cfg_rx-message-definitions.h, but we omit @@ -120,22 +136,42 @@ const CAN_NODE_s can_node2Isolated = { .canNodeRegister = canREG2, }; -static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; -static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; -static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; -static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; -static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; -static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_ERROR_STATE_s can_tableErrorState = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; +static DATA_BLOCK_INSULATION_MONITORING_s can_tableInsulation = { + .header.uniqueId = DATA_BLOCK_ID_INSULATION_MONITORING}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_MOL_FLAG_s can_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; +static DATA_BLOCK_MSL_FLAG_s can_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_PACK_VALUES_s can_tablePackValues = {.header.uniqueId = DATA_BLOCK_ID_PACK_VALUES}; +static DATA_BLOCK_RSL_FLAG_s can_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; +static DATA_BLOCK_SOC_s can_tableSoc = {.header.uniqueId = DATA_BLOCK_ID_SOC}; +static DATA_BLOCK_SOE_s can_tableSoe = {.header.uniqueId = DATA_BLOCK_ID_SOE}; +static DATA_BLOCK_SOH_s can_tableSoh = {.header.uniqueId = DATA_BLOCK_ID_SOH}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; OS_QUEUE imd_canDataQueue = NULL_PTR; const CAN_SHIM_s can_kShim = { - .pQueueImd = &imd_canDataQueue, - .pTableCellVoltage = &can_tableCellVoltages, + .pQueueImd = &ftsk_imdCanDataQueue, .pTableCellTemperature = &can_tableTemperatures, - .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCellVoltage = &can_tableCellVoltages, .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableMol = &can_tableMolFlags, + .pTableMsl = &can_tableMslFlags, .pTableOpenWire = &can_tableOpenWire, + .pTablePackValues = &can_tablePackValues, + .pTableRsl = &can_tableRslFlags, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableSof = NULL_PTR, + .pTableSoh = &can_tableSoh, .pTableStateRequest = &can_tableStateRequest, }; @@ -162,15 +198,24 @@ const CAN_RX_MESSAGE_TYPE_s can_rxMessages[] = { {CAN_NODE_1, TEST_CANRX_DUMMY_MESSAGE, &TEST_CANRX_DummyCallback}, }; -const uint8_t can_txLength = sizeof(can_txMessages) / sizeof(can_txMessages[0]); -const uint8_t can_rxLength = sizeof(can_rxMessages) / sizeof(can_rxMessages[0]); +const uint8_t can_txMessagesLength = sizeof(can_txMessages) / sizeof(can_txMessages[0]); +const uint8_t can_rxMessagesLength = sizeof(can_rxMessages) / sizeof(can_rxMessages[0]); + +CAN_BUFFER_ELEMENT_s dummyMessageBuffer = { + .canNode = CAN_NODE_1, + .id = TEST_CANTX_ID_DUMMY, + .idType = CAN_STANDARD_IDENTIFIER_11_BIT, + .data = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}; + +const uint16_t numberOfRepetitionsToReset = (TEST_CANTX_DUMMY_PERIOD_ms / CAN_TICK_ms) - 1; CAN_STATE_s *canTestState = NULL_PTR; -OS_QUEUE ftsk_dataQueue = NULL_PTR; -OS_QUEUE ftsk_imdCanDataQueue = NULL_PTR; -OS_QUEUE ftsk_canRxQueue = NULL_PTR; -volatile bool ftsk_allQueuesCreated = false; +OS_QUEUE ftsk_dataQueue = NULL_PTR; +OS_QUEUE ftsk_imdCanDataQueue = NULL_PTR; +OS_QUEUE ftsk_canRxQueue = NULL_PTR; +OS_QUEUE ftsk_canTxUnsentMessagesQueue = NULL_PTR; +volatile bool ftsk_allQueuesCreated = false; /*========== Setup and Teardown =============================================*/ void setUp(void) { @@ -284,3 +329,103 @@ void testIsCurrentSensorCcPresent(void) { TEST_ASSERT_EQUAL(true, canTestState->currentSensorCCPresent[s]); } } + +void testCAN_ValidateConfiguredTxMessagePeriod(void) { + TEST_ASSERT_PASS_ASSERT(TEST_CAN_ValidateConfiguredTxMessagePeriod()); +} + +void testCAN_ValidateConfiguredTxMessagePhase(void) { + TEST_ASSERT_PASS_ASSERT(TEST_CAN_ValidateConfiguredTxMessagePhase()); +} + +void testCAN_CheckDatabaseNullPointer(void) { + const CAN_SHIM_s can_shim_corrupted = { + /* corrupted struct example */ + + .pTableCellTemperature = &can_tableTemperatures, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableErrorState = &can_tableErrorState, + .pTableInsulation = &can_tableInsulation, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableMol = &can_tableMolFlags, + .pTableMsl = &can_tableMslFlags, + .pTableOpenWire = &can_tableOpenWire, + .pTablePackValues = &can_tablePackValues, + .pTableRsl = &can_tableRslFlags, + .pTableSoc = &can_tableSoc, + .pTableSoe = &can_tableSoe, + .pTableSof = NULL_PTR, + .pTableSoh = &can_tableSoh, + .pTableStateRequest = &can_tableStateRequest, + }; + + TEST_ASSERT_FAIL_ASSERT(TEST_CAN_CheckDatabaseNullPointer(can_shim_corrupted)); +} + +void testCAN_PeriodicTransmitQueueFull(void) { + /* Assume no messages in queue */ + OS_ReceiveFromQueue_IgnoreAndReturn(OS_FAIL); + + /* assume all message boxes are full */ + canIsTxMessagePending_IgnoreAndReturn(1u); + MATH_MinimumOfTwoUint8_t_IgnoreAndReturn(CAN_MAX_DLC); + + /* expect a message to be sent to queue */ + OS_SendToBackOfQueue_ExpectAndReturn(ftsk_canTxUnsentMessagesQueue, (void *)&dummyMessageBuffer, 0u, OS_FAIL); + /* sending to queue failed, expect error sent to diag */ + DIAG_Handler_ExpectAndReturn(DIAG_ID_CAN_TX_QUEUE_FULL, DIAG_EVENT_NOT_OK, DIAG_SYSTEM, 0u, DIAG_HANDLER_RETURN_OK); + + /* test call */ + TEST_CAN_PeriodicTransmit(); + + /* call repeatedly until phase is zero again */ + for (uint16_t i = 0; i < numberOfRepetitionsToReset; i++) { + TEST_CAN_PeriodicTransmit(); + } +} + +void testCAN_PeriodicTransmitQueueHasSpace(void) { + /* Assume no messages in queue */ + OS_ReceiveFromQueue_IgnoreAndReturn(OS_FAIL); + + /* assume all message boxes are full */ + canIsTxMessagePending_IgnoreAndReturn(1u); + MATH_MinimumOfTwoUint8_t_IgnoreAndReturn(CAN_MAX_DLC); + + /* expect a message to be sent to queue */ + OS_SendToBackOfQueue_ExpectAndReturn(ftsk_canTxUnsentMessagesQueue, (void *)&dummyMessageBuffer, 0u, OS_SUCCESS); + /* sending to queue successful, expect no error */ + DIAG_Handler_ExpectAndReturn(DIAG_ID_CAN_TX_QUEUE_FULL, DIAG_EVENT_OK, DIAG_SYSTEM, 0u, DIAG_HANDLER_RETURN_OK); + + /* test call */ + TEST_CAN_PeriodicTransmit(); + + /* call repeatedly until phase is zero again */ + for (uint16_t i = 0; i < numberOfRepetitionsToReset; i++) { + TEST_CAN_PeriodicTransmit(); + } +} + +void testCAN_IsMessagePeriodElapsed(void) { + /* Invalid messageIndex */ + TEST_ASSERT_FAIL_ASSERT(TEST_CAN_IsMessagePeriodElapsed(0u, UINT16_MAX)); + + /* test case period not elapsed */ + TEST_ASSERT_EQUAL(false, TEST_CAN_IsMessagePeriodElapsed(1u, 0u)); + + /* test case period elapsed */ + TEST_ASSERT_EQUAL(true, TEST_CAN_IsMessagePeriodElapsed(0u, 0u)); +} + +void testCAN_SendMessagesFromQueue(void) { + CAN_BUFFER_ELEMENT_s dummyMessageBufferEmpty = { + .canNode = NULL_PTR, .id = 0u, .idType = CAN_INVALID_TYPE, .data = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}}; + + /** only test the case of failing, because the case of successful call would + * require actual (not mocked) call of OS_ReceiveFromQueue to write to message buffer */ + OS_ReceiveFromQueue_ExpectAndReturn(ftsk_canTxUnsentMessagesQueue, (void *)&dummyMessageBufferEmpty, 0u, OS_FAIL); + + /* test call */ + TEST_ASSERT_PASS_ASSERT(CAN_SendMessagesFromQueue()); +} diff --git a/tests/unit/app/driver/can/test_can_1.c b/tests/unit/app/driver/can/test_can_1.c new file mode 100644 index 00000000..bd96bced --- /dev/null +++ b/tests/unit/app/driver/can/test_can_1.c @@ -0,0 +1,248 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_1.c + * @author foxBMS Team + * @date 2023-03-13 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the configuration validation functions and counter reset calculation in the the CAN driver + * @details This file implements the test of the validation functions for tx message + * configuration with the first invalid configuration of message period + * and phase in dummy message 1. + * Both functions are tested to assert an error with invalid configuration. + * Also the test for the CAN_CalculateCounterResetValue function is + * implemented here. It is tested to calculate the correct value for + * the given dummy messages. + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "MockHL_can.h" +#include "Mockcan_cfg.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockftask.h" +#include "Mockimd.h" +#include "Mockio.h" +#include "Mockmcu.h" +#include "Mockos.h" +#include "Mockpex.h" +#include "Mockqueue.h" +#include "Mocktest_can_mpu_prototype_queue_create_stub.h" + +#include "version_cfg.h" + +#include "can.h" +#include "test_assert_helper.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/* see src/app/driver/config/can_cfg_rx-message-definitions.h, but we omit + this include here */ +#define CANRX_NOT_PERIODIC (0u) + +/* TX test case */ +#define TEST_CANTX_ID_DUMMY (0x001) +#define TEST_CANTX_DUMMY_PERIOD_ms (51u) /* Period must be divisible by CAN Tick */ +#define TEST_CANTX_DUMMY_PHASE_ms (11u) /* Phase must be divisible by CAN Tick */ + +#define TEST_CANTX_DUMMY_MESSAGE \ + { \ + .id = TEST_CANTX_ID_DUMMY, \ + .dlc = CAN_DEFAULT_DLC, \ + .endianness = CAN_LITTLE_ENDIAN, \ + .idType = CAN_STANDARD_IDENTIFIER_11_BIT, \ + }, \ + { \ + .period = TEST_CANTX_DUMMY_PERIOD_ms, .phase = TEST_CANTX_DUMMY_PHASE_ms \ + } + +#define TEST_CANTX_DUMMY_PERIOD_2_ms (30) +#define TEST_CANTX_DUMMY_PHASE_2_ms (0) + +#define TEST_CANTX_DUMMY_MESSAGE_2 \ + { \ + .id = TEST_CANTX_ID_DUMMY, \ + .dlc = CAN_DEFAULT_DLC, \ + .endianness = CAN_LITTLE_ENDIAN, \ + .idType = CAN_STANDARD_IDENTIFIER_11_BIT, \ + }, \ + { \ + .period = TEST_CANTX_DUMMY_PERIOD_2_ms, .phase = TEST_CANTX_DUMMY_PHASE_2_ms \ + } + +#define TEST_CANTX_DUMMY_PERIOD_3_ms (70) +#define TEST_CANTX_DUMMY_PHASE_3_ms (0) + +#define TEST_CANTX_DUMMY_MESSAGE_3 \ + { \ + .id = TEST_CANTX_ID_DUMMY, \ + .dlc = CAN_DEFAULT_DLC, \ + .endianness = CAN_LITTLE_ENDIAN, \ + .idType = CAN_STANDARD_IDENTIFIER_11_BIT, \ + }, \ + { \ + .period = TEST_CANTX_DUMMY_PERIOD_3_ms, .phase = TEST_CANTX_DUMMY_PHASE_3_ms \ + } + +/* Rx test case*/ +#define TEST_CANRX_ID_DUMMY (0x002) + +#define TEST_CANRX_DUMMY_MESSAGE \ + { \ + .id = TEST_CANRX_ID_DUMMY, \ + .dlc = CAN_DEFAULT_DLC, \ + .endianness = CAN_LITTLE_ENDIAN, \ + .idType = CAN_STANDARD_IDENTIFIER_11_BIT, \ + }, \ + { \ + .period = CANRX_NOT_PERIODIC \ + } + +const CAN_NODE_s can_node1 = { + .canNodeRegister = canREG1, +}; + +const CAN_NODE_s can_node2Isolated = { + .canNodeRegister = canREG2, +}; + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, +}; + +static uint32_t TEST_CANTX_DummyCallback( + CAN_MESSAGE_PROPERTIES_s message, + uint8_t *pCanData, + uint8_t *pMuxId, + const CAN_SHIM_s *const kpkCanShim) { + return 0; +} + +static uint32_t TEST_CANRX_DummyCallback( + CAN_MESSAGE_PROPERTIES_s message, + const uint8_t *const kpkCanData, + const CAN_SHIM_s *const kpkCanShim) { + return 0; +} + +const CAN_TX_MESSAGE_TYPE_s can_txMessages[] = { + {CAN_NODE_1, TEST_CANTX_DUMMY_MESSAGE, &TEST_CANTX_DummyCallback, NULL_PTR}, + {CAN_NODE_1, TEST_CANTX_DUMMY_MESSAGE_2, &TEST_CANTX_DummyCallback, NULL_PTR}, + {CAN_NODE_1, TEST_CANTX_DUMMY_MESSAGE_3, &TEST_CANTX_DummyCallback, NULL_PTR}, +}; + +const CAN_RX_MESSAGE_TYPE_s can_rxMessages[] = { + {CAN_NODE_1, TEST_CANRX_DUMMY_MESSAGE, &TEST_CANRX_DummyCallback}, +}; + +const uint8_t can_txMessagesLength = sizeof(can_txMessages) / sizeof(can_txMessages[0]); +const uint8_t can_rxMessagesLength = sizeof(can_rxMessages) / sizeof(can_rxMessages[0]); + +CAN_STATE_s *canTestState = NULL_PTR; + +OS_QUEUE ftsk_dataQueue = NULL_PTR; +OS_QUEUE ftsk_imdCanDataQueue = NULL_PTR; +OS_QUEUE ftsk_canRxQueue = NULL_PTR; +OS_QUEUE ftsk_canTxUnsentMessagesQueue = NULL_PTR; +volatile bool ftsk_allQueuesCreated = false; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +void testCAN_ValidateConfiguredTxMessagePeriod(void) { + TEST_ASSERT_FAIL_ASSERT(TEST_CAN_ValidateConfiguredTxMessagePeriod()); +} + +void testCAN_ValidateConfiguredTxMessagePhase(void) { + TEST_ASSERT_FAIL_ASSERT(TEST_CAN_ValidateConfiguredTxMessagePhase()); +} + +void testCAN_CalculateCounterResetValue(void) { + /* least common multiple of the test message periods is 3570ms, so with a + tick of 10ms the expected counter reset value is 357 */ + TEST_ASSERT_EQUAL(357u, TEST_CAN_CalculateCounterResetValue()); +} diff --git a/tests/unit/app/driver/can/test_can_2.c b/tests/unit/app/driver/can/test_can_2.c new file mode 100644 index 00000000..f3ee85db --- /dev/null +++ b/tests/unit/app/driver/can/test_can_2.c @@ -0,0 +1,209 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_can_2.c + * @author foxBMS Team + * @date 2023-03-13 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the configuration validation functions in the the CAN driver + * @details This file implements the test of the validation functions for tx message + * configuration with the second invalid configuration of message period + * and phase. + * Both functions are tested to assert an error with invalid configuration. + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "MockHL_can.h" +#include "Mockcan_cfg.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfoxmath.h" +#include "Mockftask.h" +#include "Mockimd.h" +#include "Mockio.h" +#include "Mockmcu.h" +#include "Mockos.h" +#include "Mockpex.h" +#include "Mockqueue.h" +#include "Mocktest_can_mpu_prototype_queue_create_stub.h" + +#include "version_cfg.h" + +#include "can.h" +#include "test_assert_helper.h" + +#include +#include + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/* see src/app/driver/config/can_cfg_rx-message-definitions.h, but we omit + this include here */ +#define CANRX_NOT_PERIODIC (0u) + +/* TX test case */ +#define TEST_CANTX_ID_DUMMY (0x001) +#define TEST_CANTX_DUMMY_PERIOD_ms (0u) /* Period must be greater than 0 */ +#define TEST_CANTX_DUMMY_PHASE_ms (10u) /* Phase must be smaller than period */ + +#define TEST_CANTX_DUMMY_MESSAGE \ + { \ + .id = TEST_CANTX_ID_DUMMY, \ + .dlc = CAN_DEFAULT_DLC, \ + .endianness = CAN_LITTLE_ENDIAN, \ + .idType = CAN_STANDARD_IDENTIFIER_11_BIT, \ + }, \ + { \ + .period = TEST_CANTX_DUMMY_PERIOD_ms, .phase = TEST_CANTX_DUMMY_PHASE_ms \ + } + +/* Rx test case*/ +#define TEST_CANRX_ID_DUMMY (0x002) + +#define TEST_CANRX_DUMMY_MESSAGE \ + { \ + .id = TEST_CANRX_ID_DUMMY, \ + .dlc = CAN_DEFAULT_DLC, \ + .endianness = CAN_LITTLE_ENDIAN, \ + .idType = CAN_STANDARD_IDENTIFIER_11_BIT, \ + }, \ + { \ + .period = CANRX_NOT_PERIODIC \ + } + +const CAN_NODE_s can_node1 = { + .canNodeRegister = canREG1, +}; + +const CAN_NODE_s can_node2Isolated = { + .canNodeRegister = canREG2, +}; + +static DATA_BLOCK_CELL_VOLTAGE_s can_tableCellVoltages = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE}; +static DATA_BLOCK_CELL_TEMPERATURE_s can_tableTemperatures = {.header.uniqueId = DATA_BLOCK_ID_CELL_TEMPERATURE}; +static DATA_BLOCK_MIN_MAX_s can_tableMinimumMaximumValues = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX}; +static DATA_BLOCK_CURRENT_SENSOR_s can_tableCurrentSensor = {.header.uniqueId = DATA_BLOCK_ID_CURRENT_SENSOR}; +static DATA_BLOCK_OPEN_WIRE_s can_tableOpenWire = {.header.uniqueId = DATA_BLOCK_ID_OPEN_WIRE_BASE}; +static DATA_BLOCK_STATE_REQUEST_s can_tableStateRequest = {.header.uniqueId = DATA_BLOCK_ID_STATE_REQUEST}; + +OS_QUEUE imd_canDataQueue = NULL_PTR; + +const CAN_SHIM_s can_kShim = { + .pQueueImd = &imd_canDataQueue, + .pTableCellVoltage = &can_tableCellVoltages, + .pTableCellTemperature = &can_tableTemperatures, + .pTableMinMax = &can_tableMinimumMaximumValues, + .pTableCurrentSensor = &can_tableCurrentSensor, + .pTableOpenWire = &can_tableOpenWire, + .pTableStateRequest = &can_tableStateRequest, +}; + +static uint32_t TEST_CANTX_DummyCallback( + CAN_MESSAGE_PROPERTIES_s message, + uint8_t *pCanData, + uint8_t *pMuxId, + const CAN_SHIM_s *const kpkCanShim) { + return 0; +} + +static uint32_t TEST_CANRX_DummyCallback( + CAN_MESSAGE_PROPERTIES_s message, + const uint8_t *const kpkCanData, + const CAN_SHIM_s *const kpkCanShim) { + return 0; +} + +const CAN_TX_MESSAGE_TYPE_s can_txMessages[] = { + {CAN_NODE_1, TEST_CANTX_DUMMY_MESSAGE, &TEST_CANTX_DummyCallback, NULL_PTR}, +}; + +const CAN_RX_MESSAGE_TYPE_s can_rxMessages[] = { + {CAN_NODE_1, TEST_CANRX_DUMMY_MESSAGE, &TEST_CANRX_DummyCallback}, +}; + +const uint8_t can_txMessagesLength = sizeof(can_txMessages) / sizeof(can_txMessages[0]); +const uint8_t can_rxMessagesLength = sizeof(can_rxMessages) / sizeof(can_rxMessages[0]); + +CAN_STATE_s *canTestState = NULL_PTR; + +OS_QUEUE ftsk_dataQueue = NULL_PTR; +OS_QUEUE ftsk_imdCanDataQueue = NULL_PTR; +OS_QUEUE ftsk_canRxQueue = NULL_PTR; +OS_QUEUE ftsk_canTxUnsentMessagesQueue = NULL_PTR; +volatile bool ftsk_allQueuesCreated = false; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ + +void testCAN_ValidateConfiguredTxMessagePeriod(void) { + TEST_ASSERT_FAIL_ASSERT(TEST_CAN_ValidateConfiguredTxMessagePeriod()); +} + +void testCAN_ValidateConfiguredTxMessagePhase(void) { + TEST_ASSERT_FAIL_ASSERT(TEST_CAN_ValidateConfiguredTxMessagePhase()); +} diff --git a/tests/unit/app/driver/checksum/test_checksum.c b/tests/unit/app/driver/checksum/test_checksum.c index 1b604c9f..df14837b 100644 --- a/tests/unit/app/driver/checksum/test_checksum.c +++ b/tests/unit/app/driver/checksum/test_checksum.c @@ -43,8 +43,8 @@ * @file test_checksum.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,9 @@ #include "checksum.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/checksum") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/config/test_can_cfg.c b/tests/unit/app/driver/config/test_can_cfg.c index e75c61ae..1b9e81fb 100644 --- a/tests/unit/app/driver/config/test_can_cfg.c +++ b/tests/unit/app/driver/config/test_can_cfg.c @@ -43,8 +43,8 @@ * @file test_can_cfg.c * @author foxBMS Team * @date 2020-07-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -68,6 +68,16 @@ #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + /*========== Definitions and Implementations for Unit Test ==================*/ OS_QUEUE ftsk_dataQueue = NULL_PTR; diff --git a/tests/unit/app/driver/config/test_can_cfg_rx.c b/tests/unit/app/driver/config/test_can_cfg_rx.c index 0694bc62..783f4dc6 100644 --- a/tests/unit/app/driver/config/test_can_cfg_rx.c +++ b/tests/unit/app/driver/config/test_can_cfg_rx.c @@ -43,8 +43,8 @@ * @file test_can_cfg_rx.c * @author foxBMS Team * @date 2020-07-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -69,7 +69,18 @@ #include -TEST_FILE("can_cfg_rx.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cfg_rx.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/rx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/config/test_can_cfg_tx.c b/tests/unit/app/driver/config/test_can_cfg_tx.c index 19453a6f..9f22b450 100644 --- a/tests/unit/app/driver/config/test_can_cfg_tx.c +++ b/tests/unit/app/driver/config/test_can_cfg_tx.c @@ -43,8 +43,8 @@ * @file test_can_cfg_tx.c * @author foxBMS Team * @date 2020-07-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -69,7 +69,18 @@ #include -TEST_FILE("can_cfg_tx.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("can_cfg_tx.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/config/test_contactor_cfg.c b/tests/unit/app/driver/config/test_contactor_cfg.c index e883c1fe..f49a5d9e 100644 --- a/tests/unit/app/driver/config/test_contactor_cfg.c +++ b/tests/unit/app/driver/config/test_contactor_cfg.c @@ -43,8 +43,8 @@ * @file test_contactor_cfg.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,10 @@ #include "contactor_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/sps") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/config/test_dma_cfg.c b/tests/unit/app/driver/config/test_dma_cfg.c index d8c99152..afcea5c9 100644 --- a/tests/unit/app/driver/config/test_dma_cfg.c +++ b/tests/unit/app/driver/config/test_dma_cfg.c @@ -43,8 +43,8 @@ * @file test_dma_cfg.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,10 @@ #include "dma_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/config/test_fram_cfg.c b/tests/unit/app/driver/config/test_fram_cfg.c index 20939da3..147cb4ae 100644 --- a/tests/unit/app/driver/config/test_fram_cfg.c +++ b/tests/unit/app/driver/config/test_fram_cfg.c @@ -43,8 +43,8 @@ * @file test_fram_cfg.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,9 @@ #include "fram_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/config/test_interlock_cfg.c b/tests/unit/app/driver/config/test_interlock_cfg.c deleted file mode 100644 index b7179be5..00000000 --- a/tests/unit/app/driver/config/test_interlock_cfg.c +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_interlock_cfg.c - * @author foxBMS Team - * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Tests for the interlock_cfg module - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" - -#include "interlock_cfg.h" - -/*========== Definitions and Implementations for Unit Test ==================*/ - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -/*========== Test Cases =====================================================*/ - -void testDummy(void) { -} diff --git a/tests/unit/app/driver/config/test_nxpfs85xx_cfg.c b/tests/unit/app/driver/config/test_nxpfs85xx_cfg.c deleted file mode 100644 index 86690a59..00000000 --- a/tests/unit/app/driver/config/test_nxpfs85xx_cfg.c +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_nxpfs85xx_cfg.c - * @author foxBMS Team - * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Tests for the CAN driver - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" - -#include "nxpfs85xx_cfg.h" - -/*========== Definitions and Implementations for Unit Test ==================*/ - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -/*========== Test Cases =====================================================*/ - -void testDummy(void) { -} diff --git a/tests/unit/app/driver/config/test_pex_cfg.c b/tests/unit/app/driver/config/test_pex_cfg.c index b2716141..80a10188 100644 --- a/tests/unit/app/driver/config/test_pex_cfg.c +++ b/tests/unit/app/driver/config/test_pex_cfg.c @@ -43,8 +43,8 @@ * @file test_pex_cfg.c * @author foxBMS Team * @date 2021-08-03 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,9 @@ #include "pex_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/config/test_spi_cfg.c b/tests/unit/app/driver/config/test_spi_cfg.c index 24891f29..2709e2e9 100644 --- a/tests/unit/app/driver/config/test_spi_cfg.c +++ b/tests/unit/app/driver/config/test_spi_cfg.c @@ -43,8 +43,8 @@ * @file test_spi_cfg.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,6 +59,10 @@ #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/spi") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/config/test_sps_cfg.c b/tests/unit/app/driver/config/test_sps_cfg.c index 5bfac93a..35684406 100644 --- a/tests/unit/app/driver/config/test_sps_cfg.c +++ b/tests/unit/app/driver/config/test_sps_cfg.c @@ -43,8 +43,8 @@ * @file test_sps_cfg.c * @author foxBMS Team * @date 2020-10-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,10 @@ #include "sps_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/sps") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/contactor/test_contactor.c b/tests/unit/app/driver/contactor/test_contactor.c index aeb2241c..f3ffc261 100644 --- a/tests/unit/app/driver/contactor/test_contactor.c +++ b/tests/unit/app/driver/contactor/test_contactor.c @@ -43,8 +43,8 @@ * @file test_contactor.c * @author foxBMS Team * @date 2020-03-31 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -65,6 +65,13 @@ #include "contactor.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") + /*========== Definitions and Implementations for Unit Test ==================*/ BS_STRING_PRECHARGE_PRESENT_e bs_stringsWithPrecharge[BS_NR_OF_STRINGS] = { BS_STRING_WITH_PRECHARGE, diff --git a/tests/unit/app/driver/crc/test_crc.c b/tests/unit/app/driver/crc/test_crc.c index e41a78a9..bbe577da 100644 --- a/tests/unit/app/driver/crc/test_crc.c +++ b/tests/unit/app/driver/crc/test_crc.c @@ -43,8 +43,8 @@ * @file test_crc.c * @author foxBMS Team * @date 2022-02-23 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,6 +58,9 @@ #include "crc.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/crc") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/dma/test_dma.c b/tests/unit/app/driver/dma/test_dma.c index d26f31c5..de609634 100644 --- a/tests/unit/app/driver/dma/test_dma.c +++ b/tests/unit/app/driver/dma/test_dma.c @@ -43,8 +43,8 @@ * @file test_dma.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -65,19 +65,22 @@ #include "dma.h" -TEST_FILE("dma.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("dma.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/i2c") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ TaskHandle_t ftsk_taskHandleI2c; -static const spiDAT1_t spi_kLtcDataConfig = { - /* struct is implemented in the TI HAL and uses uppercase true and false */ - .CS_HOLD = FALSE, /* The HW chip select signal is deactivated */ - .WDEL = TRUE, /* No delay will be inserted */ - .DFSEL = SPI_FMT_0, /* Data word format select: Data format 0 (SPI1) */ - .CSNR = 0x0, /* Chip select (CS) number, 0x01h for CS[0] */ -}; - uint32_t spi_saveFmt0[] = { 0U, 0U, diff --git a/tests/unit/app/driver/foxmath/test_foxmath.c b/tests/unit/app/driver/foxmath/test_foxmath.c index 50917335..682b16b5 100644 --- a/tests/unit/app/driver/foxmath/test_foxmath.c +++ b/tests/unit/app/driver/foxmath/test_foxmath.c @@ -43,8 +43,8 @@ * @file test_foxmath.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,9 @@ #include "foxmath.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") + /*========== Definitions and Implementations for Unit Test ==================*/ uint16_t val16; uint32_t val32; @@ -83,18 +86,18 @@ void tearDown(void) { } /*========== Test Cases =====================================================*/ -void test_linearInterpolation_X1EqualsX2() { +void test_linearInterpolation_X1EqualsX2(void) { coord_x1 = coord_x2; TEST_ASSERT_EQUAL(coord_y1, MATH_LinearInterpolation(coord_x1, coord_y1, coord_x2, coord_y2, coord_x_interpolate)); } -void test_linearInterpolation_interpolateBetweenX1AndX2() { +void test_linearInterpolation_interpolateBetweenX1AndX2(void) { TEST_ASSERT_EQUAL(75.0f, MATH_LinearInterpolation(10.f, 50.f, 20.f, 100.f, 15.f)); TEST_ASSERT_EQUAL(87.0f, MATH_LinearInterpolation(10.f, 50.f, 20.f, 100.f, 17.5f)); TEST_ASSERT_EQUAL(50.0f, MATH_LinearInterpolation(10.f, 50.f, 20.f, 100.f, 10.0001f)); } -void test_linearInterpolation_extrapolateFromX1AndX2() { +void test_linearInterpolation_extrapolateFromX1AndX2(void) { TEST_ASSERT_EQUAL(100.0f, MATH_LinearInterpolation(10.f, 50.f, 20.f, 100.f, 20.1f)); TEST_ASSERT_EQUAL(-100.0f, MATH_LinearInterpolation(10.f, 50.f, 20.f, 100.f, -20.f)); TEST_ASSERT_EQUAL(16739465.0f, MATH_LinearInterpolation(10.f, 50.f, 20.f, 100.f, 3347893.0f)); diff --git a/tests/unit/app/driver/fram/test_fram.c b/tests/unit/app/driver/fram/test_fram.c index d9f37d5c..8c14f7ac 100644 --- a/tests/unit/app/driver/fram/test_fram.c +++ b/tests/unit/app/driver/fram/test_fram.c @@ -43,8 +43,8 @@ * @file test_fram.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -70,6 +70,14 @@ #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/crc") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/engine/diag") + /*========== Definitions and Implementations for Unit Test ==================*/ const VER_VERSION_s ver_foxbmsVersionInformation VER_VERSION_INFORMATION = { .underVersionControl = true, diff --git a/tests/unit/app/driver/htsensor/test_htsensor.c b/tests/unit/app/driver/htsensor/test_htsensor.c index f111e9c0..7f9ed50a 100644 --- a/tests/unit/app/driver/htsensor/test_htsensor.c +++ b/tests/unit/app/driver/htsensor/test_htsensor.c @@ -43,8 +43,8 @@ * @file test_htsensor.c * @author foxBMS Team * @date 2021-08-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,6 +62,10 @@ #include "htsensor.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/htsensor") +TEST_INCLUDE_PATH("../../src/app/driver/i2c") + /*========== Definitions and Implementations for Unit Test ==================*/ long FSYS_RaisePrivilege(void) { diff --git a/tests/unit/app/driver/i2c/test_i2c.c b/tests/unit/app/driver/i2c/test_i2c.c index 69b9807d..58022141 100644 --- a/tests/unit/app/driver/i2c/test_i2c.c +++ b/tests/unit/app/driver/i2c/test_i2c.c @@ -43,8 +43,8 @@ * @file test_i2c.c * @author foxBMS Team * @date 2021-07-23 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,6 +62,12 @@ #include "i2c.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/i2c") +TEST_INCLUDE_PATH("../../src/app/engine/diag") + /*========== Definitions and Implementations for Unit Test ==================*/ long FSYS_RaisePrivilege(void) { diff --git a/tests/unit/app/driver/imd/bender/ir155/test_bender_ir155.c b/tests/unit/app/driver/imd/bender/ir155/test_bender_ir155.c index 91b8f279..6d4cce87 100644 --- a/tests/unit/app/driver/imd/bender/ir155/test_bender_ir155.c +++ b/tests/unit/app/driver/imd/bender/ir155/test_bender_ir155.c @@ -43,8 +43,8 @@ * @file test_bender_ir155.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -54,8 +54,45 @@ /*========== Includes =======================================================*/ #include "unity.h" +#include "Mockbender_ir155_helper.h" +#include "Mockdatabase.h" +#include "Mockdiag.h" +#include "Mockfram.h" +#include "Mockio.h" +#include "Mockos.h" + +#include "bender_ir155_cfg.h" + +#include "bender_ir155.h" +#include "imd.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/imd/bender/ir155") +TEST_INCLUDE_PATH("../../src/app/driver/imd/bender/ir155/config") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pwm") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ +IR155_STATE_s ir155_state = { + .ir155Initialized = false, + .measurement.isMeasurementValid = false, + .measurement.isUndervoltageDetected = false, + .measurement.measurementState = IR155_UNINITIALIZED, + .measurement.measurementMode = IR155_UNKNOWN, + .measurement.digitalStatusPin = STD_PIN_LOW, + .measurement.resistance_kOhm = 0, + .measurement.pwmSignal.dutyCycle_perc = 0.0f, + .measurement.pwmSignal.frequency_Hz = 0.0f, + .periodTriggerTime_ms = IMD_PERIODIC_CALL_TIME_ms, +}; + +FRAM_INSULATION_FLAG_s fram_insulationFlags = {.groundErrorDetected = false}; /*========== Setup and Teardown =============================================*/ void setUp(void) { @@ -65,5 +102,16 @@ void tearDown(void) { } /*========== Test Cases =====================================================*/ -void testNoTestsAvailable(void) { +void testIMD_ProcessInitializationState(void) { + IR155_Initialize_Expect(IMD_PERIODIC_CALL_TIME_ms); + TEST_ASSERT_EQUAL(IMD_FSM_STATE_IMD_ENABLE, IMD_ProcessInitializationState()); +} +void test_IMD_ProcessEnableState(void) { + IO_PinSet_Expect(&IR155_SUPPLY_ENABLE_PORT->DOUT, IR155_SUPPLY_ENABLE_PIN); + TEST_ASSERT_EQUAL(IMD_FSM_STATE_RUNNING, IMD_ProcessEnableState()); +} + +void test_IMD_ProcessShutdownState(void) { + IO_PinReset_Expect(&IR155_SUPPLY_ENABLE_PORT->DOUT, IR155_SUPPLY_ENABLE_PIN); + TEST_ASSERT_EQUAL(IMD_FSM_STATE_IMD_ENABLE, IMD_ProcessShutdownState()); } diff --git a/tests/unit/app/driver/imd/bender/ir155/test_bender_ir155_helper.c b/tests/unit/app/driver/imd/bender/ir155/test_bender_ir155_helper.c index 597d6272..d0019458 100644 --- a/tests/unit/app/driver/imd/bender/ir155/test_bender_ir155_helper.c +++ b/tests/unit/app/driver/imd/bender/ir155/test_bender_ir155_helper.c @@ -43,8 +43,8 @@ * @file test_bender_ir155_helper.c * @author foxBMS Team * @date 2020-11-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -60,6 +60,17 @@ #include "bender_ir155_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/imd/bender/ir155") +TEST_INCLUDE_PATH("../../src/app/driver/imd/bender/ir155/config") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pwm") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + /*========== Definitions and Implementations for Unit Test ==================*/ FRAM_INSULATION_FLAG_s fram_insulationFlags; diff --git a/tests/unit/app/driver/imd/bender/iso165c/config/test_bender_iso165c_cfg.c b/tests/unit/app/driver/imd/bender/iso165c/config/test_bender_iso165c_cfg.c deleted file mode 100644 index 3288a7bc..00000000 --- a/tests/unit/app/driver/imd/bender/iso165c/config/test_bender_iso165c_cfg.c +++ /dev/null @@ -1,71 +0,0 @@ -/** - * - * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * We kindly request you to use one or more of the following phrases to refer to - * foxBMS in your hardware, software, documentation or advertising materials: - * - * - ″This product uses parts of foxBMS®″ - * - ″This product includes parts of foxBMS®″ - * - ″This product is derived from foxBMS®″ - * - */ - -/** - * @file test_bender_iso165c_cfg.c - * @author foxBMS Team - * @date 2021-03-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup UNIT_TEST_IMPLEMENTATION - * @prefix TEST - * - * @brief Test of Bender iso165c module - * - */ - -/*========== Includes =======================================================*/ -#include "unity.h" - -#include "bender_iso165c_cfg.h" - -/*========== Definitions and Implementations for Unit Test ==================*/ - -/*========== Setup and Teardown =============================================*/ -void setUp(void) { -} - -void tearDown(void) { -} - -/*========== Test Cases =====================================================*/ -void testDummy(void) { -} diff --git a/tests/unit/app/driver/imd/bender/iso165c/test_bender_iso165c.c b/tests/unit/app/driver/imd/bender/iso165c/test_bender_iso165c.c index 2d7d6daa..bdf7a7f1 100644 --- a/tests/unit/app/driver/imd/bender/iso165c/test_bender_iso165c.c +++ b/tests/unit/app/driver/imd/bender/iso165c/test_bender_iso165c.c @@ -43,8 +43,8 @@ * @file test_bender_iso165c.c * @author foxBMS Team * @date 2021-01-19 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -70,6 +70,19 @@ #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/imd/bender/iso165c") +TEST_INCLUDE_PATH("../../src/app/driver/imd/bender/iso165c/config") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + /*========== Definitions and Implementations for Unit Test ==================*/ OS_QUEUE ftsk_dataQueue = NULL_PTR; diff --git a/tests/unit/app/driver/imd/none/test_no-imd.c b/tests/unit/app/driver/imd/none/test_no-imd.c index 1e72d388..ba6ae454 100644 --- a/tests/unit/app/driver/imd/none/test_no-imd.c +++ b/tests/unit/app/driver/imd/none/test_no-imd.c @@ -43,8 +43,8 @@ * @file test_no-imd.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,6 +61,13 @@ #include "no-imd.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/imd/none") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/imd/test_imd.c b/tests/unit/app/driver/imd/test_imd.c index df2683e6..38be092f 100644 --- a/tests/unit/app/driver/imd/test_imd.c +++ b/tests/unit/app/driver/imd/test_imd.c @@ -43,8 +43,8 @@ * @file test_imd.c * @author foxBMS Team * @date 2021-11-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,6 +61,14 @@ #include "imd.h" #include "no-imd.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/imd/none") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/interlock/test_interlock.c b/tests/unit/app/driver/interlock/test_interlock.c index 045c63f4..ab4da6c3 100644 --- a/tests/unit/app/driver/interlock/test_interlock.c +++ b/tests/unit/app/driver/interlock/test_interlock.c @@ -43,8 +43,8 @@ * @file test_interlock.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -66,6 +66,12 @@ #include "interlock.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/interlock") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/engine/diag") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ @@ -118,7 +124,7 @@ void testILCK_SetStateRequestIllegalValue(void) { } void testILCK_SetStateRequestDoubleInitializationWithoutStatemachine(void) { - /* run initialization twice, but statemachine not in between */ + /* run initialization twice, but state machine not in between */ IO_SetPinDirectionToOutput_Ignore(); IO_SetPinDirectionToInput_Ignore(); IO_PinReset_Ignore(); @@ -131,7 +137,7 @@ void testILCK_SetStateRequestDoubleInitializationWithoutStatemachine(void) { } void testILCK_SetStateRequestDoubleInitialization(void) { - /* run initialization twice and call statemachine between these requests */ + /* run initialization twice and call state machine between these requests */ OS_EnterTaskCritical_Expect(); OS_ExitTaskCritical_Expect(); @@ -175,7 +181,7 @@ void testRunStatemachineWithoutRequest(void) { void testInitializeStatemachine(void) { /* run initialization */ - /* since we are checking only for the statemachine passing through these + /* since we are checking only for the state machine passing through these states, we ignore all unnecessary functions */ OS_EnterTaskCritical_Ignore(); @@ -194,7 +200,7 @@ void testInitializeStatemachine(void) { DIAG_Handler_IgnoreAndReturn(DIAG_HANDLER_RETURN_OK); for (uint8_t i = 0u; i < 10; i++) { - /* iterate calling this statemachine 10 times (one shorttime) */ + /* iterate calling this state machine 10 times (one shorttime) */ ILCK_Trigger(); } diff --git a/tests/unit/app/driver/io/test_io.c b/tests/unit/app/driver/io/test_io.c index 231a8be9..6c99e944 100644 --- a/tests/unit/app/driver/io/test_io.c +++ b/tests/unit/app/driver/io/test_io.c @@ -43,8 +43,8 @@ * @file test_io.c * @author foxBMS Team * @date 2020-06-10 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "io.h" #include "test_assert_helper.h" -TEST_FILE("io.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("io.c") + +TEST_INCLUDE_PATH("../../src/app/driver/io") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/led/test_led.c b/tests/unit/app/driver/led/test_led.c index 36d26b4e..b5d90b4a 100644 --- a/tests/unit/app/driver/led/test_led.c +++ b/tests/unit/app/driver/led/test_led.c @@ -43,8 +43,8 @@ * @file test_led.c * @author foxBMS Team * @date 2020-10-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -60,7 +60,12 @@ #include "led.h" #include "test_assert_helper.h" -TEST_FILE("led.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("led.c") + +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/led") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/mcu/test_mcu.c b/tests/unit/app/driver/mcu/test_mcu.c index 294ffc53..6a2627ed 100644 --- a/tests/unit/app/driver/mcu/test_mcu.c +++ b/tests/unit/app/driver/mcu/test_mcu.c @@ -43,8 +43,8 @@ * @file test_mcu.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,8 @@ #include "mcu.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ volatile uint32_t MCU_RTI_CNT0_FRC0_REG = 0u; diff --git a/tests/unit/app/driver/meas/test_meas.c b/tests/unit/app/driver/meas/test_meas.c index c8a7246a..7da99587 100644 --- a/tests/unit/app/driver/meas/test_meas.c +++ b/tests/unit/app/driver/meas/test_meas.c @@ -43,8 +43,8 @@ * @file test_meas.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -55,10 +55,13 @@ /*========== Includes =======================================================*/ #include "unity.h" #include "Mockafe.h" -#include "Mockltc.h" #include "meas.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/meas") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/pex/test_pex.c b/tests/unit/app/driver/pex/test_pex.c index 8bfa9a30..3b7154a9 100644 --- a/tests/unit/app/driver/pex/test_pex.c +++ b/tests/unit/app/driver/pex/test_pex.c @@ -43,8 +43,8 @@ * @file test_pex.c * @author foxBMS Team * @date 2021-09-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -66,6 +66,12 @@ #include "pex.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/i2c") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/engine/diag") + /*========== Definitions and Implementations for Unit Test ==================*/ long FSYS_RaisePrivilege(void) { diff --git a/tests/unit/app/driver/pwm/test_pwm.c b/tests/unit/app/driver/pwm/test_pwm.c index 76eded6a..f691d0ec 100644 --- a/tests/unit/app/driver/pwm/test_pwm.c +++ b/tests/unit/app/driver/pwm/test_pwm.c @@ -43,8 +43,8 @@ * @file test_pwm.c * @author foxBMS Team * @date 2021-10-08 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -66,13 +66,19 @@ #include "pwm.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/pwm") + /*========== Definitions and Implementations for Unit Test ==================*/ static uint8_t fsysRaisePrivilegeReturnValue = 0u; long FSYS_RaisePrivilege(void) { return fsysRaisePrivilegeReturnValue; } -void ecapInit(void){}; +void ecapInit(void) { + /* dummy implementation required for linking */ +} uint32_t ecapGetCAP1(ecapBASE_t *ecap) { return ecap->CAP1; diff --git a/tests/unit/app/driver/rtc/test_rtc.c b/tests/unit/app/driver/rtc/test_rtc.c index 20ac72f4..40355977 100644 --- a/tests/unit/app/driver/rtc/test_rtc.c +++ b/tests/unit/app/driver/rtc/test_rtc.c @@ -43,8 +43,8 @@ * @file test_rtc.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,7 +61,16 @@ #include "Mocki2c.h" #include "Mockos.h" -TEST_FILE("rtc.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("rtc.c") + +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/i2c") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -76,5 +85,5 @@ void tearDown(void) { /*========== Test Cases =====================================================*/ -void testDummyFunction() { +void testDummyFunction(void) { } diff --git a/tests/unit/app/driver/sbc/test_nxpfs85xx.c b/tests/unit/app/driver/sbc/test_nxpfs85xx.c index 8ad0694d..9ff2893a 100644 --- a/tests/unit/app/driver/sbc/test_nxpfs85xx.c +++ b/tests/unit/app/driver/sbc/test_nxpfs85xx.c @@ -43,8 +43,8 @@ * @file test_nxpfs85xx.c * @author foxBMS Team * @date 2020-04-06 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix SBC * @@ -59,7 +59,7 @@ #include "Mockfassert.h" #include "Mockfram.h" #include "Mockio.h" -#include "Mockmasterinfo.h" +#include "Mockmaster_info.h" #include "Mockmcu.h" #include "Mocksbc_fs8x.h" #include "Mocksbc_fs8x_communication.h" @@ -70,7 +70,18 @@ #include -TEST_FILE("nxpfs85xx.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("nxpfs85xx.c") + +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/sbc") +TEST_INCLUDE_PATH("../../src/app/driver/sbc/fs8x_driver") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/hw_info") /*========== Definitions and Implementations for Unit Test ==================*/ #define REGISTER_TEST_VALUE (1234u) @@ -78,7 +89,7 @@ TEST_FILE("nxpfs85xx.c") #define MAIN_REGISTER fs85xx_mcuSupervisor.mainRegister #define FAILSAFE_REGISTER fs85xx_mcuSupervisor.fsRegister -static const spiDAT1_t spi_kSbcDataConfig = { +static spiDAT1_t spi_kSbcDataConfig = { /* struct is implemented in the TI HAL and uses uppercase true and false */ .CS_HOLD = FALSE, /* The HW chip select signal is deactivated */ .WDEL = TRUE, /* No delay will be inserted */ @@ -114,50 +125,52 @@ void tearDown(void) { void testDoSomething(void) { } -void testSBC_CheckRegisterValues(void) { - TEST_ASSERT_EQUAL(STD_OK, TEST_SBC_CheckRegisterValues(0u, 0u)); - TEST_ASSERT_EQUAL(STD_OK, TEST_SBC_CheckRegisterValues(UINT32_MAX, UINT32_MAX)); - TEST_ASSERT_EQUAL(STD_NOT_OK, TEST_SBC_CheckRegisterValues(0u, 1u)); - TEST_ASSERT_EQUAL(STD_NOT_OK, TEST_SBC_CheckRegisterValues(0u, UINT32_MAX)); +void testFS85_CheckRegisterValues(void) { + TEST_ASSERT_EQUAL(STD_OK, TEST_FS85_CheckRegisterValues(0u, 0u)); + TEST_ASSERT_EQUAL(STD_OK, TEST_FS85_CheckRegisterValues(UINT32_MAX, UINT32_MAX)); + TEST_ASSERT_EQUAL(STD_NOT_OK, TEST_FS85_CheckRegisterValues(0u, 1u)); + TEST_ASSERT_EQUAL(STD_NOT_OK, TEST_FS85_CheckRegisterValues(0u, UINT32_MAX)); } -void testSBC_UpdateRegister(void) { - TEST_SBC_UpdateRegister(&fs85xx_mcuSupervisor, true, 0u, REGISTER_TEST_VALUE); - TEST_SBC_UpdateRegister(&fs85xx_mcuSupervisor, false, 0u, REGISTER_TEST_VALUE); - TEST_ASSERT_FAIL_ASSERT(TEST_SBC_UpdateRegister(NULL_PTR, true, 0u, REGISTER_TEST_VALUE)); +void testFS85_UpdateRegister(void) { + TEST_FS85_UpdateRegister(&fs85xx_mcuSupervisor, true, 0u, REGISTER_TEST_VALUE); + TEST_FS85_UpdateRegister(&fs85xx_mcuSupervisor, false, 0u, REGISTER_TEST_VALUE); + TEST_ASSERT_FAIL_ASSERT(TEST_FS85_UpdateRegister(NULL_PTR, true, 0u, REGISTER_TEST_VALUE)); TEST_ASSERT_FAIL_ASSERT( - TEST_SBC_UpdateRegister(&fs85xx_mcuSupervisor, true, FS8X_M_DEVICEID_ADDR + 1u, REGISTER_TEST_VALUE)); + TEST_FS85_UpdateRegister(&fs85xx_mcuSupervisor, true, FS8X_M_DEVICEID_ADDR + 1u, REGISTER_TEST_VALUE)); } -void testSBC_UpdateFailSafeRegister(void) { - TEST_SBC_UpdateFailSafeRegister( +void testFS85_UpdateFailSafeRegister(void) { + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_GRL_FLAGS_ADDR, REGISTER_TEST_VALUE + 0u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_I_OVUV_SAFE_REACTION1_ADDR, REGISTER_TEST_VALUE + 1u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_I_OVUV_SAFE_REACTION2_ADDR, REGISTER_TEST_VALUE + 2u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_I_WD_CFG_ADDR, REGISTER_TEST_VALUE + 3u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_I_SAFE_INPUTS_ADDR, REGISTER_TEST_VALUE + 4u); - TEST_SBC_UpdateFailSafeRegister(&(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_I_FSSM_ADDR, REGISTER_TEST_VALUE + 5u); - TEST_SBC_UpdateFailSafeRegister(&(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_I_SVS_ADDR, REGISTER_TEST_VALUE + 6u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister(&(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_I_FSSM_ADDR, REGISTER_TEST_VALUE + 5u); + TEST_FS85_UpdateFailSafeRegister(&(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_I_SVS_ADDR, REGISTER_TEST_VALUE + 6u); + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_WD_WINDOW_ADDR, REGISTER_TEST_VALUE + 7u); - TEST_SBC_UpdateFailSafeRegister(&(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_WD_SEED_ADDR, REGISTER_TEST_VALUE + 8u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( + &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_WD_SEED_ADDR, REGISTER_TEST_VALUE + 8u); + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_WD_ANSWER_ADDR, REGISTER_TEST_VALUE + 9u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_OVUVREG_STATUS_ADDR, REGISTER_TEST_VALUE + 10u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_RELEASE_FS0B_ADDR, REGISTER_TEST_VALUE + 11u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_SAFE_IOS_ADDR, REGISTER_TEST_VALUE + 12u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_DIAG_SAFETY_ADDR, REGISTER_TEST_VALUE + 13u); - TEST_SBC_UpdateFailSafeRegister( + TEST_FS85_UpdateFailSafeRegister( &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_INTB_MASK_ADDR, REGISTER_TEST_VALUE + 14u); - TEST_SBC_UpdateFailSafeRegister(&(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_STATES_ADDR, REGISTER_TEST_VALUE + 15u); + TEST_FS85_UpdateFailSafeRegister( + &(fs85xx_mcuSupervisor.fsRegister), FS8X_FS_STATES_ADDR, REGISTER_TEST_VALUE + 15u); TEST_ASSERT_EQUAL(FAILSAFE_REGISTER.grl_flags, REGISTER_TEST_VALUE + 0u); TEST_ASSERT_EQUAL(FAILSAFE_REGISTER.iOvervoltageUndervoltageSafeReaction1, REGISTER_TEST_VALUE + 1u); @@ -177,22 +190,23 @@ void testSBC_UpdateFailSafeRegister(void) { TEST_ASSERT_EQUAL(FAILSAFE_REGISTER.states, REGISTER_TEST_VALUE + 15u); } -void testSBC_UpdateMainRegister(void) { - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_FLAG_ADDR, REGISTER_TEST_VALUE + 0u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_MODE_ADDR, REGISTER_TEST_VALUE + 1u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_REG_CTRL1_ADDR, REGISTER_TEST_VALUE + 2u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_REG_CTRL2_ADDR, REGISTER_TEST_VALUE + 3u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_AMUX_ADDR, REGISTER_TEST_VALUE + 4u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_CLOCK_ADDR, REGISTER_TEST_VALUE + 5u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_INT_MASK1_ADDR, REGISTER_TEST_VALUE + 6u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_INT_MASK2_ADDR, REGISTER_TEST_VALUE + 7u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_FLAG1_ADDR, REGISTER_TEST_VALUE + 8u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_FLAG2_ADDR, REGISTER_TEST_VALUE + 9u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_VMON_REGX_ADDR, REGISTER_TEST_VALUE + 10u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_LVB1_SVS_ADDR, REGISTER_TEST_VALUE + 11u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_MEMORY0_ADDR, REGISTER_TEST_VALUE + 12u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_MEMORY1_ADDR, REGISTER_TEST_VALUE + 13u); - TEST_SBC_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_DEVICEID_ADDR, REGISTER_TEST_VALUE + 14u); +void testFS85_UpdateMainRegister(void) { + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_FLAG_ADDR, REGISTER_TEST_VALUE + 0u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_MODE_ADDR, REGISTER_TEST_VALUE + 1u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_REG_CTRL1_ADDR, REGISTER_TEST_VALUE + 2u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_REG_CTRL2_ADDR, REGISTER_TEST_VALUE + 3u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_AMUX_ADDR, REGISTER_TEST_VALUE + 4u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_CLOCK_ADDR, REGISTER_TEST_VALUE + 5u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_INT_MASK1_ADDR, REGISTER_TEST_VALUE + 6u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_INT_MASK2_ADDR, REGISTER_TEST_VALUE + 7u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_FLAG1_ADDR, REGISTER_TEST_VALUE + 8u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_FLAG2_ADDR, REGISTER_TEST_VALUE + 9u); + TEST_FS85_UpdateMainRegister( + &(fs85xx_mcuSupervisor.mainRegister), FS8X_M_VMON_REGX_ADDR, REGISTER_TEST_VALUE + 10u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_LVB1_SVS_ADDR, REGISTER_TEST_VALUE + 11u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_MEMORY0_ADDR, REGISTER_TEST_VALUE + 12u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_MEMORY1_ADDR, REGISTER_TEST_VALUE + 13u); + TEST_FS85_UpdateMainRegister(&(fs85xx_mcuSupervisor.mainRegister), FS8X_M_DEVICEID_ADDR, REGISTER_TEST_VALUE + 14u); TEST_ASSERT_EQUAL(MAIN_REGISTER.flag, REGISTER_TEST_VALUE + 0u); TEST_ASSERT_EQUAL(MAIN_REGISTER.mode, REGISTER_TEST_VALUE + 1u); @@ -210,3 +224,15 @@ void testSBC_UpdateMainRegister(void) { TEST_ASSERT_EQUAL(MAIN_REGISTER.memory1, REGISTER_TEST_VALUE + 13u); TEST_ASSERT_EQUAL(MAIN_REGISTER.deviceId, REGISTER_TEST_VALUE + 14u); } + +void testFS85_CheckIgnitionSignal(void) { + FS8x_ReadRegister_IgnoreAndReturn(fs8xStatusOk); + TEST_ASSERT_PASS_ASSERT(FS85_CheckIgnitionSignal(&fs85xx_mcuSupervisor)); + TEST_ASSERT_FAIL_ASSERT(FS85_CheckIgnitionSignal(NULL_PTR)); +} + +void testFS85_GoToStandby(void) { + FS8x_WriteRegister_IgnoreAndReturn(fs8xStatusOk); + TEST_ASSERT_PASS_ASSERT(TEST_FS85_GoToStandby(&fs85xx_mcuSupervisor)); + TEST_ASSERT_FAIL_ASSERT(TEST_FS85_GoToStandby(NULL_PTR)); +} diff --git a/tests/unit/app/driver/sbc/test_sbc.c b/tests/unit/app/driver/sbc/test_sbc.c index dc1b9335..9506d641 100644 --- a/tests/unit/app/driver/sbc/test_sbc.c +++ b/tests/unit/app/driver/sbc/test_sbc.c @@ -43,8 +43,8 @@ * @file test_sbc.c * @author foxBMS Team * @date 2020-07-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix SBC * @@ -66,11 +66,20 @@ #include "sbc.h" -TEST_FILE("sbc.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("sbc.c") + +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/sbc") +TEST_INCLUDE_PATH("../../src/app/driver/sbc/fs8x_driver") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/task/config") /*========== Definitions and Implementations for Unit Test ==================*/ -FS85_STATE_s fs85xx_mcuSupervisor = {}; +FS85_STATE_s fs85xx_mcuSupervisor = {0}; /*========== Setup and Teardown =============================================*/ void setUp(void) { @@ -92,12 +101,12 @@ void testSBC_TriggerWatchdogIfRequired(void) { TEST_ASSERT_FALSE(TEST_SBC_TriggerWatchdogIfRequired(&sbc_stateMcuSupervisor)); } /* timer has elapsed now, we should see a trigger event */ - SBC_TriggerWatchdog_IgnoreAndReturn(STD_OK); + FS85_TriggerWatchdog_IgnoreAndReturn(STD_OK); TEST_ASSERT_TRUE(TEST_SBC_TriggerWatchdogIfRequired(&sbc_stateMcuSupervisor)); TEST_ASSERT_EQUAL(sbc_stateMcuSupervisor.watchdogTrigger, sbc_stateMcuSupervisor.watchdogPeriod_10ms); /* elapse timer and fail to run watchdog trigger */ sbc_stateMcuSupervisor.watchdogTrigger = 1u; - SBC_TriggerWatchdog_IgnoreAndReturn(STD_NOT_OK); + FS85_TriggerWatchdog_IgnoreAndReturn(STD_NOT_OK); TEST_ASSERT_FALSE(TEST_SBC_TriggerWatchdogIfRequired(&sbc_stateMcuSupervisor)); } diff --git a/tests/unit/app/driver/spi/test_spi.c b/tests/unit/app/driver/spi/test_spi.c index b19f1ecf..d3240c2e 100644 --- a/tests/unit/app/driver/spi/test_spi.c +++ b/tests/unit/app/driver/spi/test_spi.c @@ -43,8 +43,8 @@ * @file test_spi.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -68,7 +68,13 @@ #include -TEST_FILE("spi.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("spi.c") + +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/spi") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -94,6 +100,16 @@ DMA_CHANNEL_CONFIG_s dma_spiDmaChannels[DMA_NUMBER_SPI_INTERFACES] = { {DMA_CH8, DMA_CH9}, /*!< SPI5 */ }; +/** SPI data configuration struct for ADI communication */ +static spiDAT1_t spi_kAdiDataConfig[BS_NR_OF_STRINGS] = { + { /* struct is implemented in the TI HAL and uses uppercase true and false */ + .CS_HOLD = TRUE, /* If true, HW chip select kept active between words */ + .WDEL = FALSE, /* Activation of delay between words */ + .DFSEL = SPI_FMT_0, /* Data word format selection */ + /* Hardware chip select is configured automatically depending on configuration in #SPI_INTERFACE_CONFIG_s */ + .CSNR = SPI_HARDWARE_CHIP_SELECT_DISABLE_ALL}, +}; + /** SPI data configuration struct for LTC communication */ static spiDAT1_t spi_kLtcDataConfig[BS_NR_OF_STRINGS] = { { /* struct is implemented in the TI HAL and uses uppercase true and false */ @@ -151,16 +167,6 @@ static spiDAT1_t spi_kSpsDataConfigLowSpeed = { .CSNR = SPI_HARDWARE_CHIP_SELECT_DISABLE_ALL, }; -/** SPI data configuration struct for SPS communication in high speed (10MHz) */ -static spiDAT1_t spi_kSpsDataConfigHighSpeed = { - /* struct is implemented in the TI HAL and uses uppercase true and false */ - .CS_HOLD = TRUE, /* If true, HW chip select kept active */ - .WDEL = TRUE, /* Activation of delay between words */ - .DFSEL = SPI_FMT_2, /* Data word format selection */ - /* Hardware chip select is configured automatically depending on configuration in #SPI_INTERFACE_CONFIG_s */ - .CSNR = SPI_HARDWARE_CHIP_SELECT_DISABLE_ALL, -}; - /** SPI configuration struct for SBC communication */ static spiDAT1_t spi_kSbcDataConfig = { /* struct is implemented in the TI HAL and uses uppercase true and false */ @@ -171,6 +177,20 @@ static spiDAT1_t spi_kSbcDataConfig = { .CSNR = SPI_HARDWARE_CHIP_SELECT_DISABLE_ALL, }; +/** + * SPI interface configuration for ADI communication + * This is a list of structs because of multi string + */ +SPI_INTERFACE_CONFIG_s spi_adiInterface[BS_NR_OF_STRINGS] = { + { + .pConfig = &spi_kAdiDataConfig[0u], + .pNode = spiREG1, + .pGioPort = &(spiREG1->PC3), + .csPin = 1u, + .csType = SPI_CHIP_SELECT_HARDWARE, + }, +}; + /** * SPI interface configuration for LTC communication * This is a list of structs because of multi string @@ -290,6 +310,7 @@ void testSPI_InitializeChipSelects(void) { TEST_SPI_InitializeChipSelects(); /* ======= RT1/1: test output verification */ + TEST_ASSERT_EQUAL(SPI_HARDWARE_CHIP_SELECT_1_ACTIVE, spi_adiInterface[currentString].pConfig->CSNR); TEST_ASSERT_EQUAL(SPI_HARDWARE_CHIP_SELECT_1_ACTIVE, spi_ltcInterface[currentString].pConfig->CSNR); TEST_ASSERT_EQUAL(SPI_HARDWARE_CHIP_SELECT_1_ACTIVE, spi_nxp775InterfaceTx[currentString].pConfig->CSNR); TEST_ASSERT_EQUAL(SPI_HARDWARE_CHIP_SELECT_0_ACTIVE, spi_nxp775InterfaceRx[currentString].pConfig->CSNR); diff --git a/tests/unit/app/driver/sps/test_sps.c b/tests/unit/app/driver/sps/test_sps.c index 9ae15b98..47352800 100644 --- a/tests/unit/app/driver/sps/test_sps.c +++ b/tests/unit/app/driver/sps/test_sps.c @@ -43,8 +43,8 @@ * @file test_sps.c * @author foxBMS Team * @date 2020-10-28 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -72,9 +72,17 @@ #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/io") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/sps") + /*========== Definitions and Implementations for Unit Test ==================*/ /** SPI data configuration struct for SPS communication */ -static const spiDAT1_t spi_kSpsDataConfig = { +static spiDAT1_t spi_kSpsDataConfig = { /* struct is implemented in the TI HAL and uses uppercase true and false */ .CS_HOLD = FALSE, /*!< The HW chip select signal is deactivated */ .WDEL = TRUE, /*!< No delay will be inserted */ diff --git a/tests/unit/app/driver/ts/api/test_tsi_limits.c b/tests/unit/app/driver/ts/api/test_tsi_limits.c index 0b2a622d..75cf9776 100644 --- a/tests/unit/app/driver/ts/api/test_tsi_limits.c +++ b/tests/unit/app/driver/ts/api/test_tsi_limits.c @@ -43,8 +43,8 @@ * @file test_tsi_limits.c * @author foxBMS Team * @date 2021-01-15 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TSI * @@ -57,7 +57,12 @@ #include "Mocktsi_plausibility_cfg.h" #include "tsi.h" -TEST_FILE("tsi_limits.c") + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("tsi_limits.c") + +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/epcos/b57251v5103j060/lookup-table/test_epcos_b57251v5103j060_lookup-table.c b/tests/unit/app/driver/ts/epcos/b57251v5103j060/lookup-table/test_epcos_b57251v5103j060_lookup-table.c index 8b882a2c..daa4d9b2 100644 --- a/tests/unit/app/driver/ts/epcos/b57251v5103j060/lookup-table/test_epcos_b57251v5103j060_lookup-table.c +++ b/tests/unit/app/driver/ts/epcos/b57251v5103j060/lookup-table/test_epcos_b57251v5103j060_lookup-table.c @@ -43,8 +43,8 @@ * @file test_epcos_b57251v5103j060_lookup-table.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,12 @@ #include "foxmath.h" #include "tsi.h" -TEST_FILE("epcos_b57251v5103j060_lookup-table.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("epcos_b57251v5103j060_lookup-table.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/epcos/b57251v5103j060") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/epcos/b57251v5103j060/polynomial/test_epcos_b57251v5103j060_polynomial.c b/tests/unit/app/driver/ts/epcos/b57251v5103j060/polynomial/test_epcos_b57251v5103j060_polynomial.c index 97690ab8..03e84aae 100644 --- a/tests/unit/app/driver/ts/epcos/b57251v5103j060/polynomial/test_epcos_b57251v5103j060_polynomial.c +++ b/tests/unit/app/driver/ts/epcos/b57251v5103j060/polynomial/test_epcos_b57251v5103j060_polynomial.c @@ -43,8 +43,8 @@ * @file test_epcos_b57251v5103j060_polynomial.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,12 @@ #include "foxmath.h" #include "tsi.h" -TEST_FILE("epcos_b57251v5103j060_polynomial.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("epcos_b57251v5103j060_polynomial.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/epcos/b57251v5103j060") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/epcos/b57251v5103j060/test_epcos_b57251v5103j060.c b/tests/unit/app/driver/ts/epcos/b57251v5103j060/test_epcos_b57251v5103j060.c index e8d01a4a..b8a4b638 100644 --- a/tests/unit/app/driver/ts/epcos/b57251v5103j060/test_epcos_b57251v5103j060.c +++ b/tests/unit/app/driver/ts/epcos/b57251v5103j060/test_epcos_b57251v5103j060.c @@ -43,8 +43,8 @@ * @file test_epcos_b57251v5103j060.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,6 +58,11 @@ #include "epcos_b57251v5103j060.h" #include "foxmath.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts") +TEST_INCLUDE_PATH("../../src/app/driver/ts/epcos/b57251v5103j060") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/ts/epcos/b57861s0103f045/lookup-table/test_epcos_b57861s0103f045_lookup-table.c b/tests/unit/app/driver/ts/epcos/b57861s0103f045/lookup-table/test_epcos_b57861s0103f045_lookup-table.c index ba95f45c..e6179a1f 100644 --- a/tests/unit/app/driver/ts/epcos/b57861s0103f045/lookup-table/test_epcos_b57861s0103f045_lookup-table.c +++ b/tests/unit/app/driver/ts/epcos/b57861s0103f045/lookup-table/test_epcos_b57861s0103f045_lookup-table.c @@ -43,8 +43,8 @@ * @file test_epcos_b57861s0103f045_lookup-table.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,12 @@ #include "foxmath.h" #include "tsi.h" -TEST_FILE("epcos_b57861s0103f045_lookup-table.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("epcos_b57861s0103f045_lookup-table.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/epcos/b57861s0103f045") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/epcos/b57861s0103f045/polynomial/test_epcos_b57861s0103f045_polynomial.c b/tests/unit/app/driver/ts/epcos/b57861s0103f045/polynomial/test_epcos_b57861s0103f045_polynomial.c index 999ff8f8..201a8769 100644 --- a/tests/unit/app/driver/ts/epcos/b57861s0103f045/polynomial/test_epcos_b57861s0103f045_polynomial.c +++ b/tests/unit/app/driver/ts/epcos/b57861s0103f045/polynomial/test_epcos_b57861s0103f045_polynomial.c @@ -43,8 +43,8 @@ * @file test_epcos_b57861s0103f045_polynomial.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,12 @@ #include "foxmath.h" #include "tsi.h" -TEST_FILE("epcos_b57861s0103f045_polynomial.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("epcos_b57861s0103f045_polynomial.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/epcos/b57861s0103f045") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/epcos/b57861s0103f045/test_epcos_b57861s0103f045.c b/tests/unit/app/driver/ts/epcos/b57861s0103f045/test_epcos_b57861s0103f045.c index d56daf14..c51b4e5b 100644 --- a/tests/unit/app/driver/ts/epcos/b57861s0103f045/test_epcos_b57861s0103f045.c +++ b/tests/unit/app/driver/ts/epcos/b57861s0103f045/test_epcos_b57861s0103f045.c @@ -43,8 +43,8 @@ * @file test_epcos_b57861s0103f045.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,6 +58,11 @@ #include "epcos_b57861s0103f045.h" #include "foxmath.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts") +TEST_INCLUDE_PATH("../../src/app/driver/ts/epcos/b57861s0103f045") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/ts/fake/none/lookup-table/test_fake_none_lookup-table.c b/tests/unit/app/driver/ts/fake/none/lookup-table/test_fake_none_lookup-table.c index ab2f71c7..7217743f 100644 --- a/tests/unit/app/driver/ts/fake/none/lookup-table/test_fake_none_lookup-table.c +++ b/tests/unit/app/driver/ts/fake/none/lookup-table/test_fake_none_lookup-table.c @@ -43,8 +43,8 @@ * @file test_fake_none_lookup-table.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,7 +58,11 @@ #include "fake_none.h" #include "tsi.h" -TEST_FILE("fake_none_lookup-table.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("fake_none_lookup-table.c") + +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/fake/none") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/fake/none/polynomial/test_fake_none_polynomial.c b/tests/unit/app/driver/ts/fake/none/polynomial/test_fake_none_polynomial.c index 0e33a5bb..649b3da2 100644 --- a/tests/unit/app/driver/ts/fake/none/polynomial/test_fake_none_polynomial.c +++ b/tests/unit/app/driver/ts/fake/none/polynomial/test_fake_none_polynomial.c @@ -43,8 +43,8 @@ * @file test_fake_none_polynomial.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,7 +58,11 @@ #include "fake_none.h" #include "tsi.h" -TEST_FILE("fake_none_polynomial.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("fake_none_polynomial.c") + +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/fake/none") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/fake/none/test_fake_none.c b/tests/unit/app/driver/ts/fake/none/test_fake_none.c index 4dbe4645..1e341192 100644 --- a/tests/unit/app/driver/ts/fake/none/test_fake_none.c +++ b/tests/unit/app/driver/ts/fake/none/test_fake_none.c @@ -43,8 +43,8 @@ * @file test_fake_none.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,9 @@ #include "fake_none.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/ts/fake/none") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/ts/murata/ncu15xh103f6sxx/lookup-table/test_murata_ncu15xh103f6sxx_lookup-table.c b/tests/unit/app/driver/ts/murata/ncxxxxh103/lookup-table/test_murata_ncxxxxh103_lookup-table.c similarity index 87% rename from tests/unit/app/driver/ts/murata/ncu15xh103f6sxx/lookup-table/test_murata_ncu15xh103f6sxx_lookup-table.c rename to tests/unit/app/driver/ts/murata/ncxxxxh103/lookup-table/test_murata_ncxxxxh103_lookup-table.c index 17bea8b1..91d7a01d 100644 --- a/tests/unit/app/driver/ts/murata/ncu15xh103f6sxx/lookup-table/test_murata_ncu15xh103f6sxx_lookup-table.c +++ b/tests/unit/app/driver/ts/murata/ncxxxxh103/lookup-table/test_murata_ncxxxxh103_lookup-table.c @@ -40,11 +40,11 @@ */ /** - * @file test_murata_ncu15xh103f6sxx_lookup-table.c + * @file test_murata_ncxxxxh103_lookup-table.c * @author foxBMS Team * @date 2022-10-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -54,12 +54,17 @@ /*========== Includes =======================================================*/ #include "unity.h" -#include "Mockmurata_ncu15xh103f6sxx.h" +#include "Mockmurata_ncxxxxh103.h" #include "foxmath.h" #include "tsi.h" -TEST_FILE("murata_ncu15xh103f6sxx_lookup-table.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("murata_ncxxxxh103_lookup-table.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/murata/ncxxxxh103") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/murata/ncu15xh103f6sxx/polynomial/test_murata_ncu15xh103f6sxx_polynomial.c b/tests/unit/app/driver/ts/murata/ncxxxxh103/polynomial/test_murata_ncxxxxh103_polynomial.c similarity index 85% rename from tests/unit/app/driver/ts/murata/ncu15xh103f6sxx/polynomial/test_murata_ncu15xh103f6sxx_polynomial.c rename to tests/unit/app/driver/ts/murata/ncxxxxh103/polynomial/test_murata_ncxxxxh103_polynomial.c index 51c31147..45f29ca7 100644 --- a/tests/unit/app/driver/ts/murata/ncu15xh103f6sxx/polynomial/test_murata_ncu15xh103f6sxx_polynomial.c +++ b/tests/unit/app/driver/ts/murata/ncxxxxh103/polynomial/test_murata_ncxxxxh103_polynomial.c @@ -40,11 +40,11 @@ */ /** - * @file test_murata_ncu15xh103f6sxx_polynomial.c + * @file test_murata_ncxxxxh103_polynomial.c * @author foxBMS Team * @date 2022-12-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -54,13 +54,18 @@ /*========== Includes =======================================================*/ #include "unity.h" -#include "Mockmurata_ncu15xh103f6sxx.h" +#include "Mockmurata_ncxxxxh103.h" #include "foxmath.h" #include "test_assert_helper.h" #include "tsi.h" -TEST_FILE("murata_ncu15xh103f6sxx_polynomial.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("murata_ncxxxxh103_polynomial.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/murata/ncxxxxh103") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -72,7 +77,7 @@ void tearDown(void) { } /*========== Test Cases =====================================================*/ -void testTSI_GetTemperatureFromMurataNcu15xh103f6sxx(void) { +void testTSI_GetTemperatureFromMurataNcxxxxh103(void) { const uint8_t test_adcVoltage_mv = 0x64; const float test_temperature = 3.5; TS_Mur00GetTemperatureFromPolynomial_ExpectAndReturn(test_adcVoltage_mv, test_temperature); diff --git a/tests/unit/app/driver/ts/murata/ncu15xh103f6sxx/test_murata_ncu15xh103f6sxx.c b/tests/unit/app/driver/ts/murata/ncxxxxh103/test_murata_ncxxxxh103.c similarity index 89% rename from tests/unit/app/driver/ts/murata/ncu15xh103f6sxx/test_murata_ncu15xh103f6sxx.c rename to tests/unit/app/driver/ts/murata/ncxxxxh103/test_murata_ncxxxxh103.c index 51f0b211..99742d2f 100644 --- a/tests/unit/app/driver/ts/murata/ncu15xh103f6sxx/test_murata_ncu15xh103f6sxx.c +++ b/tests/unit/app/driver/ts/murata/ncxxxxh103/test_murata_ncxxxxh103.c @@ -40,11 +40,11 @@ */ /** - * @file test_murata_ncu15xh103f6sxx.c + * @file test_murata_ncxxxxh103.c * @author foxBMS Team * @date 2022-10-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -56,9 +56,14 @@ #include "unity.h" #include "foxmath.h" -#include "murata_ncu15xh103f6sxx.h" +#include "murata_ncxxxxh103.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts") +TEST_INCLUDE_PATH("../../src/app/driver/ts/murata/ncxxxxh103") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/ts/test_beta.c b/tests/unit/app/driver/ts/test_beta.c index 135c2aab..e4b5ccde 100644 --- a/tests/unit/app/driver/ts/test_beta.c +++ b/tests/unit/app/driver/ts/test_beta.c @@ -43,8 +43,8 @@ * @file test_beta.c * @author foxBMS Team * @date 2020-03-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix BETA * @@ -57,6 +57,10 @@ #include "beta.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/ts/vishay/ntcalug01a103g/lookup-table/test_vishay_ntcalug01a103g_lookup-table.c b/tests/unit/app/driver/ts/vishay/ntcalug01a103g/lookup-table/test_vishay_ntcalug01a103g_lookup-table.c index 57ef53d6..68f768f4 100644 --- a/tests/unit/app/driver/ts/vishay/ntcalug01a103g/lookup-table/test_vishay_ntcalug01a103g_lookup-table.c +++ b/tests/unit/app/driver/ts/vishay/ntcalug01a103g/lookup-table/test_vishay_ntcalug01a103g_lookup-table.c @@ -43,8 +43,8 @@ * @file test_vishay_ntcalug01a103g_lookup-table.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,12 @@ #include "foxmath.h" #include "tsi.h" -TEST_FILE("vishay_ntcalug01a103g_lookup-table.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("vishay_ntcalug01a103g_lookup-table.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/vishay/ntcalug01a103g") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/vishay/ntcalug01a103g/polynomial/test_vishay_ntcalug01a103g_polynomial.c b/tests/unit/app/driver/ts/vishay/ntcalug01a103g/polynomial/test_vishay_ntcalug01a103g_polynomial.c index 588edb40..024ef48d 100644 --- a/tests/unit/app/driver/ts/vishay/ntcalug01a103g/polynomial/test_vishay_ntcalug01a103g_polynomial.c +++ b/tests/unit/app/driver/ts/vishay/ntcalug01a103g/polynomial/test_vishay_ntcalug01a103g_polynomial.c @@ -43,8 +43,8 @@ * @file test_vishay_ntcalug01a103g_polynomial.c * @author foxBMS Team * @date 2020-08-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,12 @@ #include "foxmath.h" #include "tsi.h" -TEST_FILE("vishay_ntcalug01a103g_polynomial.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("vishay_ntcalug01a103g_polynomial.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/vishay/ntcalug01a103g") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/vishay/ntcalug01a103g/test_vishay_ntcalug01a103g.c b/tests/unit/app/driver/ts/vishay/ntcalug01a103g/test_vishay_ntcalug01a103g.c index bcf3aad7..7b9526b8 100644 --- a/tests/unit/app/driver/ts/vishay/ntcalug01a103g/test_vishay_ntcalug01a103g.c +++ b/tests/unit/app/driver/ts/vishay/ntcalug01a103g/test_vishay_ntcalug01a103g.c @@ -43,8 +43,8 @@ * @file test_vishay_ntcalug01a103g.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,6 +59,11 @@ #include "test_assert_helper.h" #include "vishay_ntcalug01a103g.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts") +TEST_INCLUDE_PATH("../../src/app/driver/ts/vishay/ntcalug01a103g") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/test_vishay_ntcle317e4103sba_lookup-table.c b/tests/unit/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/test_vishay_ntcle317e4103sba_lookup-table.c index f0072c23..bb851774 100644 --- a/tests/unit/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/test_vishay_ntcle317e4103sba_lookup-table.c +++ b/tests/unit/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/test_vishay_ntcle317e4103sba_lookup-table.c @@ -43,8 +43,8 @@ * @file test_vishay_ntcle317e4103sba_lookup-table.c * @author foxBMS Team * @date 2021-11-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,12 @@ #include "foxmath.h" #include "tsi.h" -TEST_FILE("vishay_ntcle317e4103sba_lookup-table.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("vishay_ntcle317e4103sba_lookup-table.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/vishay/ntcle317e4103sba") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/driver/ts/vishay/ntcle317e4103sba/test_vishay_ntcle317e4103sba.c b/tests/unit/app/driver/ts/vishay/ntcle317e4103sba/test_vishay_ntcle317e4103sba.c index 8beccd0e..eaad3fd3 100644 --- a/tests/unit/app/driver/ts/vishay/ntcle317e4103sba/test_vishay_ntcle317e4103sba.c +++ b/tests/unit/app/driver/ts/vishay/ntcle317e4103sba/test_vishay_ntcle317e4103sba.c @@ -43,8 +43,8 @@ * @file test_vishay_ntcle317e4103sba.c * @author foxBMS Team * @date 2021-11-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,6 +59,11 @@ #include "test_assert_helper.h" #include "vishay_ntcle317e4103sba.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts") +TEST_INCLUDE_PATH("../../src/app/driver/ts/vishay/ntcle317e4103sba") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ @@ -78,7 +83,7 @@ void testTS_Vis01GetTemperatureFromLutFixedValues(void) { TEST_ASSERT_EQUAL_INT16(INT16_MAX, TS_Vis01GetTemperatureFromLut(10u)); } -/** Polynomial is not implemeneted for this sensor */ +/** Polynomial is not implemented for this sensor */ void testTS_Vis01GetTemperatureFromPolynomialFixedValues(void) { TEST_ASSERT_FAIL_ASSERT(TS_Vis01GetTemperatureFromPolynomial(1u)); } diff --git a/tests/unit/app/driver/ts/vishay/ntcle413e2103f102l/lookup-table/test_vishay_ntcle413e2103f102l_lookup-table.c b/tests/unit/app/driver/ts/vishay/ntcle413e2103f102l/lookup-table/test_vishay_ntcle413e2103f102l_lookup-table.c new file mode 100644 index 00000000..d0eefd35 --- /dev/null +++ b/tests/unit/app/driver/ts/vishay/ntcle413e2103f102l/lookup-table/test_vishay_ntcle413e2103f102l_lookup-table.c @@ -0,0 +1,84 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_vishay_ntcle413e2103f102l_lookup-table.c + * @author foxBMS Team + * @date 2021-11-02 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of vishay_ntcle413e2103f102l temperature sensor + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockvishay_ntcle413e2103f102l.h" + +#include "foxmath.h" +#include "tsi.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("vishay_ntcle413e2103f102l_lookup-table.c") + +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts/api") +TEST_INCLUDE_PATH("../../src/app/driver/ts/vishay/ntcle413e2103f102l") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testTSI_GetTemperatureFromVishayNTCLE413E2103F102LLookupTable(void) { + const uint8_t test_adcVoltage_mv = 5; + const float test_temperature = 1.0; + TS_Vis02GetTemperatureFromLut_ExpectAndReturn(test_adcVoltage_mv, test_temperature); + TEST_ASSERT_EQUAL(test_temperature, TSI_GetTemperature(test_adcVoltage_mv)); +} diff --git a/tests/unit/app/driver/ts/vishay/ntcle413e2103f102l/test_vishay_ntcle413e2103f102l.c b/tests/unit/app/driver/ts/vishay/ntcle413e2103f102l/test_vishay_ntcle413e2103f102l.c new file mode 100644 index 00000000..8f76723b --- /dev/null +++ b/tests/unit/app/driver/ts/vishay/ntcle413e2103f102l/test_vishay_ntcle413e2103f102l.c @@ -0,0 +1,94 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_vishay_ntcle413e2103f102l.c + * @author foxBMS Team + * @date 2021-11-02 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Tests for the vishay_ntcle413e2103f102l module + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" + +#include "foxmath.h" +#include "test_assert_helper.h" +#include "vishay_ntcle413e2103f102l.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/foxmath") +TEST_INCLUDE_PATH("../../src/app/driver/ts") +TEST_INCLUDE_PATH("../../src/app/driver/ts/vishay/ntcle413e2103f102l") + +/*========== Definitions and Implementations for Unit Test ==================*/ + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +void testTS_Vis02GetTemperatureFromLutFixedValues(void) { + /* Voltage higher than supply - expected failure - temp on negative boundary */ + TEST_ASSERT_EQUAL_INT16(INT16_MIN, TS_Vis02GetTemperatureFromLut(4000u)); + /* Voltage is zero - expected failure - temp on positive boundary */ + TEST_ASSERT_EQUAL_INT16(INT16_MAX, TS_Vis02GetTemperatureFromLut(0u)); + /* Resistance is high, slightly out of range - expected failure - temp on negative boundary */ + TEST_ASSERT_EQUAL_INT16(INT16_MIN, TS_Vis02GetTemperatureFromLut(2855u)); + /* Resistance is low, slightly out of range - expected failure - temp on positive boundary */ + TEST_ASSERT_EQUAL_INT16(INT16_MAX, TS_Vis02GetTemperatureFromLut(235u)); + /* Resistance is in range - expected success - check expected temp */ + TEST_ASSERT_EQUAL_INT16(-38, TS_Vis02GetTemperatureFromLut(2842u)); + TEST_ASSERT_EQUAL_INT16(103, TS_Vis02GetTemperatureFromLut(248u)); +} + +/** Polynomial is not implemented for this sensor */ +void testTS_Vis02GetTemperatureFromPolynomialFixedValues(void) { + TEST_ASSERT_FAIL_ASSERT(TS_Vis02GetTemperatureFromPolynomial(1u)); +} diff --git a/tests/unit/app/engine/config/test_database_cfg.c b/tests/unit/app/engine/config/test_database_cfg.c index 34a49d85..bf7d0e17 100644 --- a/tests/unit/app/engine/config/test_database_cfg.c +++ b/tests/unit/app/engine/config/test_database_cfg.c @@ -43,8 +43,8 @@ * @file test_database_cfg.c * @author foxBMS Team * @date 2020-04-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,8 @@ #include "database_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/engine/config/test_diag_cfg.c b/tests/unit/app/engine/config/test_diag_cfg.c index 590aa102..16e18650 100644 --- a/tests/unit/app/engine/config/test_diag_cfg.c +++ b/tests/unit/app/engine/config/test_diag_cfg.c @@ -43,8 +43,8 @@ * @file test_diag_cfg.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,6 +59,9 @@ #include "diag_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/engine/config/test_sys_cfg.c b/tests/unit/app/engine/config/test_sys_cfg.c index c9302bed..305ed855 100644 --- a/tests/unit/app/engine/config/test_sys_cfg.c +++ b/tests/unit/app/engine/config/test_sys_cfg.c @@ -43,8 +43,8 @@ * @file test_sys_cfg.c * @author foxBMS Team * @date 2020-04-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,6 +59,10 @@ #include "sys_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/engine/config/test_sys_mon_cfg.c b/tests/unit/app/engine/config/test_sys_mon_cfg.c index 0ff5ccec..7fd3c6db 100644 --- a/tests/unit/app/engine/config/test_sys_mon_cfg.c +++ b/tests/unit/app/engine/config/test_sys_mon_cfg.c @@ -43,8 +43,8 @@ * @file test_sys_mon_cfg.c * @author foxBMS Team * @date 2020-04-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,11 @@ #include "sys_mon_cfg.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ @@ -67,7 +72,7 @@ void tearDown(void) { } /*========== Test Cases =====================================================*/ -void testSYSMDummyCallbackExists() { +void testSYSMDummyCallbackExists(void) { SYSM_TASK_ID_e dummy = SYSM_TASK_ID_MAX; TEST_SYSM_DummyCallback(dummy); } diff --git a/tests/unit/app/engine/database/test_database.c b/tests/unit/app/engine/database/test_database.c index 5e714f2e..c8ec92ca 100644 --- a/tests/unit/app/engine/database/test_database.c +++ b/tests/unit/app/engine/database/test_database.c @@ -43,8 +43,8 @@ * @file test_database.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -67,6 +67,12 @@ #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + /*========== Definitions and Implementations for Unit Test ==================*/ /** * struct for message injection in database queue in #testDATA_ExecuteDataBist() @@ -108,10 +114,6 @@ OS_STD_RETURN_e DATA_mpuInjectValuesForExecuteBISTTestCallback( } void testDATA_ExecuteDataBist(void) { - DATA_BLOCK_DUMMY_FOR_SELF_TEST_s dummyTable = {.header.uniqueId = DATA_BLOCK_ID_DUMMY_FOR_SELF_TEST}; - const uint8_t testValue = DATA_DUMMY_VALUE_UINT8_T_ALTERNATING_BIT_PATTERN; - dummyTable.member1 = UINT8_MAX; - dummyTable.member2 = testValue; OS_SendToBackOfQueue_Stub(&DATA_mpuInjectValuesForExecuteBISTTestCallback); TEST_ASSERT_PASS_ASSERT(DATA_ExecuteDataBist()); } diff --git a/tests/unit/app/engine/database/test_database_helper.c b/tests/unit/app/engine/database/test_database_helper.c index 2e8a4078..3fe3d7bb 100644 --- a/tests/unit/app/engine/database/test_database_helper.c +++ b/tests/unit/app/engine/database/test_database_helper.c @@ -43,8 +43,8 @@ * @file test_database_helper.c * @author foxBMS Team * @date 2021-05-05 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -64,6 +64,8 @@ #include "database_helper.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ @@ -278,9 +280,9 @@ void testDATA_GetModuleNumberFromVoltageIndex(void) { * #testDATA_GetCellNumberFromVoltageIndex */ void testDATA_GetCellNumberFromVoltageIndex(void) { for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) { - for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) { - uint16_t voltageIndex = (m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c; - TEST_ASSERT_EQUAL(DATA_GetCellNumberFromVoltageIndex(voltageIndex), c); + for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) { + uint16_t voltageIndex = (m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + cb; + TEST_ASSERT_EQUAL(DATA_GetCellNumberFromVoltageIndex(voltageIndex), cb); } } diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_aerosol-sensor.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_aerosol-sensor.c new file mode 100644 index 00000000..49b616d1 --- /dev/null +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_aerosol-sensor.c @@ -0,0 +1,145 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file test_diag_cbs_aerosol-sensor.c + * @author foxBMS Team + * @date 2023-09-06 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST + * + * @brief Test of the current sensor diag handler implementation. + * + */ + +/*========== Includes =======================================================*/ +#include "unity.h" +#include "Mockdiag_cfg.h" + +#include "diag_cbs.h" +#include "test_assert_helper.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_aerosol-sensor.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") + +/*========== Definitions and Implementations for Unit Test ==================*/ +/** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ +static DATA_BLOCK_ERROR_STATE_s test_tableErrorFlags = {.header.uniqueId = DATA_BLOCK_ID_ERROR_STATE}; + +/** local copy of the #DATA_BLOCK_MOL_FLAG_s table */ +static DATA_BLOCK_MOL_FLAG_s test_tableMolFlags = {.header.uniqueId = DATA_BLOCK_ID_MOL_FLAG}; + +/** local copy of the #DATA_BLOCK_RSL_FLAG_s table */ +static DATA_BLOCK_RSL_FLAG_s test_tableRslFlags = {.header.uniqueId = DATA_BLOCK_ID_RSL_FLAG}; + +/** local copy of the #DATA_BLOCK_MSL_FLAG_s table */ +static DATA_BLOCK_MSL_FLAG_s test_tableMslFlags = {.header.uniqueId = DATA_BLOCK_ID_MSL_FLAG}; + +const DIAG_DATABASE_SHIM_s diag_kpkDatabaseShim = { + .pTableError = &test_tableErrorFlags, + .pTableMol = &test_tableMolFlags, + .pTableRsl = &test_tableRslFlags, + .pTableMsl = &test_tableMslFlags, +}; + +/*========== Setup and Teardown =============================================*/ +void setUp(void) { +} + +void tearDown(void) { +} + +/*========== Test Cases =====================================================*/ +/** + * @brief Testing DIAG_AerosolAlert + * @details The following cases need to be tested: + * - Argument validation: + * - AT1/3: invalid diagnosis event ID for diagId -> assert + * - AT2/3: invalid event for event -> assert + * - AT3/3: NULL_PTR for kpkDiagShim -> assert + * - Routine validation: + * - RT1/4: Function keeps alter value on false + * - RT2/4: Function sets alert value in the struct to true + * - RT3/4: Function keeps alter value on true after an error + * occurred + * - RT4/4: Function resets alter value in the struct to from true + * to false + */ +void testDIAG_AerosolSensorIllegalInput(void) { + /* ======= Assertion tests ============================================= */ + /* ======= AT1/3 ======= */ + TEST_ASSERT_FAIL_ASSERT(DIAG_AerosolAlert(DIAG_ID_MAX, DIAG_EVENT_OK, &diag_kpkDatabaseShim, 0u)); + /* ======= AT2/3 ======= */ + TEST_ASSERT_FAIL_ASSERT(DIAG_AerosolAlert(DIAG_ID_AEROSOL_ALERT, 42, &diag_kpkDatabaseShim, 0u)); + /* ======= AT3/3 ======= */ + TEST_ASSERT_FAIL_ASSERT(DIAG_AerosolAlert(DIAG_ID_AEROSOL_ALERT, DIAG_EVENT_OK, NULL_PTR, 0u)); + + /* ======= Routine tests =============================================== */ + /* ======= RT1/4: Test implementation */ + diag_kpkDatabaseShim.pTableError->aerosolAlert = false; + /* ======= RT1/4: call function under test */ + DIAG_AerosolAlert(DIAG_ID_AEROSOL_ALERT, DIAG_EVENT_OK, &diag_kpkDatabaseShim, 0u); + /* ======= RT1/4: test output verification */ + TEST_ASSERT_FALSE(diag_kpkDatabaseShim.pTableError->aerosolAlert); + + /* ======= RT2/4: Test implementation */ + diag_kpkDatabaseShim.pTableError->aerosolAlert = false; + /* ======= RT2/4: call function under test */ + DIAG_AerosolAlert(DIAG_ID_AEROSOL_ALERT, DIAG_EVENT_NOT_OK, &diag_kpkDatabaseShim, 0u); + /* ======= RT2/4: test output verification */ + TEST_ASSERT_TRUE(diag_kpkDatabaseShim.pTableError->aerosolAlert); + + /* ======= RT3/4: Test implementation */ + /* ======= RT3/4: call function under test */ + DIAG_AerosolAlert(DIAG_ID_AEROSOL_ALERT, DIAG_EVENT_OK, &diag_kpkDatabaseShim, 0u); + /* ======= RT3/4: test output verification */ + TEST_ASSERT_TRUE(diag_kpkDatabaseShim.pTableError->aerosolAlert); + + /* ======= RT4/4: Test implementation */ + /* ======= RT4/4: call function under test */ + DIAG_AerosolAlert(DIAG_ID_AEROSOL_ALERT, DIAG_EVENT_RESET, &diag_kpkDatabaseShim, 0u); + /* ======= RT4/4: test output verification */ + TEST_ASSERT_FALSE(diag_kpkDatabaseShim.pTableError->aerosolAlert); +} diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_afe.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_afe.c index 4a35120a..04fb1c95 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_afe.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_afe.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_afe.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_afe.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_afe.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_bms.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_bms.c index 57a10645..f7e010c0 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_bms.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_bms.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_bms.c * @author foxBMS Team * @date 2022-07-27 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,7 +61,10 @@ #include -TEST_FILE("diag_cbs_bms.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_bms.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_can.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_can.c index 2d1b1dc2..784b64df 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_can.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_can.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_can.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_can.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_can.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_contactor.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_contactor.c index 2dc5b211..c427c504 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_contactor.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_contactor.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_contactor.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,7 +61,10 @@ #include -TEST_FILE("diag_cbs_contactor.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_contactor.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_current-sensor.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_current-sensor.c index 51bbf9e8..e403ebb8 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_current-sensor.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_current-sensor.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_current-sensor.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_current-sensor.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_current-sensor.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_current.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_current.c index cacaedb8..4f452711 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_current.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_current.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_current.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_current.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_current.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_deep-discharge.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_deep-discharge.c index a97db175..74ecbf80 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_deep-discharge.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_deep-discharge.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_deep-discharge.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,7 +62,12 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_deep-discharge.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_deep-discharge.c") + +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_dummy.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_dummy.c index dfa49d25..8384459f 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_dummy.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_dummy.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_dummy.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_dummy.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_dummy.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_fram.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_fram.c index b27bdf29..9b4d2830 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_fram.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_fram.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_fram.c * @author foxBMS Team * @date 2022-02-24 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,7 +61,10 @@ #include -TEST_FILE("diag_cbs_fram.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_fram.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_i2c.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_i2c.c index 5a4ee1a4..07879da3 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_i2c.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_i2c.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_i2c.c * @author foxBMS Team * @date 2021-09-29 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,7 +61,10 @@ #include -TEST_FILE("diag_cbs_i2c.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_i2c.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_insulation.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_insulation.c index 8393fded..e916fd66 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_insulation.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_insulation.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_insulation.c * @author foxBMS Team * @date 2021-02-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,7 +62,10 @@ #include #include -TEST_FILE("diag_cbs_insulation.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_insulation.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_interlock.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_interlock.c index c2911344..7a7460f6 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_interlock.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_interlock.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_interlock.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,7 +62,10 @@ #include #include -TEST_FILE("diag_cbs_interlock.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_interlock.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_plausibility.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_plausibility.c index ec9bb2a6..b83595c9 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_plausibility.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_plausibility.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_plausibility.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_plausibility.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_plausibility.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_power-measurement.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_power-measurement.c index 91816c57..fb155162 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_power-measurement.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_power-measurement.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_power-measurement.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_power-measurement.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_power-measurement.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_rtc.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_rtc.c index 1753d692..3d25d0d9 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_rtc.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_rtc.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_rtc.c * @author foxBMS Team * @date 2022-11-25 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -62,7 +62,10 @@ #include #include -TEST_FILE("diag_cbs_rtc.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_rtc.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_sbc.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_sbc.c index 77a3ecb2..0cfac26a 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_sbc.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_sbc.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_sbc.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_sbc.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_sbc.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_sys-mon.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_sys-mon.c index 842c57c8..b8a09eb9 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_sys-mon.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_sys-mon.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_sys-mon.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -60,7 +60,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_sys-mon.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_sys-mon.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_temperature.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_temperature.c index c01876ed..328f3a79 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_temperature.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_temperature.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_temperature.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_temperature.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_temperature.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/cbs/test_diag_cbs_voltage.c b/tests/unit/app/engine/diag/cbs/test_diag_cbs_voltage.c index e3626473..a1939990 100644 --- a/tests/unit/app/engine/diag/cbs/test_diag_cbs_voltage.c +++ b/tests/unit/app/engine/diag/cbs/test_diag_cbs_voltage.c @@ -43,8 +43,8 @@ * @file test_diag_cbs_voltage.c * @author foxBMS Team * @date 2021-02-17 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -59,7 +59,10 @@ #include "diag_cbs.h" #include "test_assert_helper.h" -TEST_FILE("diag_cbs_voltage.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("diag_cbs_voltage.c") + +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") /*========== Definitions and Implementations for Unit Test ==================*/ /** local copy of the #DATA_BLOCK_ERROR_STATE_s table */ diff --git a/tests/unit/app/engine/diag/test_diag.c b/tests/unit/app/engine/diag/test_diag.c index dba47816..9288eb63 100644 --- a/tests/unit/app/engine/diag/test_diag.c +++ b/tests/unit/app/engine/diag/test_diag.c @@ -43,8 +43,8 @@ * @file test_diag.c * @author foxBMS Team * @date 2020-04-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,6 +61,10 @@ #include "diag.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/diag/cbs") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/engine/hwinfo/test_masterinfo.c b/tests/unit/app/engine/hw_info/test_master_info.c similarity index 94% rename from tests/unit/app/engine/hwinfo/test_masterinfo.c rename to tests/unit/app/engine/hw_info/test_master_info.c index 63dcbad2..8451c9b6 100644 --- a/tests/unit/app/engine/hwinfo/test_masterinfo.c +++ b/tests/unit/app/engine/hw_info/test_master_info.c @@ -40,11 +40,11 @@ */ /** - * @file test_masterinfo.c + * @file test_master_info.c * @author foxBMS Team * @date 2020-07-09 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -55,7 +55,10 @@ /*========== Includes =======================================================*/ #include "unity.h" -#include "masterinfo.h" +#include "master_info.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/engine/hw_info") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/engine/sys/test_reset.c b/tests/unit/app/engine/sys/test_reset.c index 5f1719c6..31a3ba72 100644 --- a/tests/unit/app/engine/sys/test_reset.c +++ b/tests/unit/app/engine/sys/test_reset.c @@ -43,8 +43,8 @@ * @file test_reset.c * @author foxBMS Team * @date 2022-11-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,7 +57,10 @@ #include "reset.h" -TEST_FILE("reset.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("reset.c") + +TEST_INCLUDE_PATH("../../src/app/engine/sys") /*========== Definitions and Implementations for Unit Test ==================*/ @@ -71,5 +74,5 @@ void tearDown(void) { /*========== Test Cases =====================================================*/ /** make sure that the general BIST is running */ void testSYS_TriggerSoftwareReset(void) { - SYS_TriggerSoftwareReset; + SYS_TriggerSoftwareReset(); } diff --git a/tests/unit/app/engine/sys/test_sys.c b/tests/unit/app/engine/sys/test_sys.c index fb42cc66..3b5237ee 100644 --- a/tests/unit/app/engine/sys/test_sys.c +++ b/tests/unit/app/engine/sys/test_sys.c @@ -43,8 +43,8 @@ * @file test_sys.c * @author foxBMS Team * @date 2020-04-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -78,6 +78,31 @@ #include "sys.h" #include "test_assert_helper.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("sys.c") + +TEST_INCLUDE_PATH("../../src/app/application/algorithm") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/config") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation/sof/trapezoid") +TEST_INCLUDE_PATH("../../src/app/application/bal") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/interlock") +TEST_INCLUDE_PATH("../../src/app/driver/meas") +TEST_INCLUDE_PATH("../../src/app/driver/sbc") +TEST_INCLUDE_PATH("../../src/app/driver/sbc/fs8x_driver") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/sys") +TEST_INCLUDE_PATH("../../src/app/task/config") + /*========== Definitions and Implementations for Unit Test ==================*/ SBC_STATE_s sbc_stateMcuSupervisor; diff --git a/tests/unit/app/engine/sys_mon/test_sys_mon.c b/tests/unit/app/engine/sys_mon/test_sys_mon.c index 4faa539c..75b080d2 100644 --- a/tests/unit/app/engine/sys_mon/test_sys_mon.c +++ b/tests/unit/app/engine/sys_mon/test_sys_mon.c @@ -43,8 +43,8 @@ * @file test_sys_mon.c * @author foxBMS Team * @date 2020-04-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -67,6 +67,12 @@ #include #include +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/sys_mon") + /*========== Definitions and Implementations for Unit Test ==================*/ #define DUMMY_TASK_ID_0 (0) #define DUMMY_TASK_ID_1 (1) diff --git a/tests/unit/app/main/test_fassert.c b/tests/unit/app/main/test_fassert.c index 7f42683a..408ffb06 100644 --- a/tests/unit/app/main/test_fassert.c +++ b/tests/unit/app/main/test_fassert.c @@ -43,8 +43,8 @@ * @file test_fassert.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,8 @@ #include "fassert.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/main/test_fstartup.c b/tests/unit/app/main/test_fstartup.c index 7cfdcc5f..e5fe0367 100644 --- a/tests/unit/app/main/test_fstartup.c +++ b/tests/unit/app/main/test_fstartup.c @@ -43,8 +43,8 @@ * @file test_fstartup.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -55,6 +55,8 @@ /*========== Includes =======================================================*/ #include "unity.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/main/test_main.c b/tests/unit/app/main/test_main.c index 3101c4a4..3d897df9 100644 --- a/tests/unit/app/main/test_main.c +++ b/tests/unit/app/main/test_main.c @@ -43,8 +43,8 @@ * @file test_main.c * @author foxBMS Team * @date 2020-04-01 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -55,6 +55,8 @@ /*========== Includes =======================================================*/ #include "unity.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/app/task/config/test_ftask_cfg.c b/tests/unit/app/task/config/test_ftask_cfg.c index ec7d4f1e..24b73ac6 100644 --- a/tests/unit/app/task/config/test_ftask_cfg.c +++ b/tests/unit/app/task/config/test_ftask_cfg.c @@ -43,8 +43,8 @@ * @file test_ftask_cfg.c * @author foxBMS Team * @date 2020-04-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -91,7 +91,39 @@ #include "fassert.h" #include "ftask.h" -#include "imd.h" + +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/algorithm") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/config") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation/sof/trapezoid") +TEST_INCLUDE_PATH("../../src/app/application/bal") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/application/redundancy") +TEST_INCLUDE_PATH("../../src/app/driver/adc") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/htsensor") +TEST_INCLUDE_PATH("../../src/app/driver/i2c") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/interlock") +TEST_INCLUDE_PATH("../../src/app/driver/led") +TEST_INCLUDE_PATH("../../src/app/driver/meas") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/sbc") +TEST_INCLUDE_PATH("../../src/app/driver/sbc/fs8x_driver") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/sys") +TEST_INCLUDE_PATH("../../src/app/engine/sys_mon") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ OS_TASK_HANDLE ftsk_taskHandleAfe; @@ -110,13 +142,6 @@ SBC_STATE_s sbc_stateMcuSupervisor; SYS_STATE_s sys_state = {0}; -static uint8_t ftsk_dataQueueStorageArea[FTSK_DATA_QUEUE_LENGTH * FTSK_DATA_QUEUE_ITEM_SIZE] = {0}; -static uint8_t ftsk_imdQueueStorageArea[FTSK_IMD_QUEUE_LENGTH * FTSK_IMD_QUEUE_ITEM_SIZE] = {0}; -static uint8_t ftsk_canRxQueueStorageArea[FTSK_CAN_RX_QUEUE_LENGTH * FTSK_CAN_RX_QUEUE_ITEM_SIZE] = {0}; -static StaticQueue_t ftsk_dataQueueStructure; -static StaticQueue_t ftsk_imdQueueStructure; -static StaticQueue_t ftsk_canRxQueueStructure; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/task/ftask/freertos/test_ftask_freertos.c b/tests/unit/app/task/ftask/freertos/test_ftask_freertos.c index eef2ecca..35bf9a00 100644 --- a/tests/unit/app/task/ftask/freertos/test_ftask_freertos.c +++ b/tests/unit/app/task/ftask/freertos/test_ftask_freertos.c @@ -43,8 +43,8 @@ * @file test_ftask_freertos.c * @author foxBMS Team * @date 2021-11-26 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,7 +61,16 @@ #include "ftask.h" -TEST_FILE("ftask_freertos.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("ftask_freertos.c") + +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/engine/sys_mon") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ OS_TASK_HANDLE ftsk_taskHandleAfe; diff --git a/tests/unit/app/task/ftask/test_ftask.c b/tests/unit/app/task/ftask/test_ftask.c index b6734425..e22922d9 100644 --- a/tests/unit/app/task/ftask/test_ftask.c +++ b/tests/unit/app/task/ftask/test_ftask.c @@ -43,8 +43,8 @@ * @file test_ftask.c * @author foxBMS Team * @date 2020-04-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -91,6 +91,39 @@ #include "fassert.h" #include "ftask.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/app/application/algorithm") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/config") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation") +TEST_INCLUDE_PATH("../../src/app/application/algorithm/state_estimation/sof/trapezoid") +TEST_INCLUDE_PATH("../../src/app/application/bal") +TEST_INCLUDE_PATH("../../src/app/application/bms") +TEST_INCLUDE_PATH("../../src/app/application/redundancy") +TEST_INCLUDE_PATH("../../src/app/driver/adc") +TEST_INCLUDE_PATH("../../src/app/driver/afe/api") +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/contactor") +TEST_INCLUDE_PATH("../../src/app/driver/dma") +TEST_INCLUDE_PATH("../../src/app/driver/fram") +TEST_INCLUDE_PATH("../../src/app/driver/htsensor") +TEST_INCLUDE_PATH("../../src/app/driver/i2c") +TEST_INCLUDE_PATH("../../src/app/driver/imd") +TEST_INCLUDE_PATH("../../src/app/driver/interlock") +TEST_INCLUDE_PATH("../../src/app/driver/led") +TEST_INCLUDE_PATH("../../src/app/driver/meas") +TEST_INCLUDE_PATH("../../src/app/driver/pex") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/driver/sbc") +TEST_INCLUDE_PATH("../../src/app/driver/sbc/fs8x_driver") +TEST_INCLUDE_PATH("../../src/app/driver/spi") +TEST_INCLUDE_PATH("../../src/app/driver/sps") +TEST_INCLUDE_PATH("../../src/app/engine/diag") +TEST_INCLUDE_PATH("../../src/app/engine/sys") +TEST_INCLUDE_PATH("../../src/app/engine/sys_mon") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") + /*========== Definitions and Implementations for Unit Test ==================*/ OS_TASK_HANDLE ftsk_taskHandleAfe; @@ -110,14 +143,6 @@ SBC_STATE_s sbc_stateMcuSupervisor; SYS_STATE_s sys_state = {0}; -static uint8_t ftsk_dataQueueStorageArea[FTSK_DATA_QUEUE_LENGTH * FTSK_DATA_QUEUE_ITEM_SIZE] = {0}; -static uint8_t ftsk_imdQueueStorageArea[FTSK_IMD_QUEUE_LENGTH * FTSK_IMD_QUEUE_ITEM_SIZE] = {0}; -static uint8_t ftsk_canRxQueueStorageArea[FTSK_CAN_RX_QUEUE_LENGTH * FTSK_CAN_RX_QUEUE_ITEM_SIZE] = {0}; -static StaticQueue_t ftsk_dataQueueStructure; -static StaticQueue_t ftsk_imdQueueStructure; -static StaticQueue_t ftsk_canRxQueueStructure; -static StaticQueue_t ftsk_rtcQueueStructure; - /*========== Setup and Teardown =============================================*/ void setUp(void) { } diff --git a/tests/unit/app/task/os/freertos/test_os_freertos.c b/tests/unit/app/task/os/freertos/test_os_freertos.c index 1cd6cff7..e1a41a1c 100644 --- a/tests/unit/app/task/os/freertos/test_os_freertos.c +++ b/tests/unit/app/task/os/freertos/test_os_freertos.c @@ -43,8 +43,8 @@ * @file test_os_freertos.c * @author foxBMS Team * @date 2021-11-26 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -54,6 +54,7 @@ /*========== Includes =======================================================*/ #include "unity.h" +#include "Mockcan_cbs_tx_crash-dump.h" #include "Mockftask.h" #include "Mockftask_cfg.h" #include "Mockportmacro.h" @@ -64,7 +65,15 @@ #include "os.h" #include "test_assert_helper.h" -TEST_FILE("os_freertos.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("os_freertos.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ diff --git a/tests/unit/app/task/os/test_os.c b/tests/unit/app/task/os/test_os.c index 7877fed1..aaccd204 100644 --- a/tests/unit/app/task/os/test_os.c +++ b/tests/unit/app/task/os/test_os.c @@ -43,8 +43,8 @@ * @file test_os.c * @author foxBMS Team * @date 2020-03-13 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix OS * @@ -54,6 +54,7 @@ /*========== Includes =======================================================*/ #include "unity.h" +#include "Mockcan.h" #include "Mockftask.h" #include "Mockftask_cfg.h" #include "Mockportmacro.h" @@ -61,17 +62,30 @@ #include "Mockrtc.h" #include "Mocktask.h" +#include "can_cfg.h" + +#include "can_cbs_tx_crash-dump.h" #include "os.h" #include "test_assert_helper.h" #include #include -TEST_FILE("os.c") -TEST_FILE("os_freertos.c") +/*========== Unit Testing Framework Directives ==============================*/ +TEST_SOURCE_FILE("os.c") +TEST_SOURCE_FILE("os_freertos.c") + +TEST_INCLUDE_PATH("../../src/app/driver/can") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs") +TEST_INCLUDE_PATH("../../src/app/driver/can/cbs/tx") +TEST_INCLUDE_PATH("../../src/app/driver/config") +TEST_INCLUDE_PATH("../../src/app/driver/rtc") +TEST_INCLUDE_PATH("../../src/app/task/config") +TEST_INCLUDE_PATH("../../src/app/task/ftask") /*========== Definitions and Implementations for Unit Test ==================*/ static OS_TIMER_s *test_timer; +OS_QUEUE ftsk_imdCanDataQueue = NULL_PTR; /*========== Setup and Teardown =============================================*/ void setUp(void) { diff --git a/tests/unit/axivion/axivion_config.json b/tests/unit/axivion/axivion_config.json new file mode 100644 index 00000000..8997ce65 --- /dev/null +++ b/tests/unit/axivion/axivion_config.json @@ -0,0 +1,14 @@ +{ + "_Layers": [ + "compiler_config.json", + "ci_config.json", + "../../axivion/rule_config_c.py", + "../../axivion/rule_config_c.json", + "../../axivion/rule_config_names.py", + "../../axivion/rule_config_names.json", + "../../axivion/rule_config_include_guard.py", + "../../axivion/rule_config_bad_tokens.json", + "../../axivion/rule_config_metric_lines.json", + "../../axivion/rule_config_addon.json" + ] +} diff --git a/tests/unit/axivion/call_irlink.py b/tests/unit/axivion/call_irlink.py new file mode 100644 index 00000000..2858cd3c --- /dev/null +++ b/tests/unit/axivion/call_irlink.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Template for Python scripts""" + +import argparse +import logging +import shutil +import subprocess +from pathlib import Path + + +def main(): + """This script does this and that""" + parser = argparse.ArgumentParser() + parser.add_argument( + "-v", + "--verbosity", + dest="verbosity", + action="count", + default=0, + help="set verbosity level", + ) + args = parser.parse_args() + + if args.verbosity == 1: + logging.basicConfig(level=logging.INFO) + elif args.verbosity > 1: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.ERROR) + + irlink = shutil.which("irlink") + + tests_dir = Path("tests/unit/build/axivion") + + tests = [str(i) for i in tests_dir.glob("test_*.exe")] + cmd = ( + [ + irlink, + "--multi_binary", + "-j", + ] + + tests + + [ + "tests/unit/build/axivion/foxbms-unit-tests.ir", + ] + ) + + logging.debug(cmd) + logging.debug(f"Number of tests {len(tests)}") + with subprocess.Popen(cmd) as p: + p.communicate() + + +if __name__ == "__main__": + main() diff --git a/tests/unit/axivion/ci_config.json b/tests/unit/axivion/ci_config.json new file mode 100644 index 00000000..a1961093 --- /dev/null +++ b/tests/unit/axivion/ci_config.json @@ -0,0 +1,80 @@ +{ + "Analysis": { + "Analysis-GlobalOptions": { + "global_excludes": [ + "C:/ti/*", + "*build/*", + "*src/hal/*", + "*src/os/*", + "*tools/vendor/ceedling/*" + ] + }, + "SaveRFG": { + "_active": true, + "rfg_file": "../build/axivion/foxbms-unit-tests.elf.rfg" + } + }, + "Project": { + "BuildSystemIntegration": { + "child_order": [ + "Command", + "Linking" + ] + }, + "Command": { + "_active": true, + "build_command": "$(builtin:AXIVION_CONFDIR)/../run_ut_gcc_build.bat configure build_axivion -v -c yes", + "clean_command": "$(builtin:AXIVION_CONFDIR)/../run_ut_gcc_build.bat configure clean_axivion -v -c yes", + "cwd": null + }, + "Git": { + "_active": true, + "sourceserver_gitdir": "$(env:sourceServerGitDir=)" + }, + "Linking": { + "_active": true, + "_copy_from": "Command", + "build_command": "$(builtin:AXIVION_CONFDIR)/link.bat" + }, + "Project-GlobalOptions": { + "ci_mode": { + "clean_after": false, + "clean_before": "!$(env:SKIP_PREBUILD_CLEAN=false)" + }, + "directory": "../../../", + "ir": "tests/unit/build/axivion/foxbms-unit-tests.ir", + "name": "$(env:analysisProjectName=foxbms-2)" + }, + "Shadow": { + "_active": true, + "include_globbings": [ + "*.[ch]" + ], + "rootpath": "build/unit_test", + "shadow_directory": "$(env:projectShadowRepo)" + } + }, + "Results": { + "Dashboard": { + "dashboard_url": "$(env:AXIVION_DASHBOARD_URL=)" + }, + "Database": { + "ci_mode": { + "directory": "$(AXIVION_DATABASES_DIR=.)", + "filename": "$(env:databaseFileRemote=)" + } + }, + "JSONReport": { + "_active": true, + "filename": "foxbms_spa_report.json" + } + }, + "_Format": "1.0", + "_Version": "7.5.2", + "_VersionNum": [ + 7, + 5, + 2, + 11578 + ] +} diff --git a/tests/unit/axivion/compiler_config.json b/tests/unit/axivion/compiler_config.json new file mode 100644 index 00000000..c9569d7b --- /dev/null +++ b/tests/unit/axivion/compiler_config.json @@ -0,0 +1,817 @@ +{ + "Project": { + "GNUToolchain": { + "_active": true, + "archiver": { + "native_archiver": "C:\\MinGW64\\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\\mingw64\\bin\\ar.EXE" + }, + "language_c": { + "emulated_compiler": "GNU", + "emulated_compiler_version": 80100, + "language_version": "C18", + "native_compiler": "C:\\MinGW64\\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\\mingw64\\bin\\gcc.EXE", + "preprocessing": { + "predefined_macros": { + "FAS_ASSERT_LEVEL": "2", + "GNU_COMPILER": "1", + "UNITY_INCLUDE_EXEC_TIME": "1", + "UNITY_UNIT_TEST": "1", + "WIN32": "1", + "WIN64": "1", + "WINNT": "1", + "_INTEGRAL_MAX_BITS": "64", + "_REENTRANT": "1", + "_WIN32": "1", + "_WIN64": "1", + "__ATOMIC_ACQUIRE": "2", + "__ATOMIC_ACQ_REL": "4", + "__ATOMIC_CONSUME": "1", + "__ATOMIC_HLE_ACQUIRE": "65536", + "__ATOMIC_HLE_RELEASE": "131072", + "__ATOMIC_RELAXED": "0", + "__ATOMIC_RELEASE": "3", + "__ATOMIC_SEQ_CST": "5", + "__BIGGEST_ALIGNMENT__": "16", + "__BYTE_ORDER__": "__ORDER_LITTLE_ENDIAN__", + "__CHAR_BIT__": "8", + "__DBL_DECIMAL_DIG__": "17", + "__DBL_DENORM_MIN__": "((double)4.94065645841246544176568792868221372e-324L)", + "__DBL_DIG__": "15", + "__DBL_EPSILON__": "((double)2.22044604925031308084726333618164062e-16L)", + "__DBL_HAS_DENORM__": "1", + "__DBL_HAS_INFINITY__": "1", + "__DBL_HAS_QUIET_NAN__": "1", + "__DBL_MANT_DIG__": "53", + "__DBL_MAX_10_EXP__": "308", + "__DBL_MAX_EXP__": "1024", + "__DBL_MAX__": "((double)1.79769313486231570814527423731704357e+308L)", + "__DBL_MIN_10_EXP__": "(-307)", + "__DBL_MIN_EXP__": "(-1021)", + "__DBL_MIN__": "((double)2.22507385850720138309023271733240406e-308L)", + "__DEC128_EPSILON__": "1E-33DL", + "__DEC128_MANT_DIG__": "34", + "__DEC128_MAX_EXP__": "6145", + "__DEC128_MAX__": "9.999999999999999999999999999999999E6144DL", + "__DEC128_MIN_EXP__": "(-6142)", + "__DEC128_MIN__": "1E-6143DL", + "__DEC128_SUBNORMAL_MIN__": "0.000000000000000000000000000000001E-6143DL", + "__DEC32_EPSILON__": "1E-6DF", + "__DEC32_MANT_DIG__": "7", + "__DEC32_MAX_EXP__": "97", + "__DEC32_MAX__": "9.999999E96DF", + "__DEC32_MIN_EXP__": "(-94)", + "__DEC32_MIN__": "1E-95DF", + "__DEC32_SUBNORMAL_MIN__": "0.000001E-95DF", + "__DEC64_EPSILON__": "1E-15DD", + "__DEC64_MANT_DIG__": "16", + "__DEC64_MAX_EXP__": "385", + "__DEC64_MAX__": "9.999999999999999E384DD", + "__DEC64_MIN_EXP__": "(-382)", + "__DEC64_MIN__": "1E-383DD", + "__DEC64_SUBNORMAL_MIN__": "0.000000000000001E-383DD", + "__DECIMAL_BID_FORMAT__": "1", + "__DECIMAL_DIG__": "21", + "__DEC_EVAL_METHOD__": "2", + "__FINITE_MATH_ONLY__": "0", + "__FLOAT_WORD_ORDER__": "__ORDER_LITTLE_ENDIAN__", + "__FLT128_DECIMAL_DIG__": "36", + "__FLT128_DENORM_MIN__": "6.47517511943802511092443895822764655e-4966F128", + "__FLT128_DIG__": "33", + "__FLT128_EPSILON__": "1.92592994438723585305597794258492732e-34F128", + "__FLT128_HAS_DENORM__": "1", + "__FLT128_HAS_INFINITY__": "1", + "__FLT128_HAS_QUIET_NAN__": "1", + "__FLT128_MANT_DIG__": "113", + "__FLT128_MAX_10_EXP__": "4932", + "__FLT128_MAX_EXP__": "16384", + "__FLT128_MAX__": "1.18973149535723176508575932662800702e+4932F128", + "__FLT128_MIN_10_EXP__": "(-4931)", + "__FLT128_MIN_EXP__": "(-16381)", + "__FLT128_MIN__": "3.36210314311209350626267781732175260e-4932F128", + "__FLT32X_DECIMAL_DIG__": "17", + "__FLT32X_DENORM_MIN__": "4.94065645841246544176568792868221372e-324F32x", + "__FLT32X_DIG__": "15", + "__FLT32X_EPSILON__": "2.22044604925031308084726333618164062e-16F32x", + "__FLT32X_HAS_DENORM__": "1", + "__FLT32X_HAS_INFINITY__": "1", + "__FLT32X_HAS_QUIET_NAN__": "1", + "__FLT32X_MANT_DIG__": "53", + "__FLT32X_MAX_10_EXP__": "308", + "__FLT32X_MAX_EXP__": "1024", + "__FLT32X_MAX__": "1.79769313486231570814527423731704357e+308F32x", + "__FLT32X_MIN_10_EXP__": "(-307)", + "__FLT32X_MIN_EXP__": "(-1021)", + "__FLT32X_MIN__": "2.22507385850720138309023271733240406e-308F32x", + "__FLT32_DECIMAL_DIG__": "9", + "__FLT32_DENORM_MIN__": "1.40129846432481707092372958328991613e-45F32", + "__FLT32_DIG__": "6", + "__FLT32_EPSILON__": "1.19209289550781250000000000000000000e-7F32", + "__FLT32_HAS_DENORM__": "1", + "__FLT32_HAS_INFINITY__": "1", + "__FLT32_HAS_QUIET_NAN__": "1", + "__FLT32_MANT_DIG__": "24", + "__FLT32_MAX_10_EXP__": "38", + "__FLT32_MAX_EXP__": "128", + "__FLT32_MAX__": "3.40282346638528859811704183484516925e+38F32", + "__FLT32_MIN_10_EXP__": "(-37)", + "__FLT32_MIN_EXP__": "(-125)", + "__FLT32_MIN__": "1.17549435082228750796873653722224568e-38F32", + "__FLT64X_DECIMAL_DIG__": "21", + "__FLT64X_DENORM_MIN__": "3.64519953188247460252840593361941982e-4951F64x", + "__FLT64X_DIG__": "18", + "__FLT64X_EPSILON__": "1.08420217248550443400745280086994171e-19F64x", + "__FLT64X_HAS_DENORM__": "1", + "__FLT64X_HAS_INFINITY__": "1", + "__FLT64X_HAS_QUIET_NAN__": "1", + "__FLT64X_MANT_DIG__": "64", + "__FLT64X_MAX_10_EXP__": "4932", + "__FLT64X_MAX_EXP__": "16384", + "__FLT64X_MAX__": "1.18973149535723176502126385303097021e+4932F64x", + "__FLT64X_MIN_10_EXP__": "(-4931)", + "__FLT64X_MIN_EXP__": "(-16381)", + "__FLT64X_MIN__": "3.36210314311209350626267781732175260e-4932F64x", + "__FLT64_DECIMAL_DIG__": "17", + "__FLT64_DENORM_MIN__": "4.94065645841246544176568792868221372e-324F64", + "__FLT64_DIG__": "15", + "__FLT64_EPSILON__": "2.22044604925031308084726333618164062e-16F64", + "__FLT64_HAS_DENORM__": "1", + "__FLT64_HAS_INFINITY__": "1", + "__FLT64_HAS_QUIET_NAN__": "1", + "__FLT64_MANT_DIG__": "53", + "__FLT64_MAX_10_EXP__": "308", + "__FLT64_MAX_EXP__": "1024", + "__FLT64_MAX__": "1.79769313486231570814527423731704357e+308F64", + "__FLT64_MIN_10_EXP__": "(-307)", + "__FLT64_MIN_EXP__": "(-1021)", + "__FLT64_MIN__": "2.22507385850720138309023271733240406e-308F64", + "__FLT_DECIMAL_DIG__": "9", + "__FLT_DENORM_MIN__": "1.40129846432481707092372958328991613e-45F", + "__FLT_DIG__": "6", + "__FLT_EPSILON__": "1.19209289550781250000000000000000000e-7F", + "__FLT_EVAL_METHOD_TS_18661_3__": "0", + "__FLT_EVAL_METHOD__": "0", + "__FLT_HAS_DENORM__": "1", + "__FLT_HAS_INFINITY__": "1", + "__FLT_HAS_QUIET_NAN__": "1", + "__FLT_MANT_DIG__": "24", + "__FLT_MAX_10_EXP__": "38", + "__FLT_MAX_EXP__": "128", + "__FLT_MAX__": "3.40282346638528859811704183484516925e+38F", + "__FLT_MIN_10_EXP__": "(-37)", + "__FLT_MIN_EXP__": "(-125)", + "__FLT_MIN__": "1.17549435082228750796873653722224568e-38F", + "__FLT_RADIX__": "2", + "__FXSR__": "1", + "__GCC_ASM_FLAG_OUTPUTS__": "1", + "__GCC_ATOMIC_BOOL_LOCK_FREE": "2", + "__GCC_ATOMIC_CHAR16_T_LOCK_FREE": "2", + "__GCC_ATOMIC_CHAR32_T_LOCK_FREE": "2", + "__GCC_ATOMIC_CHAR_LOCK_FREE": "2", + "__GCC_ATOMIC_INT_LOCK_FREE": "2", + "__GCC_ATOMIC_LLONG_LOCK_FREE": "2", + "__GCC_ATOMIC_LONG_LOCK_FREE": "2", + "__GCC_ATOMIC_POINTER_LOCK_FREE": "2", + "__GCC_ATOMIC_SHORT_LOCK_FREE": "2", + "__GCC_ATOMIC_TEST_AND_SET_TRUEVAL": "1", + "__GCC_ATOMIC_WCHAR_T_LOCK_FREE": "2", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1": "1", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16": "1", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2": "1", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4": "1", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8": "1", + "__GCC_IEC_559": "2", + "__GCC_IEC_559_COMPLEX": "2", + "__GXX_ABI_VERSION": "1012", + "__GXX_MERGED_TYPEINFO_NAMES": "0", + "__GXX_TYPEINFO_EQUALITY_INLINE": "0", + "__INT16_C(c)": "c", + "__INT16_MAX__": "0x7fff", + "__INT16_TYPE__": "short int", + "__INT32_C(c)": "c", + "__INT32_MAX__": "0x7fffffff", + "__INT32_TYPE__": "int", + "__INT64_C(c)": "c ## LL", + "__INT64_MAX__": "0x7fffffffffffffffLL", + "__INT64_TYPE__": "long long int", + "__INT8_C(c)": "c", + "__INT8_MAX__": "0x7f", + "__INT8_TYPE__": "signed char", + "__INTMAX_C(c)": "c ## LL", + "__INTMAX_MAX__": "0x7fffffffffffffffLL", + "__INTMAX_TYPE__": "long long int", + "__INTMAX_WIDTH__": "64", + "__INTPTR_MAX__": "0x7fffffffffffffffLL", + "__INTPTR_TYPE__": "long long int", + "__INTPTR_WIDTH__": "64", + "__INT_FAST16_MAX__": "0x7fff", + "__INT_FAST16_TYPE__": "short int", + "__INT_FAST16_WIDTH__": "16", + "__INT_FAST32_MAX__": "0x7fffffff", + "__INT_FAST32_TYPE__": "int", + "__INT_FAST32_WIDTH__": "32", + "__INT_FAST64_MAX__": "0x7fffffffffffffffLL", + "__INT_FAST64_TYPE__": "long long int", + "__INT_FAST64_WIDTH__": "64", + "__INT_FAST8_MAX__": "0x7f", + "__INT_FAST8_TYPE__": "signed char", + "__INT_FAST8_WIDTH__": "8", + "__INT_LEAST16_MAX__": "0x7fff", + "__INT_LEAST16_TYPE__": "short int", + "__INT_LEAST16_WIDTH__": "16", + "__INT_LEAST32_MAX__": "0x7fffffff", + "__INT_LEAST32_TYPE__": "int", + "__INT_LEAST32_WIDTH__": "32", + "__INT_LEAST64_MAX__": "0x7fffffffffffffffLL", + "__INT_LEAST64_TYPE__": "long long int", + "__INT_LEAST64_WIDTH__": "64", + "__INT_LEAST8_MAX__": "0x7f", + "__INT_LEAST8_TYPE__": "signed char", + "__INT_LEAST8_WIDTH__": "8", + "__INT_MAX__": "0x7fffffff", + "__INT_WIDTH__": "32", + "__LDBL_DECIMAL_DIG__": "21", + "__LDBL_DENORM_MIN__": "3.64519953188247460252840593361941982e-4951L", + "__LDBL_DIG__": "18", + "__LDBL_EPSILON__": "1.08420217248550443400745280086994171e-19L", + "__LDBL_HAS_DENORM__": "1", + "__LDBL_HAS_INFINITY__": "1", + "__LDBL_HAS_QUIET_NAN__": "1", + "__LDBL_MANT_DIG__": "64", + "__LDBL_MAX_10_EXP__": "4932", + "__LDBL_MAX_EXP__": "16384", + "__LDBL_MAX__": "1.18973149535723176502126385303097021e+4932L", + "__LDBL_MIN_10_EXP__": "(-4931)", + "__LDBL_MIN_EXP__": "(-16381)", + "__LDBL_MIN__": "3.36210314311209350626267781732175260e-4932L", + "__LONG_LONG_MAX__": "0x7fffffffffffffffLL", + "__LONG_LONG_WIDTH__": "64", + "__LONG_MAX__": "0x7fffffffL", + "__LONG_WIDTH__": "32", + "__MINGW32__": "1", + "__MINGW64__": "1", + "__MMX__": "1", + "__MSVCRT__": "1", + "__NO_INLINE__": "1", + "__ORDER_BIG_ENDIAN__": "4321", + "__ORDER_LITTLE_ENDIAN__": "1234", + "__ORDER_PDP_ENDIAN__": "3412", + "__PIC__": "1", + "__PRAGMA_REDEFINE_EXTNAME": "1", + "__PTRDIFF_MAX__": "0x7fffffffffffffffLL", + "__PTRDIFF_TYPE__": "long long int", + "__PTRDIFF_WIDTH__": "64", + "__REGISTER_PREFIX__": "", + "__SCHAR_MAX__": "0x7f", + "__SCHAR_WIDTH__": "8", + "__SEG_FS": "1", + "__SEG_GS": "1", + "__SEH__": "1", + "__SHRT_MAX__": "0x7fff", + "__SHRT_WIDTH__": "16", + "__SIG_ATOMIC_MAX__": "0x7fffffff", + "__SIG_ATOMIC_MIN__": "(-__SIG_ATOMIC_MAX__ - 1)", + "__SIG_ATOMIC_TYPE__": "int", + "__SIG_ATOMIC_WIDTH__": "32", + "__SIZEOF_DOUBLE__": "8", + "__SIZEOF_FLOAT128__": "16", + "__SIZEOF_FLOAT80__": "16", + "__SIZEOF_FLOAT__": "4", + "__SIZEOF_INT128__": "16", + "__SIZEOF_INT__": "4", + "__SIZEOF_LONG_DOUBLE__": "16", + "__SIZEOF_LONG_LONG__": "8", + "__SIZEOF_LONG__": "4", + "__SIZEOF_POINTER__": "8", + "__SIZEOF_PTRDIFF_T__": "8", + "__SIZEOF_SHORT__": "2", + "__SIZEOF_SIZE_T__": "8", + "__SIZEOF_WCHAR_T__": "2", + "__SIZEOF_WINT_T__": "2", + "__SIZE_MAX__": "0xffffffffffffffffULL", + "__SIZE_TYPE__": "long long unsigned int", + "__SIZE_WIDTH__": "64", + "__SSE2_MATH__": "1", + "__SSE2__": "1", + "__SSE3__": "1", + "__SSE_MATH__": "1", + "__SSE__": "1", + "__STDC_HOSTED__": "1", + "__STDC_UTF_16__": "1", + "__STDC_UTF_32__": "1", + "__UINT16_C(c)": "c", + "__UINT16_MAX__": "0xffff", + "__UINT16_TYPE__": "short unsigned int", + "__UINT32_C(c)": "c ## U", + "__UINT32_MAX__": "0xffffffffU", + "__UINT32_TYPE__": "unsigned int", + "__UINT64_C(c)": "c ## ULL", + "__UINT64_MAX__": "0xffffffffffffffffULL", + "__UINT64_TYPE__": "long long unsigned int", + "__UINT8_C(c)": "c", + "__UINT8_MAX__": "0xff", + "__UINT8_TYPE__": "unsigned char", + "__UINTMAX_C(c)": "c ## ULL", + "__UINTMAX_MAX__": "0xffffffffffffffffULL", + "__UINTMAX_TYPE__": "long long unsigned int", + "__UINTPTR_MAX__": "0xffffffffffffffffULL", + "__UINTPTR_TYPE__": "long long unsigned int", + "__UINT_FAST16_MAX__": "0xffff", + "__UINT_FAST16_TYPE__": "short unsigned int", + "__UINT_FAST32_MAX__": "0xffffffffU", + "__UINT_FAST32_TYPE__": "unsigned int", + "__UINT_FAST64_MAX__": "0xffffffffffffffffULL", + "__UINT_FAST64_TYPE__": "long long unsigned int", + "__UINT_FAST8_MAX__": "0xff", + "__UINT_FAST8_TYPE__": "unsigned char", + "__UINT_LEAST16_MAX__": "0xffff", + "__UINT_LEAST16_TYPE__": "short unsigned int", + "__UINT_LEAST32_MAX__": "0xffffffffU", + "__UINT_LEAST32_TYPE__": "unsigned int", + "__UINT_LEAST64_MAX__": "0xffffffffffffffffULL", + "__UINT_LEAST64_TYPE__": "long long unsigned int", + "__UINT_LEAST8_MAX__": "0xff", + "__UINT_LEAST8_TYPE__": "unsigned char", + "__USER_LABEL_PREFIX__": "", + "__WCHAR_MAX__": "0xffff", + "__WCHAR_MIN__": "0", + "__WCHAR_TYPE__": "short unsigned int", + "__WCHAR_WIDTH__": "16", + "__WIN32": "1", + "__WIN32__": "1", + "__WIN64": "1", + "__WIN64__": "1", + "__WINNT": "1", + "__WINNT__": "1", + "__WINT_MAX__": "0xffff", + "__WINT_MIN__": "0", + "__WINT_TYPE__": "short unsigned int", + "__WINT_WIDTH__": "16", + "__amd64": "1", + "__amd64__": "1", + "__cdecl": "__attribute__((__cdecl__))", + "__code_model_medium__": "1", + "__declspec(x)": "__attribute__((x))", + "__fastcall": "__attribute__((__fastcall__))", + "__nocona": "1", + "__nocona__": "1", + "__pic__": "1", + "__stdcall": "__attribute__((__stdcall__))", + "__thiscall": "__attribute__((__thiscall__))", + "__tune_core2__": "1", + "__x86_64": "1", + "__x86_64__": "1", + "_cdecl": "__attribute__((__cdecl__))", + "_fastcall": "__attribute__((__fastcall__))", + "_stdcall": "__attribute__((__stdcall__))", + "_thiscall": "__attribute__((__thiscall__))" + }, + "sys_include_envvar": null, + "sys_include_path": [ + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include-fixed", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/include" + ] + } + }, + "language_c.command.#": "C:\\MinGW64\\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\\mingw64\\bin\\gcc.EXE -DGNU_COMPILER -DUNITY_UNIT_TEST -DUNITY_INCLUDE_EXEC_TIME -DFAS_ASSERT_LEVEL=2", + "language_c.info.#": "Using built-in specs.\nCOLLECT_GCC=C:\\MinGW64\\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\\mingw64\\bin\\gcc.EXE\nCOLLECT_LTO_WRAPPER=C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/8.1.0/lto-wrapper.exe\nTarget: x86_64-w64-mingw32\nConfigured with: ../../../src/gcc-8.1.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64 --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev0, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/lib -L/c/mingw810/prerequisites/x86_64-zlib-static/lib -L/c/mingw810/prerequisites/x86_64-w64-mingw32-static/lib '\nThread model: posix\ngcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) \n", + "language_cxx": { + "emulated_compiler": "GNU", + "emulated_compiler_version": 80100, + "language_version": "Cpp14", + "native_compiler": "C:\\MinGW64\\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.EXE", + "preprocessing": { + "predefined_macros": { + "FAS_ASSERT_LEVEL": "2", + "GNU_COMPILER": "1", + "UNITY_INCLUDE_EXEC_TIME": "1", + "UNITY_UNIT_TEST": "1", + "WIN32": "1", + "WIN64": "1", + "WINNT": "1", + "_INTEGRAL_MAX_BITS": "64", + "_REENTRANT": "1", + "_WIN32": "1", + "_WIN64": "1", + "__ATOMIC_ACQUIRE": "2", + "__ATOMIC_ACQ_REL": "4", + "__ATOMIC_CONSUME": "1", + "__ATOMIC_HLE_ACQUIRE": "65536", + "__ATOMIC_HLE_RELEASE": "131072", + "__ATOMIC_RELAXED": "0", + "__ATOMIC_RELEASE": "3", + "__ATOMIC_SEQ_CST": "5", + "__BIGGEST_ALIGNMENT__": "16", + "__BYTE_ORDER__": "__ORDER_LITTLE_ENDIAN__", + "__CHAR_BIT__": "8", + "__DBL_DECIMAL_DIG__": "17", + "__DBL_DENORM_MIN__": "double(4.94065645841246544176568792868221372e-324L)", + "__DBL_DIG__": "15", + "__DBL_EPSILON__": "double(2.22044604925031308084726333618164062e-16L)", + "__DBL_HAS_DENORM__": "1", + "__DBL_HAS_INFINITY__": "1", + "__DBL_HAS_QUIET_NAN__": "1", + "__DBL_MANT_DIG__": "53", + "__DBL_MAX_10_EXP__": "308", + "__DBL_MAX_EXP__": "1024", + "__DBL_MAX__": "double(1.79769313486231570814527423731704357e+308L)", + "__DBL_MIN_10_EXP__": "(-307)", + "__DBL_MIN_EXP__": "(-1021)", + "__DBL_MIN__": "double(2.22507385850720138309023271733240406e-308L)", + "__DEC128_EPSILON__": "1E-33DL", + "__DEC128_MANT_DIG__": "34", + "__DEC128_MAX_EXP__": "6145", + "__DEC128_MAX__": "9.999999999999999999999999999999999E6144DL", + "__DEC128_MIN_EXP__": "(-6142)", + "__DEC128_MIN__": "1E-6143DL", + "__DEC128_SUBNORMAL_MIN__": "0.000000000000000000000000000000001E-6143DL", + "__DEC32_EPSILON__": "1E-6DF", + "__DEC32_MANT_DIG__": "7", + "__DEC32_MAX_EXP__": "97", + "__DEC32_MAX__": "9.999999E96DF", + "__DEC32_MIN_EXP__": "(-94)", + "__DEC32_MIN__": "1E-95DF", + "__DEC32_SUBNORMAL_MIN__": "0.000001E-95DF", + "__DEC64_EPSILON__": "1E-15DD", + "__DEC64_MANT_DIG__": "16", + "__DEC64_MAX_EXP__": "385", + "__DEC64_MAX__": "9.999999999999999E384DD", + "__DEC64_MIN_EXP__": "(-382)", + "__DEC64_MIN__": "1E-383DD", + "__DEC64_SUBNORMAL_MIN__": "0.000000000000001E-383DD", + "__DECIMAL_BID_FORMAT__": "1", + "__DECIMAL_DIG__": "21", + "__DEC_EVAL_METHOD__": "2", + "__DEPRECATED": "1", + "__FINITE_MATH_ONLY__": "0", + "__FLOAT_WORD_ORDER__": "__ORDER_LITTLE_ENDIAN__", + "__FLT128_DECIMAL_DIG__": "36", + "__FLT128_DENORM_MIN__": "6.47517511943802511092443895822764655e-4966F128", + "__FLT128_DIG__": "33", + "__FLT128_EPSILON__": "1.92592994438723585305597794258492732e-34F128", + "__FLT128_HAS_DENORM__": "1", + "__FLT128_HAS_INFINITY__": "1", + "__FLT128_HAS_QUIET_NAN__": "1", + "__FLT128_MANT_DIG__": "113", + "__FLT128_MAX_10_EXP__": "4932", + "__FLT128_MAX_EXP__": "16384", + "__FLT128_MAX__": "1.18973149535723176508575932662800702e+4932F128", + "__FLT128_MIN_10_EXP__": "(-4931)", + "__FLT128_MIN_EXP__": "(-16381)", + "__FLT128_MIN__": "3.36210314311209350626267781732175260e-4932F128", + "__FLT32X_DECIMAL_DIG__": "17", + "__FLT32X_DENORM_MIN__": "4.94065645841246544176568792868221372e-324F32x", + "__FLT32X_DIG__": "15", + "__FLT32X_EPSILON__": "2.22044604925031308084726333618164062e-16F32x", + "__FLT32X_HAS_DENORM__": "1", + "__FLT32X_HAS_INFINITY__": "1", + "__FLT32X_HAS_QUIET_NAN__": "1", + "__FLT32X_MANT_DIG__": "53", + "__FLT32X_MAX_10_EXP__": "308", + "__FLT32X_MAX_EXP__": "1024", + "__FLT32X_MAX__": "1.79769313486231570814527423731704357e+308F32x", + "__FLT32X_MIN_10_EXP__": "(-307)", + "__FLT32X_MIN_EXP__": "(-1021)", + "__FLT32X_MIN__": "2.22507385850720138309023271733240406e-308F32x", + "__FLT32_DECIMAL_DIG__": "9", + "__FLT32_DENORM_MIN__": "1.40129846432481707092372958328991613e-45F32", + "__FLT32_DIG__": "6", + "__FLT32_EPSILON__": "1.19209289550781250000000000000000000e-7F32", + "__FLT32_HAS_DENORM__": "1", + "__FLT32_HAS_INFINITY__": "1", + "__FLT32_HAS_QUIET_NAN__": "1", + "__FLT32_MANT_DIG__": "24", + "__FLT32_MAX_10_EXP__": "38", + "__FLT32_MAX_EXP__": "128", + "__FLT32_MAX__": "3.40282346638528859811704183484516925e+38F32", + "__FLT32_MIN_10_EXP__": "(-37)", + "__FLT32_MIN_EXP__": "(-125)", + "__FLT32_MIN__": "1.17549435082228750796873653722224568e-38F32", + "__FLT64X_DECIMAL_DIG__": "21", + "__FLT64X_DENORM_MIN__": "3.64519953188247460252840593361941982e-4951F64x", + "__FLT64X_DIG__": "18", + "__FLT64X_EPSILON__": "1.08420217248550443400745280086994171e-19F64x", + "__FLT64X_HAS_DENORM__": "1", + "__FLT64X_HAS_INFINITY__": "1", + "__FLT64X_HAS_QUIET_NAN__": "1", + "__FLT64X_MANT_DIG__": "64", + "__FLT64X_MAX_10_EXP__": "4932", + "__FLT64X_MAX_EXP__": "16384", + "__FLT64X_MAX__": "1.18973149535723176502126385303097021e+4932F64x", + "__FLT64X_MIN_10_EXP__": "(-4931)", + "__FLT64X_MIN_EXP__": "(-16381)", + "__FLT64X_MIN__": "3.36210314311209350626267781732175260e-4932F64x", + "__FLT64_DECIMAL_DIG__": "17", + "__FLT64_DENORM_MIN__": "4.94065645841246544176568792868221372e-324F64", + "__FLT64_DIG__": "15", + "__FLT64_EPSILON__": "2.22044604925031308084726333618164062e-16F64", + "__FLT64_HAS_DENORM__": "1", + "__FLT64_HAS_INFINITY__": "1", + "__FLT64_HAS_QUIET_NAN__": "1", + "__FLT64_MANT_DIG__": "53", + "__FLT64_MAX_10_EXP__": "308", + "__FLT64_MAX_EXP__": "1024", + "__FLT64_MAX__": "1.79769313486231570814527423731704357e+308F64", + "__FLT64_MIN_10_EXP__": "(-307)", + "__FLT64_MIN_EXP__": "(-1021)", + "__FLT64_MIN__": "2.22507385850720138309023271733240406e-308F64", + "__FLT_DECIMAL_DIG__": "9", + "__FLT_DENORM_MIN__": "1.40129846432481707092372958328991613e-45F", + "__FLT_DIG__": "6", + "__FLT_EPSILON__": "1.19209289550781250000000000000000000e-7F", + "__FLT_EVAL_METHOD_TS_18661_3__": "0", + "__FLT_EVAL_METHOD__": "0", + "__FLT_HAS_DENORM__": "1", + "__FLT_HAS_INFINITY__": "1", + "__FLT_HAS_QUIET_NAN__": "1", + "__FLT_MANT_DIG__": "24", + "__FLT_MAX_10_EXP__": "38", + "__FLT_MAX_EXP__": "128", + "__FLT_MAX__": "3.40282346638528859811704183484516925e+38F", + "__FLT_MIN_10_EXP__": "(-37)", + "__FLT_MIN_EXP__": "(-125)", + "__FLT_MIN__": "1.17549435082228750796873653722224568e-38F", + "__FLT_RADIX__": "2", + "__FXSR__": "1", + "__GCC_ASM_FLAG_OUTPUTS__": "1", + "__GCC_ATOMIC_BOOL_LOCK_FREE": "2", + "__GCC_ATOMIC_CHAR16_T_LOCK_FREE": "2", + "__GCC_ATOMIC_CHAR32_T_LOCK_FREE": "2", + "__GCC_ATOMIC_CHAR_LOCK_FREE": "2", + "__GCC_ATOMIC_INT_LOCK_FREE": "2", + "__GCC_ATOMIC_LLONG_LOCK_FREE": "2", + "__GCC_ATOMIC_LONG_LOCK_FREE": "2", + "__GCC_ATOMIC_POINTER_LOCK_FREE": "2", + "__GCC_ATOMIC_SHORT_LOCK_FREE": "2", + "__GCC_ATOMIC_TEST_AND_SET_TRUEVAL": "1", + "__GCC_ATOMIC_WCHAR_T_LOCK_FREE": "2", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1": "1", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16": "1", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2": "1", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4": "1", + "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8": "1", + "__GCC_IEC_559": "2", + "__GCC_IEC_559_COMPLEX": "2", + "__GLIBCXX_BITSIZE_INT_N_0": "128", + "__GLIBCXX_TYPE_INT_N_0": "__int128", + "__GXX_ABI_VERSION": "1012", + "__GXX_MERGED_TYPEINFO_NAMES": "0", + "__GXX_TYPEINFO_EQUALITY_INLINE": "0", + "__GXX_WEAK__": "1", + "__INT16_C(c)": "c", + "__INT16_MAX__": "0x7fff", + "__INT16_TYPE__": "short int", + "__INT32_C(c)": "c", + "__INT32_MAX__": "0x7fffffff", + "__INT32_TYPE__": "int", + "__INT64_C(c)": "c ## LL", + "__INT64_MAX__": "0x7fffffffffffffffLL", + "__INT64_TYPE__": "long long int", + "__INT8_C(c)": "c", + "__INT8_MAX__": "0x7f", + "__INT8_TYPE__": "signed char", + "__INTMAX_C(c)": "c ## LL", + "__INTMAX_MAX__": "0x7fffffffffffffffLL", + "__INTMAX_TYPE__": "long long int", + "__INTMAX_WIDTH__": "64", + "__INTPTR_MAX__": "0x7fffffffffffffffLL", + "__INTPTR_TYPE__": "long long int", + "__INTPTR_WIDTH__": "64", + "__INT_FAST16_MAX__": "0x7fff", + "__INT_FAST16_TYPE__": "short int", + "__INT_FAST16_WIDTH__": "16", + "__INT_FAST32_MAX__": "0x7fffffff", + "__INT_FAST32_TYPE__": "int", + "__INT_FAST32_WIDTH__": "32", + "__INT_FAST64_MAX__": "0x7fffffffffffffffLL", + "__INT_FAST64_TYPE__": "long long int", + "__INT_FAST64_WIDTH__": "64", + "__INT_FAST8_MAX__": "0x7f", + "__INT_FAST8_TYPE__": "signed char", + "__INT_FAST8_WIDTH__": "8", + "__INT_LEAST16_MAX__": "0x7fff", + "__INT_LEAST16_TYPE__": "short int", + "__INT_LEAST16_WIDTH__": "16", + "__INT_LEAST32_MAX__": "0x7fffffff", + "__INT_LEAST32_TYPE__": "int", + "__INT_LEAST32_WIDTH__": "32", + "__INT_LEAST64_MAX__": "0x7fffffffffffffffLL", + "__INT_LEAST64_TYPE__": "long long int", + "__INT_LEAST64_WIDTH__": "64", + "__INT_LEAST8_MAX__": "0x7f", + "__INT_LEAST8_TYPE__": "signed char", + "__INT_LEAST8_WIDTH__": "8", + "__INT_MAX__": "0x7fffffff", + "__INT_WIDTH__": "32", + "__LDBL_DECIMAL_DIG__": "21", + "__LDBL_DENORM_MIN__": "3.64519953188247460252840593361941982e-4951L", + "__LDBL_DIG__": "18", + "__LDBL_EPSILON__": "1.08420217248550443400745280086994171e-19L", + "__LDBL_HAS_DENORM__": "1", + "__LDBL_HAS_INFINITY__": "1", + "__LDBL_HAS_QUIET_NAN__": "1", + "__LDBL_MANT_DIG__": "64", + "__LDBL_MAX_10_EXP__": "4932", + "__LDBL_MAX_EXP__": "16384", + "__LDBL_MAX__": "1.18973149535723176502126385303097021e+4932L", + "__LDBL_MIN_10_EXP__": "(-4931)", + "__LDBL_MIN_EXP__": "(-16381)", + "__LDBL_MIN__": "3.36210314311209350626267781732175260e-4932L", + "__LONG_LONG_MAX__": "0x7fffffffffffffffLL", + "__LONG_LONG_WIDTH__": "64", + "__LONG_MAX__": "0x7fffffffL", + "__LONG_WIDTH__": "32", + "__MINGW32__": "1", + "__MINGW64__": "1", + "__MMX__": "1", + "__MSVCRT__": "1", + "__NO_INLINE__": "1", + "__ORDER_BIG_ENDIAN__": "4321", + "__ORDER_LITTLE_ENDIAN__": "1234", + "__ORDER_PDP_ENDIAN__": "3412", + "__PIC__": "1", + "__PRAGMA_REDEFINE_EXTNAME": "1", + "__PTRDIFF_MAX__": "0x7fffffffffffffffLL", + "__PTRDIFF_TYPE__": "long long int", + "__PTRDIFF_WIDTH__": "64", + "__REGISTER_PREFIX__": "", + "__SCHAR_MAX__": "0x7f", + "__SCHAR_WIDTH__": "8", + "__SEG_FS": "1", + "__SEG_GS": "1", + "__SEH__": "1", + "__SHRT_MAX__": "0x7fff", + "__SHRT_WIDTH__": "16", + "__SIG_ATOMIC_MAX__": "0x7fffffff", + "__SIG_ATOMIC_MIN__": "(-__SIG_ATOMIC_MAX__ - 1)", + "__SIG_ATOMIC_TYPE__": "int", + "__SIG_ATOMIC_WIDTH__": "32", + "__SIZEOF_DOUBLE__": "8", + "__SIZEOF_FLOAT128__": "16", + "__SIZEOF_FLOAT80__": "16", + "__SIZEOF_FLOAT__": "4", + "__SIZEOF_INT128__": "16", + "__SIZEOF_INT__": "4", + "__SIZEOF_LONG_DOUBLE__": "16", + "__SIZEOF_LONG_LONG__": "8", + "__SIZEOF_LONG__": "4", + "__SIZEOF_POINTER__": "8", + "__SIZEOF_PTRDIFF_T__": "8", + "__SIZEOF_SHORT__": "2", + "__SIZEOF_SIZE_T__": "8", + "__SIZEOF_WCHAR_T__": "2", + "__SIZEOF_WINT_T__": "2", + "__SIZE_MAX__": "0xffffffffffffffffULL", + "__SIZE_TYPE__": "long long unsigned int", + "__SIZE_WIDTH__": "64", + "__SSE2_MATH__": "1", + "__SSE2__": "1", + "__SSE3__": "1", + "__SSE_MATH__": "1", + "__SSE__": "1", + "__STDC_HOSTED__": "1", + "__STDC_UTF_16__": "1", + "__STDC_UTF_32__": "1", + "__UINT16_C(c)": "c", + "__UINT16_MAX__": "0xffff", + "__UINT16_TYPE__": "short unsigned int", + "__UINT32_C(c)": "c ## U", + "__UINT32_MAX__": "0xffffffffU", + "__UINT32_TYPE__": "unsigned int", + "__UINT64_C(c)": "c ## ULL", + "__UINT64_MAX__": "0xffffffffffffffffULL", + "__UINT64_TYPE__": "long long unsigned int", + "__UINT8_C(c)": "c", + "__UINT8_MAX__": "0xff", + "__UINT8_TYPE__": "unsigned char", + "__UINTMAX_C(c)": "c ## ULL", + "__UINTMAX_MAX__": "0xffffffffffffffffULL", + "__UINTMAX_TYPE__": "long long unsigned int", + "__UINTPTR_MAX__": "0xffffffffffffffffULL", + "__UINTPTR_TYPE__": "long long unsigned int", + "__UINT_FAST16_MAX__": "0xffff", + "__UINT_FAST16_TYPE__": "short unsigned int", + "__UINT_FAST32_MAX__": "0xffffffffU", + "__UINT_FAST32_TYPE__": "unsigned int", + "__UINT_FAST64_MAX__": "0xffffffffffffffffULL", + "__UINT_FAST64_TYPE__": "long long unsigned int", + "__UINT_FAST8_MAX__": "0xff", + "__UINT_FAST8_TYPE__": "unsigned char", + "__UINT_LEAST16_MAX__": "0xffff", + "__UINT_LEAST16_TYPE__": "short unsigned int", + "__UINT_LEAST32_MAX__": "0xffffffffU", + "__UINT_LEAST32_TYPE__": "unsigned int", + "__UINT_LEAST64_MAX__": "0xffffffffffffffffULL", + "__UINT_LEAST64_TYPE__": "long long unsigned int", + "__UINT_LEAST8_MAX__": "0xff", + "__UINT_LEAST8_TYPE__": "unsigned char", + "__USER_LABEL_PREFIX__": "", + "__WCHAR_MAX__": "0xffff", + "__WCHAR_MIN__": "0", + "__WCHAR_TYPE__": "short unsigned int", + "__WCHAR_UNSIGNED__": "1", + "__WCHAR_WIDTH__": "16", + "__WIN32": "1", + "__WIN32__": "1", + "__WIN64": "1", + "__WIN64__": "1", + "__WINNT": "1", + "__WINNT__": "1", + "__WINT_MAX__": "0xffff", + "__WINT_MIN__": "0", + "__WINT_TYPE__": "short unsigned int", + "__WINT_WIDTH__": "16", + "__amd64": "1", + "__amd64__": "1", + "__cdecl": "__attribute__((__cdecl__))", + "__code_model_medium__": "1", + "__declspec(x)": "__attribute__((x))", + "__fastcall": "__attribute__((__fastcall__))", + "__nocona": "1", + "__nocona__": "1", + "__pic__": "1", + "__stdcall": "__attribute__((__stdcall__))", + "__thiscall": "__attribute__((__thiscall__))", + "__tune_core2__": "1", + "__x86_64": "1", + "__x86_64__": "1", + "_cdecl": "__attribute__((__cdecl__))", + "_fastcall": "__attribute__((__fastcall__))", + "_stdcall": "__attribute__((__stdcall__))", + "_thiscall": "__attribute__((__thiscall__))" + }, + "sys_include_envvar": null, + "sys_include_path": [ + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/x86_64-w64-mingw32", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/backward", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include-fixed", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/include" + ] + } + }, + "language_cxx.command.#": "C:\\MinGW64\\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.EXE -DGNU_COMPILER -DUNITY_UNIT_TEST -DUNITY_INCLUDE_EXEC_TIME -DFAS_ASSERT_LEVEL=2", + "language_cxx.info.#": "Using built-in specs.\nCOLLECT_GCC=C:\\MinGW64\\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.EXE\nCOLLECT_LTO_WRAPPER=C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/8.1.0/lto-wrapper.exe\nTarget: x86_64-w64-mingw32\nConfigured with: ../../../src/gcc-8.1.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64 --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev0, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/lib -L/c/mingw810/prerequisites/x86_64-zlib-static/lib -L/c/mingw810/prerequisites/x86_64-w64-mingw32-static/lib '\nThread model: posix\ngcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) \n", + "linker": { + "library_path": [ + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../lib/", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/", + "C:/MinGW64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../" + ] + }, + "types": { + "char16_t_type": "unsigned short", + "char32_t_type": "unsigned int", + "char_bits": 8, + "double_type": { + "alignof": 8, + "sizeof": 8 + }, + "float_type": { + "alignof": 4, + "sizeof": 4 + }, + "int_type": { + "alignof": 4, + "sizeof": 4 + }, + "long_double_type": { + "alignof": 16, + "sizeof": 16 + }, + "long_long_type": { + "alignof": 8, + "sizeof": 8 + }, + "long_type": { + "alignof": 4, + "sizeof": 4 + }, + "pointer_type": { + "alignof": 8, + "sizeof": 8 + }, + "ptrdiff_t_type": "signed long long", + "short_type": { + "alignof": 2, + "sizeof": 2 + }, + "size_t_type": "unsigned long long", + "wchar_t_type": "unsigned short", + "wint_t_type": "unsigned short" + } + } + }, + "_Format": "1.0", + "_Version": "7.5.2", + "_VersionNum": [ + 7, + 5, + 2, + 11578 + ] +} diff --git a/tests/unit/axivion/link.bat b/tests/unit/axivion/link.bat new file mode 100644 index 00000000..b955b1ce --- /dev/null +++ b/tests/unit/axivion/link.bat @@ -0,0 +1,44 @@ +@REM Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +@REM All rights reserved. +@REM +@REM SPDX-License-Identifier: BSD-3-Clause +@REM +@REM Redistribution and use in source and binary forms, with or without +@REM modification, are permitted provided that the following conditions are met: +@REM +@REM 1. Redistributions of source code must retain the above copyright notice, this +@REM list of conditions and the following disclaimer. +@REM +@REM 2. Redistributions in binary form must reproduce the above copyright notice, +@REM this list of conditions and the following disclaimer in the documentation +@REM and/or other materials provided with the distribution. +@REM +@REM 3. Neither the name of the copyright holder nor the names of its +@REM contributors may be used to endorse or promote products derived from +@REM this software without specific prior written permission. +@REM +@REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +@REM AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +@REM IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +@REM DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +@REM FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +@REM DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +@REM SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +@REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +@REM OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +@REM OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +@REM +@REM We kindly request you to use one or more of the following phrases to refer to +@REM foxBMS in your hardware, software, documentation or advertising materials: +@REM +@REM - "This product uses parts of foxBMS®" +@REM - "This product includes parts of foxBMS®" +@REM - "This product is derived from foxBMS®" + +@SETLOCAL EnableExtensions EnableDelayedExpansion + +@pushd %~dp0..\..\.. + +@tools\utils\cmd\run-python-script.bat %~dp0call_irlink.py %* + +@popd diff --git a/tests/unit/build.json b/tests/unit/build.json new file mode 100644 index 00000000..f50d8411 --- /dev/null +++ b/tests/unit/build.json @@ -0,0 +1,3062 @@ +{ + "src/app/application/algorithm/algorithm.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_algorithm", + "src/app/application/algorithm", + "src/app/application/algorithm/config", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_algorithm/Mockalgorithm_cfg.c", + "build/unit_test/test/mocks/test_algorithm/Mockos.c", + "build/unit_test/test/mocks/test_algorithm/Mocktest_algorithm_stubs.c", + "src/app/application/algorithm/algorithm.c", + "tests/unit/app/application/algorithm/test_algorithm.c", + "build/unit_test/test/runners/test_algorithm_runner.c" + ] + }, + "src/app/application/algorithm/config/algorithm_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_algorithm_cfg", + "src/app/application/algorithm/config", + "src/app/application/algorithm/moving_average", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_algorithm_cfg/Mockdatabase.c", + "build/unit_test/test/mocks/test_algorithm_cfg/Mockmoving_average.c", + "build/unit_test/test/mocks/test_algorithm_cfg/Mockos.c", + "src/app/application/algorithm/config/algorithm_cfg.c", + "tests/unit/app/application/algorithm/config/test_algorithm_cfg.c", + "build/unit_test/test/runners/test_algorithm_cfg_runner.c" + ] + }, + "src/app/application/algorithm/moving_average/moving_average.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_moving_average", + "src/app/application/algorithm/config", + "src/app/application/algorithm/moving_average", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_moving_average/Mockdatabase.c", + "build/unit_test/test/mocks/test_moving_average/Mockos.c", + "src/app/application/algorithm/moving_average/moving_average.c", + "tests/unit/app/application/algorithm/moving_average/test_moving_average.c", + "build/unit_test/test/runners/test_moving_average_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/soc/counting/soc_counting.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soc_counting", + "src/app/application/algorithm/state_estimation", + "src/app/application/algorithm/state_estimation/soc/counting", + "src/app/application/bms", + "src/app/driver/config", + "src/app/driver/contactor", + "src/app/driver/foxmath", + "src/app/driver/fram", + "src/app/driver/sps", + "src/app/task/config", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_soc_counting/Mockbms.c", + "build/unit_test/test/mocks/test_soc_counting/Mockdatabase.c", + "build/unit_test/test/mocks/test_soc_counting/Mockfram.c", + "src/app/application/algorithm/state_estimation/soc/counting/soc_counting.c", + "src/app/driver/foxmath/foxmath.c", + "src/app/application/config/battery_cell_cfg.c", + "tests/unit/app/application/algorithm/state_estimation/soc/counting/test_soc_counting.c", + "build/unit_test/test/runners/test_soc_counting_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/soc/debug/soc_debug.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soc_debug", + "src/app/application/algorithm/state_estimation", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5", + "include", + "..tests/unit/support", + "test/mocks/test_soc_debug" + ], + "sources": [ + "build/unit_test/test/mocks/test_soc_debug/Mockdatabase.c", + "src/app/application/algorithm/state_estimation/soc/debug/soc_debug.c", + "tests/unit/app/application/algorithm/state_estimation/soc/debug/test_soc_debug.c", + "build/unit_test/test/runners/test_soc_debug_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/soc/none/soc_none.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soc_none", + "src/app/application/algorithm/state_estimation", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_soc_none/Mockdatabase.c", + "src/app/application/algorithm/state_estimation/soc/none/soc_none.c", + "tests/unit/app/application/algorithm/state_estimation/soc/none/test_soc_none.c", + "build/unit_test/test/runners/test_soc_none_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/soe/counting/soe_counting.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soe_counting", + "src/app/application/algorithm/state_estimation", + "src/app/application/bms", + "src/app/driver/config", + "src/app/driver/contactor", + "src/app/driver/foxmath", + "src/app/driver/fram", + "src/app/driver/sps", + "src/app/task/config", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_soe_counting/Mockbms.c", + "build/unit_test/test/mocks/test_soe_counting/Mockdatabase.c", + "build/unit_test/test/mocks/test_soe_counting/Mockfram.c", + "src/app/application/algorithm/state_estimation/soe/counting/soe_counting.c", + "src/app/application/config/battery_cell_cfg.c", + "src/app/driver/foxmath/foxmath.c", + "tests/unit/app/application/algorithm/state_estimation/soe/counting/test_soe_counting.c", + "build/unit_test/test/runners/test_soe_counting_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/soe/debug/soe_debug.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soe_debug", + "src/app/application/algorithm/state_estimation", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_soe_debug/Mockdatabase.c", + "src/app/application/algorithm/state_estimation/soe/debug/soe_debug.c", + "tests/unit/app/application/algorithm/state_estimation/soe/debug/test_soe_debug.c", + "build/unit_test/test/runners/test_soe_debug_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/soe/none/soe_none.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soe_none" + ], + "sources": [ + "build/unit_test/test/mocks/test_soe_none/Mockdatabase.c", + "src/app/application/algorithm/state_estimation/soe/none/soe_none.c", + "tests/unit/app/application/algorithm/state_estimation/soe/none/test_soe_none.c", + "build/unit_test/test/runners/test_soe_none_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sof_trapezoid" + ], + "sources": [ + "build/unit_test/test/mocks/test_sof_trapezoid/Mockbms.c", + "build/unit_test/test/mocks/test_sof_trapezoid/Mockdatabase.c", + "build/unit_test/test/mocks/test_sof_trapezoid/Mockfram.c", + "src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid.c", + "tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid.c", + "build/unit_test/test/runners/test_sof_trapezoid_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sof_trapezoid_cfg" + ], + "sources": [ + "src/app/application/algorithm/state_estimation/sof/trapezoid/sof_trapezoid_cfg.c", + "tests/unit/app/application/algorithm/state_estimation/sof/trapezoid/test_sof_trapezoid_cfg.c", + "build/unit_test/test/runners/test_sof_trapezoid_cfg_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/soh/debug/soh_debug.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soh_debug" + ], + "sources": [ + "build/unit_test/test/mocks/test_soh_debug/Mockdatabase.c", + "src/app/application/algorithm/state_estimation/soh/debug/soh_debug.c", + "tests/unit/app/application/algorithm/state_estimation/soh/debug/test_soh_debug.c", + "build/unit_test/test/runners/test_soh_debug_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/soh/none/soh_none.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soh_none" + ], + "sources": [ + "build/unit_test/test/mocks/test_soh_none/Mockdatabase.c", + "src/app/application/algorithm/state_estimation/soh/none/soh_none.c", + "tests/unit/app/application/algorithm/state_estimation/soh/none/test_soh_none.c", + "build/unit_test/test/runners/test_soh_none_runner.c" + ] + }, + "src/app/application/algorithm/state_estimation/state_estimation.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_state_estimation" + ], + "sources": [ + "build/unit_test/test/mocks/test_state_estimation/Mockdatabase.c", + "src/app/application/algorithm/state_estimation/state_estimation.c", + "tests/unit/app/application/algorithm/state_estimation/test_state_estimation.c", + "build/unit_test/test/runners/test_state_estimation_runner.c" + ] + }, + "src/app/application/bal/bal.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_bal" + ], + "sources": [ + "build/unit_test/test/mocks/test_bal/Mockdatabase.c", + "build/unit_test/test/mocks/test_bal/Mockos.c", + "src/app/application/bal/bal.c", + "tests/unit/app/application/bal/test_bal.c", + "build/unit_test/test/runners/test_bal_runner.c" + ] + }, + "src/app/application/bal/history/bal_strategy_history.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_bal_strategy_history" + ], + "sources": [ + "build/unit_test/test/mocks/test_bal_strategy_history/Mockbal_cfg.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockbattery_system_cfg.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockbms.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockdatabase.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockfassert.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockfram.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockio.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockmcu.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockos.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockspi.c", + "build/unit_test/test/mocks/test_bal_strategy_history/Mockstate_estimation.c", + "src/app/application/bal/history/bal_strategy_history.c", + "tests/unit/app/application/bal/history/test_bal_strategy_history.c", + "build/unit_test/test/runners/test_bal_strategy_history_runner.c" + ] + }, + "src/app/application/bal/none/bal_strategy_none.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_bal_strategy_none" + ], + "sources": [ + "build/unit_test/test/mocks/test_bal_strategy_none/Mockbattery_system_cfg.c", + "build/unit_test/test/mocks/test_bal_strategy_none/Mockbms.c", + "build/unit_test/test/mocks/test_bal_strategy_none/Mockdatabase.c", + "build/unit_test/test/mocks/test_bal_strategy_none/Mockfassert.c", + "build/unit_test/test/mocks/test_bal_strategy_none/Mockfram.c", + "build/unit_test/test/mocks/test_bal_strategy_none/Mockio.c", + "build/unit_test/test/mocks/test_bal_strategy_none/Mockmcu.c", + "build/unit_test/test/mocks/test_bal_strategy_none/Mockos.c", + "build/unit_test/test/mocks/test_bal_strategy_none/Mockspi.c", + "src/app/application/bal/none/bal_strategy_none.c", + "tests/unit/app/application/bal/none/test_bal_strategy_none.c", + "build/unit_test/test/runners/test_bal_strategy_none_runner.c" + ] + }, + "src/app/application/bal/voltage/bal_strategy_voltage.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_bal_strategy_voltage" + ], + "sources": [ + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockbal_cfg.c", + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockbattery_system_cfg.c", + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockbms.c", + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockdatabase.c", + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockfassert.c", + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockfram.c", + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockio.c", + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockmcu.c", + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockos.c", + "build/unit_test/test/mocks/test_bal_strategy_voltage/Mockspi.c", + "src/app/application/bal/voltage/bal_strategy_voltage.c", + "tests/unit/app/application/bal/voltage/test_bal_strategy_voltage.c", + "build/unit_test/test/runners/test_bal_strategy_voltage_runner.c" + ] + }, + "src/app/application/bms/bms.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_bms" + ], + "sources": [ + "build/unit_test/test/mocks/test_bms/Mockafe.c", + "build/unit_test/test/mocks/test_bms/Mockbal.c", + "build/unit_test/test/mocks/test_bms/Mockbattery_system_cfg.c", + "build/unit_test/test/mocks/test_bms/Mockcontactor.c", + "build/unit_test/test/mocks/test_bms/Mockdatabase.c", + "build/unit_test/test/mocks/test_bms/Mockdiag.c", + "build/unit_test/test/mocks/test_bms/Mockfassert.c", + "build/unit_test/test/mocks/test_bms/Mockimd.c", + "build/unit_test/test/mocks/test_bms/Mockinterlock.c", + "build/unit_test/test/mocks/test_bms/Mockled.c", + "build/unit_test/test/mocks/test_bms/Mockmeas.c", + "build/unit_test/test/mocks/test_bms/Mockos.c", + "build/unit_test/test/mocks/test_bms/Mockplausibility.c", + "build/unit_test/test/mocks/test_bms/Mocksoa.c", + "src/app/application/bms/bms.c", + "tests/unit/app/application/bms/test_bms.c", + "build/unit_test/test/runners/test_bms_runner.c" + ] + }, + "src/app/application/config/bal_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_bal_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_bal_cfg/Mockos.c", + "src/app/application/config/bal_cfg.c", + "tests/unit/app/application/config/test_bal_cfg.c", + "build/unit_test/test/runners/test_bal_cfg_runner.c" + ] + }, + "src/app/application/config/battery_cell_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_battery_cell_cfg" + ], + "sources": [ + "src/app/application/config/battery_cell_cfg.c", + "tests/unit/app/application/config/test_battery_cell_cfg.c", + "build/unit_test/test/runners/test_battery_cell_cfg_runner.c" + ] + }, + "src/app/application/config/battery_system_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_battery_system_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_battery_system_cfg/Mockdatabase.c", + "src/app/application/config/battery_system_cfg.c", + "tests/unit/app/application/config/test_battery_system_cfg.c", + "build/unit_test/test/runners/test_battery_system_cfg_runner.c" + ] + }, + "src/app/application/config/soa_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soa_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_soa_cfg/Mockbattery_cell_cfg.c", + "build/unit_test/test/mocks/test_soa_cfg/Mockbms.c", + "src/app/application/config/soa_cfg.c", + "tests/unit/app/application/config/test_soa_cfg.c", + "build/unit_test/test/runners/test_soa_cfg_runner.c" + ] + }, + "src/app/application/plausibility/plausibility.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_plausibility" + ], + "sources": [ + "build/unit_test/test/mocks/test_plausibility/Mockdiag.c", + "src/app/application/plausibility/plausibility.c", + "tests/unit/app/application/plausibility/test_plausibility.c", + "build/unit_test/test/runners/test_plausibility_runner.c" + ] + }, + "src/app/application/redundancy/redundancy.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_redundancy" + ], + "sources": [ + "build/unit_test/test/mocks/test_redundancy/Mockbms.c", + "build/unit_test/test/mocks/test_redundancy/Mockdatabase.c", + "build/unit_test/test/mocks/test_redundancy/Mockdatabase_helper.c", + "build/unit_test/test/mocks/test_redundancy/Mockdiag.c", + "build/unit_test/test/mocks/test_redundancy/Mockos.c", + "build/unit_test/test/mocks/test_redundancy/Mockplausibility.c", + "src/app/application/redundancy/redundancy.c", + "tests/unit/app/application/redundancy/test_redundancy.c", + "build/unit_test/test/runners/test_redundancy_runner.c" + ] + }, + "src/app/application/soa/soa.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_soa" + ], + "sources": [ + "build/unit_test/test/mocks/test_soa/Mockbms.c", + "build/unit_test/test/mocks/test_soa/Mockcontactor.c", + "build/unit_test/test/mocks/test_soa/Mockdatabase.c", + "build/unit_test/test/mocks/test_soa/Mockdiag.c", + "build/unit_test/test/mocks/test_soa/Mocksoa_cfg.c", + "src/app/application/soa/soa.c", + "tests/unit/app/application/soa/test_soa.c", + "build/unit_test/test/runners/test_soa_runner.c" + ] + }, + "src/app/driver/adc/adc.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adc", + "src/app/driver/adc", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_adc/MockHL_adc.c", + "build/unit_test/test/mocks/test_adc/Mockdatabase.c", + "build/unit_test/test/mocks/test_adc/Mockfassert.c", + "src/app/driver/adc/adc.c", + "tests/unit/app/driver/adc/test_adc.c", + "build/unit_test/test/runners/test_adc_runner.c" + ] + }, + "src/app/driver/afe/adi/ades1830/adi_ades1830_balancing.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades1830_balancing" + ], + "sources": [ + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockadi_ades183x.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockadi_ades183x_helpers.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockadi_ades183x_pec.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockadi_ades183x_voltages.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockdatabase.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockfassert.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockftask.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockio.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockos.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockpex.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockspi.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mockspi_cfg.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mocktask.c", + "build/unit_test/test/mocks/test_adi_ades1830_balancing/Mocktsi.c", + "src/app/driver/afe/adi/ades1830/adi_ades1830_balancing.c", + "tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_balancing.c", + "build/unit_test/test/runners/test_adi_ades1830_balancing_runner.c" + ] + }, + "src/app/driver/afe/adi/ades1830/adi_ades1830_gpio_voltages.c": { + "defines": [ + "FOXBMS_AFE_DRIVER_ADI_ADES1830=1u" + ], + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades1830_gpio_voltages", + "src/app/application/config", + "src/app/driver/afe/adi/ades1830", + "src/app/driver/afe/adi/common/ades183x", + "src/app/driver/afe/adi/common/ades183x/config", + "src/app/driver/afe/adi/common/ades183x/pec", + "src/app/driver/afe/api", + "src/app/driver/config", + "src/app/driver/dma", + "src/app/driver/io", + "src/app/driver/pex", + "src/app/driver/rtc", + "src/app/driver/spi", + "src/app/driver/ts/api", + "src/app/engine/database", + "src/app/engine/diag", + "src/app/task/config", + "src/app/task/ftask", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_adi_ades1830_gpio_voltages/Mockadi_ades183x_cfg.c", + "build/unit_test/test/mocks/test_adi_ades1830_gpio_voltages/Mockos.c", + "build/unit_test/test/mocks/test_adi_ades1830_gpio_voltages/Mockspi.c", + "src/app/driver/afe/adi/ades1830/adi_ades1830_gpio_voltages.c", + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_helpers.c", + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_buffers.c", + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands.c", + "src/app/driver/afe/adi/common/ades183x/pec/adi_ades183x_pec.c", + "tests/unit/app/driver/afe/adi/ades1830/test_adi_ades1830_gpio_voltages.c", + "build/unit_test/test/runners/test_adi_ades1830_gpio_voltages_runner.c" + ] + }, + "src/app/driver/afe/adi/ades1830/config/adi_ades1830_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades1830_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_adi_ades1830_cfg/Mocktsi.c", + "src/app/driver/afe/adi/ades1830/config/adi_ades1830_cfg.c", + "tests/unit/app/driver/afe/adi/ades1830/config/test_adi_ades1830_cfg.c", + "build/unit_test/test/runners/test_adi_ades1830_cfg_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/adi_ades183x.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/adi_ades183x.c", + "tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x.c", + "build/unit_test/test/runners/test_adi_ades183x_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_buffers.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_buffers" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_buffers.c", + "tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_buffers.c", + "build/unit_test/test/runners/test_adi_ades183x_buffers_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_commands" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands.c", + "tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_commands.c", + "build/unit_test/test/runners/test_adi_ades183x_commands_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands_voltages.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_commands_voltages" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_commands_voltages.c", + "tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_commands_voltages.c", + "build/unit_test/test/runners/test_adi_ades183x_commands_voltages_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_diagnostic_w.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_diagnostic_w" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/_w.c", + "tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_diagnostic_w.c", + "build/unit_test/test/runners/test_adi_ades183x_diagnostic_w_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_helpers.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_helpers" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_helpers.c", + "tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_helpers.c", + "build/unit_test/test/runners/test_adi_ades183x_helpers_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_initialization.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_initialization" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_initialization.c", + "tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_initialization.c", + "build/unit_test/test/runners/test_adi_ades183x_initialization_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_temperatures.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_temperatures" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_temperatures.c", + "tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_temperatures.c", + "build/unit_test/test/runners/test_adi_ades183x_temperatures_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_voltages.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_voltages" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/adi_ades183x_voltages.c", + "tests/unit/app/driver/afe/adi/common/ades183x/test_adi_ades183x_voltages.c", + "build/unit_test/test/runners/test_adi_ades183x_voltages_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_afe" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe.c", + "tests/unit/app/driver/afe/adi/common/ades183x/api/test_adi_ades183x_afe.c", + "build/unit_test/test/runners/test_adi_ades183x_afe_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe_dma.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_afe_dma" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/api/adi_ades183x_afe_dma.c", + "tests/unit/app/driver/afe/adi/common/ades183x/api/test_adi_ades183x_afe_dma.c", + "build/unit_test/test/runners/test_adi_ades183x_afe_dma_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/config/adi_ades183x_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_cfg" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/config/adi_ades183x_cfg.c", + "tests/unit/app/driver/afe/adi/common/ades183x/config/test_adi_ades183x_cfg.c", + "build/unit_test/test/runners/test_adi_ades183x_cfg_runner.c" + ] + }, + "src/app/driver/afe/adi/common/ades183x/pec/adi_ades183x_pec.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_adi_ades183x_pec" + ], + "sources": [ + "src/app/driver/afe/adi/common/ades183x/pec/adi_ades183x_pec.c", + "tests/unit/app/driver/afe/adi/common/ades183x/pec/test_adi_ades183x_pec.c", + "build/unit_test/test/runners/test_adi_ades183x_pec_runner.c" + ] + }, + "src/app/driver/afe/api/afe_plausibility.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_afe_plausibility" + ], + "sources": [ + "build/unit_test/test/mocks/test_afe_plausibility/Mocktsi.c", + "src/app/driver/afe/api/afe_plausibility.c", + "tests/unit/app/driver/afe/api/test_afe_plausibility.c", + "build/unit_test/test/runners/test_afe_plausibility_runner.c" + ] + }, + "src/app/driver/afe/debug/default/api/debug_default_afe.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_debug_default_afe" + ], + "sources": [ + "build/unit_test/test/mocks/test_debug_default_afe/Mockdatabase.c", + "build/unit_test/test/mocks/test_debug_default_afe/Mockdebug_default.c", + "src/app/driver/afe/debug/default/api/debug_default_afe.c", + "tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe.c", + "build/unit_test/test/runners/test_debug_default_afe_runner.c" + ] + }, + "src/app/driver/afe/debug/default/api/debug_default_afe_dma.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_debug_default_afe_dma" + ], + "sources": [ + "build/unit_test/test/mocks/test_debug_default_afe_dma/Mockdebug_default.c", + "build/unit_test/test/mocks/test_debug_default_afe_dma/Mockfassert.c", + "src/app/driver/afe/debug/default/api/debug_default_afe_dma.c", + "tests/unit/app/driver/afe/debug/default/api/test_debug_default_afe_dma.c", + "build/unit_test/test/runners/test_debug_default_afe_dma_runner.c" + ] + }, + "src/app/driver/afe/debug/default/debug_default.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_debug_default" + ], + "sources": [ + "build/unit_test/test/mocks/test_debug_default/Mockdatabase.c", + "build/unit_test/test/mocks/test_debug_default/Mockos.c", + "src/app/driver/afe/debug/default/debug_default.c", + "tests/unit/app/driver/afe/debug/default/test_debug_default.c", + "build/unit_test/test/runners/test_debug_default_runner.c" + ] + }, + "src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ltc_6806_cfg" + ], + "sources": [ + "src/app/driver/afe/ltc/6806/config/ltc_6806_cfg.c", + "tests/unit/app/driver/afe/ltc/6806/config/test_ltc_6806_cfg.c", + "build/unit_test/test/runners/test_ltc_6806_cfg_runner.c" + ] + }, + "src/app/driver/afe/ltc/6806/ltc_6806.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ltc_6806" + ], + "sources": [ + "build/unit_test/test/mocks/test_ltc_6806/Mockafe_plausibility.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockdatabase.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockdiag.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockdma.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockfassert.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockio.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockltc_afe_dma.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockltc_pec.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockos.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockpex.c", + "build/unit_test/test/mocks/test_ltc_6806/Mockspi.c", + "src/app/driver/afe/ltc/6806/ltc_6806.c", + "tests/unit/app/driver/afe/ltc/6806/test_ltc_6806.c", + "build/unit_test/test/runners/test_ltc_6806_runner.c" + ] + }, + "src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ltc_6813-1_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_ltc_6813-1_cfg/Mocktsi.c", + "src/app/driver/afe/ltc/6813-1/config/ltc_6813-1_cfg.c", + "tests/unit/app/driver/afe/ltc/6813-1/config/test_ltc_6813-1_cfg.c", + "build/unit_test/test/runners/test_ltc_6813-1_cfg_runner.c" + ] + }, + "src/app/driver/afe/ltc/6813-1/ltc_6813-1.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ltc_6813-1" + ], + "sources": [ + "build/unit_test/test/mocks/test_ltc_6813-1/Mockafe_plausibility.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockdatabase.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockdiag.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockdma.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockfassert.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockio.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockltc_afe_dma.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockltc_pec.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockos.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockpex.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mockspi.c", + "build/unit_test/test/mocks/test_ltc_6813-1/Mocktsi.c", + "src/app/driver/afe/ltc/6813-1/ltc_6813-1.c", + "tests/unit/app/driver/afe/ltc/6813-1/test_ltc_6813-1.c", + "build/unit_test/test/runners/test_ltc_6813-1_runner.c" + ] + }, + "src/app/driver/afe/ltc/api/ltc_afe.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ltc_afe" + ], + "sources": [ + "build/unit_test/test/mocks/test_ltc_afe/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_ltc_afe/Mockltc.c", + "src/app/driver/afe/ltc/api/ltc_afe.c", + "tests/unit/app/driver/afe/ltc/api/test_ltc_afe.c", + "build/unit_test/test/runners/test_ltc_afe_runner.c" + ] + }, + "src/app/driver/afe/ltc/common/ltc_afe_dma.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ltc_afe_dma" + ], + "sources": [ + "build/unit_test/test/mocks/test_ltc_afe_dma/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_ltc_afe_dma/Mockfassert.c", + "build/unit_test/test/mocks/test_ltc_afe_dma/Mockio.c", + "build/unit_test/test/mocks/test_ltc_afe_dma/Mockltc.c", + "build/unit_test/test/mocks/test_ltc_afe_dma/Mockspi.c", + "src/app/driver/afe/ltc/common/ltc_afe_dma.c", + "tests/unit/app/driver/afe/ltc/common/test_ltc_afe_dma.c", + "build/unit_test/test/runners/test_ltc_afe_dma_runner.c" + ] + }, + "src/app/driver/afe/ltc/common/ltc_pec.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ltc_pec" + ], + "sources": [ + "src/app/driver/afe/ltc/common/ltc_pec.c", + "tests/unit/app/driver/afe/ltc/common/test_ltc_pec.c", + "build/unit_test/test/runners/test_ltc_pec_runner.c" + ] + }, + "src/app/driver/afe/maxim/api/mxm_afe.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_afe" + ], + "sources": [ + "build/unit_test/test/mocks/test_mxm_afe/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_mxm_afe/Mockmxm_17841b.c", + "build/unit_test/test/mocks/test_mxm_afe/Mockmxm_1785x.c", + "build/unit_test/test/mocks/test_mxm_afe/Mockmxm_battery_management.c", + "build/unit_test/test/mocks/test_mxm_afe/Mockmxm_cfg.c", + "build/unit_test/test/mocks/test_mxm_afe/Mockos.c", + "src/app/driver/afe/maxim/api/mxm_afe.c", + "tests/unit/app/driver/afe/maxim/api/test_mxm_afe.c", + "build/unit_test/test/runners/test_mxm_afe_runner.c" + ] + }, + "src/app/driver/afe/maxim/common/config/mxm_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_mxm_cfg/Mockdiag.c", + "build/unit_test/test/mocks/test_mxm_cfg/Mockfassert.c", + "build/unit_test/test/mocks/test_mxm_cfg/Mockio.c", + "build/unit_test/test/mocks/test_mxm_cfg/Mockspi.c", + "build/unit_test/test/mocks/test_mxm_cfg/Mockspi_cfg.c", + "src/app/driver/afe/maxim/common/config/mxm_cfg.c", + "tests/unit/app/driver/afe/maxim/common/config/test_mxm_cfg.c", + "build/unit_test/test/runners/test_mxm_cfg_runner.c" + ] + }, + "src/app/driver/afe/maxim/common/mxm_17841b.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_17841b" + ], + "sources": [ + "build/unit_test/test/mocks/test_mxm_17841b/Mockfassert.c", + "build/unit_test/test/mocks/test_mxm_17841b/Mockmxm_cfg.c", + "build/unit_test/test/mocks/test_mxm_17841b/Mockos.c", + "src/app/driver/afe/maxim/common/mxm_17841b.c", + "tests/unit/app/driver/afe/maxim/common/test_mxm_17841b.c", + "build/unit_test/test/runners/test_mxm_17841b_runner.c" + ] + }, + "src/app/driver/afe/maxim/common/mxm_1785x.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_1785x" + ], + "sources": [ + "build/unit_test/test/mocks/test_mxm_1785x/Mockafe_plausibility.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockdatabase.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockdiag.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockfassert.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockmxm_17841b.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockmxm_41b_register_map.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockmxm_battery_management.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockmxm_cfg.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockmxm_crc8.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockmxm_registry.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mockos.c", + "build/unit_test/test/mocks/test_mxm_1785x/Mocktsi.c", + "src/app/driver/afe/maxim/common/mxm_1785x.c", + "tests/unit/app/driver/afe/maxim/common/test_mxm_1785x.c", + "build/unit_test/test/runners/test_mxm_1785x_runner.c" + ] + }, + "src/app/driver/afe/maxim/common/mxm_1785x_tools.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_1785x_tools" + ], + "sources": [ + "build/unit_test/test/mocks/test_mxm_1785x_tools/Mockfassert.c", + "build/unit_test/test/mocks/test_mxm_1785x_tools/Mockmxm_cfg.c", + "src/app/driver/afe/maxim/common/mxm_1785x_tools.c", + "tests/unit/app/driver/afe/maxim/common/test_mxm_1785x_tools.c", + "build/unit_test/test/runners/test_mxm_1785x_tools_runner.c" + ] + }, + "src/app/driver/afe/maxim/common/mxm_afe_dma.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_afe_dma" + ], + "sources": [ + "build/unit_test/test/mocks/test_mxm_afe_dma/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_mxm_afe_dma/Mockfassert.c", + "src/app/driver/afe/maxim/common/mxm_afe_dma.c", + "tests/unit/app/driver/afe/maxim/common/test_mxm_afe_dma.c", + "build/unit_test/test/runners/test_mxm_afe_dma_runner.c" + ] + }, + "src/app/driver/afe/maxim/common/mxm_battery_management.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_battery_management" + ], + "sources": [ + "build/unit_test/test/mocks/test_mxm_battery_management/Mockdiag.c", + "build/unit_test/test/mocks/test_mxm_battery_management/Mockfassert.c", + "build/unit_test/test/mocks/test_mxm_battery_management/Mockmxm_17841b.c", + "build/unit_test/test/mocks/test_mxm_battery_management/Mockmxm_41b_register_map.c", + "build/unit_test/test/mocks/test_mxm_battery_management/Mockmxm_cfg.c", + "build/unit_test/test/mocks/test_mxm_battery_management/Mockmxm_crc8.c", + "build/unit_test/test/mocks/test_mxm_battery_management/Mockos.c", + "src/app/driver/afe/maxim/common/mxm_battery_management.c", + "tests/unit/app/driver/afe/maxim/common/test_mxm_battery_management.c", + "build/unit_test/test/runners/test_mxm_battery_management_runner.c" + ] + }, + "src/app/driver/afe/maxim/common/mxm_bitextract.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_bitextract" + ], + "sources": [ + "src/app/driver/afe/maxim/common/mxm_bitextract.c", + "tests/unit/app/driver/afe/maxim/common/test_mxm_bitextract.c", + "build/unit_test/test/runners/test_mxm_bitextract_runner.c" + ] + }, + "src/app/driver/afe/maxim/common/mxm_crc8.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_crc8" + ], + "sources": [ + "src/app/driver/afe/maxim/common/mxm_crc8.c", + "tests/unit/app/driver/afe/maxim/common/test_mxm_crc8.c", + "build/unit_test/test/runners/test_mxm_crc8_runner.c" + ] + }, + "src/app/driver/afe/maxim/common/mxm_registry.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_registry" + ], + "sources": [ + "build/unit_test/test/mocks/test_mxm_registry/Mockfassert.c", + "build/unit_test/test/mocks/test_mxm_registry/Mockmxm_1785x.c", + "build/unit_test/test/mocks/test_mxm_registry/Mockmxm_basic_defines.c", + "src/app/driver/afe/maxim/common/mxm_registry.c", + "tests/unit/app/driver/afe/maxim/common/test_mxm_registry.c", + "build/unit_test/test/runners/test_mxm_registry_runner.c" + ] + }, + "src/app/driver/afe/maxim/max17852/mxm_17852.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mxm_17852" + ], + "sources": [ + "build/unit_test/test/mocks/test_mxm_17852/Mockafe_plausibility.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockdatabase.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockdiag.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockfassert.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockmxm_17841b.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockmxm_41b_register_map.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockmxm_battery_management.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockmxm_cfg.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockmxm_crc8.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockmxm_registry.c", + "build/unit_test/test/mocks/test_mxm_17852/Mockos.c", + "build/unit_test/test/mocks/test_mxm_17852/Mocktsi.c", + "src/app/driver/afe/maxim/max17852/mxm_17852.c", + "tests/unit/app/driver/afe/maxim/max17852/test_mxm_17852.c", + "build/unit_test/test/runners/test_mxm_17852_runner.c" + ] + }, + "src/app/driver/afe/nxp/api/nxp_afe.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_nxp_afe" + ], + "sources": [ + "build/unit_test/test/mocks/test_nxp_afe/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_nxp_afe/Mocknxp_afe.c", + "src/app/driver/afe/nxp/api/nxp_afe.c", + "tests/unit/app/driver/afe/nxp/api/test_nxp_afe.c", + "build/unit_test/test/runners/test_nxp_afe_runner.c" + ] + }, + "src/app/driver/afe/nxp/mc33775a/api/nxp_mc33775a_afe.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_nxp_mc33775a_afe" + ], + "sources": [ + "build/unit_test/test/mocks/test_nxp_mc33775a_afe/Mockafe_dma.c", + "build/unit_test/test/mocks/test_nxp_mc33775a_afe/Mockdma.c", + "build/unit_test/test/mocks/test_nxp_mc33775a_afe/Mocknxp_mc33775a.c", + "build/unit_test/test/mocks/test_nxp_mc33775a_afe/Mockos.c", + "build/unit_test/test/mocks/test_nxp_mc33775a_afe/Mockpex.c", + "src/app/driver/afe/nxp/mc33775a/api/nxp_mc33775a_afe.c", + "tests/unit/app/driver/afe/nxp/mc33775a/api/test_nxp_mc33775a_afe.c", + "build/unit_test/test/runners/test_nxp_mc33775a_afe_runner.c" + ] + }, + "src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_nxp_mc33775a_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_nxp_mc33775a_cfg/Mocktsi.c", + "src/app/driver/afe/nxp/mc33775a/config/nxp_mc33775a_cfg.c", + "tests/unit/app/driver/afe/nxp/mc33775a/config/test_nxp_mc33775a_cfg.c", + "build/unit_test/test/runners/test_nxp_mc33775a_cfg_runner.c" + ] + }, + "src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_nxp_afe_dma" + ], + "sources": [ + "build/unit_test/test/mocks/test_nxp_afe_dma/Mockdma.c", + "build/unit_test/test/mocks/test_nxp_afe_dma/Mockio.c", + "build/unit_test/test/mocks/test_nxp_afe_dma/Mockmcu.c", + "build/unit_test/test/mocks/test_nxp_afe_dma/Mocknxp_mc33775a-ll.c", + "build/unit_test/test/mocks/test_nxp_afe_dma/Mocknxp_mc33775a.c", + "build/unit_test/test/mocks/test_nxp_afe_dma/Mockos.c", + "build/unit_test/test/mocks/test_nxp_afe_dma/Mockspi.c", + "build/unit_test/test/mocks/test_nxp_afe_dma/Mocktask.c", + "src/app/driver/afe/nxp/mc33775a/nxp_afe_dma.c", + "tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_afe_dma.c", + "build/unit_test/test/runners/test_nxp_afe_dma_runner.c" + ] + }, + "src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_nxp_mc33775a-ll" + ], + "sources": [ + "build/unit_test/test/mocks/test_nxp_mc33775a-ll/Mockdma.c", + "build/unit_test/test/mocks/test_nxp_mc33775a-ll/Mockio.c", + "build/unit_test/test/mocks/test_nxp_mc33775a-ll/Mockmcu.c", + "build/unit_test/test/mocks/test_nxp_mc33775a-ll/Mockos.c", + "build/unit_test/test/mocks/test_nxp_mc33775a-ll/Mockspi.c", + "build/unit_test/test/mocks/test_nxp_mc33775a-ll/Mocktask.c", + "src/app/driver/afe/nxp/mc33775a/nxp_mc33775a-ll.c", + "tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a-ll.c", + "build/unit_test/test/runners/test_nxp_mc33775a-ll_runner.c" + ] + }, + "src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_nxp_mc33775a" + ], + "sources": [ + "build/unit_test/test/mocks/test_nxp_mc33775a/MockHL_gio.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/MockHL_system.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mockafe_dma.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mockdatabase.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mockdiag.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mockftask.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mockio.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mockmcu.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mocknxp_mc33775a-ll.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mocknxp_mc33775a_cfg.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mockos.c", + "build/unit_test/test/mocks/test_nxp_mc33775a/Mockspi.c", + "src/app/driver/afe/nxp/mc33775a/nxp_mc33775a.c", + "tests/unit/app/driver/afe/nxp/mc33775a/test_nxp_mc33775a.c", + "build/unit_test/test/runners/test_nxp_mc33775a_runner.c" + ] + }, + "src/app/driver/afe/nxp/mc33775a/vendor/uc_msg_t.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_uc_msg_t" + ], + "sources": [ + "src/app/driver/afe/nxp/mc33775a/vendor/uc_msg_t.c", + "tests/unit/app/driver/afe/nxp/mc33775a/vendor/test_uc_msg_t.c", + "None" + ] + }, + "src/app/driver/afe/ti/api/ti_afe.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ti_afe" + ], + "sources": [ + "src/app/driver/afe/ti/api/ti_afe.c", + "tests/unit/app/driver/afe/ti/api/test_ti_afe.c", + "build/unit_test/test/runners/test_ti_afe_runner.c" + ] + }, + "src/app/driver/afe/ti/common/api/ti_bq79xxx_afe_dma.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ti_bq79xxx_afe_dma" + ], + "sources": [ + "build/unit_test/test/mocks/test_ti_bq79xxx_afe_dma/Mockdma.c", + "build/unit_test/test/mocks/test_ti_bq79xxx_afe_dma/Mockio.c", + "build/unit_test/test/mocks/test_ti_bq79xxx_afe_dma/Mockmcu.c", + "build/unit_test/test/mocks/test_ti_bq79xxx_afe_dma/Mockos.c", + "build/unit_test/test/mocks/test_ti_bq79xxx_afe_dma/Mockspi.c", + "build/unit_test/test/mocks/test_ti_bq79xxx_afe_dma/Mocktask.c", + "src/app/driver/afe/ti/common/api/ti_bq79xxx_afe_dma.c", + "tests/unit/app/driver/afe/ti/common/api/test_ti_bq79xxx_afe_dma.c", + "build/unit_test/test/runners/test_ti_bq79xxx_afe_dma_runner.c" + ] + }, + "src/app/driver/afe/ti/dummy/api/ti_dummy_afe.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ti_dummy_afe" + ], + "sources": [ + "src/app/driver/afe/ti/dummy/api/ti_dummy_afe.c", + "tests/unit/app/driver/afe/ti/dummy/api/test_ti_dummy_afe.c", + "build/unit_test/test/runners/test_ti_dummy_afe_runner.c" + ] + }, + "src/app/driver/afe/ti/dummy/ti_dummy.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ti_dummy" + ], + "sources": [ + "src/app/driver/afe/ti/dummy/ti_dummy.c", + "tests/unit/app/driver/afe/ti/dummy/test_ti_dummy.c", + "build/unit_test/test/runners/test_ti_dummy_runner.c" + ] + }, + "src/app/driver/can/can.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can" + ], + "sources": [ + "build/unit_test/test/mocks/test_can/MockHL_can.c", + "build/unit_test/test/mocks/test_can/Mockcan_cfg.c", + "build/unit_test/test/mocks/test_can/Mockdatabase.c", + "build/unit_test/test/mocks/test_can/Mockdiag.c", + "build/unit_test/test/mocks/test_can/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can/Mockftask.c", + "build/unit_test/test/mocks/test_can/Mockimd.c", + "build/unit_test/test/mocks/test_can/Mockio.c", + "build/unit_test/test/mocks/test_can/Mockmcu.c", + "build/unit_test/test/mocks/test_can/Mockos.c", + "build/unit_test/test/mocks/test_can/Mockpex.c", + "build/unit_test/test/mocks/test_can/Mockqueue.c", + "build/unit_test/test/mocks/test_can/Mocktest_can_mpu_prototype_queue_create_stub.c", + "src/app/driver/can/can.c", + "tests/unit/app/driver/can/test_can.c", + "build/unit_test/test/runners/test_can_runner.c" + ] + }, + "src/app/driver/can/cbs/can_helper.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_helper" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_helper/Mockcan.c", + "build/unit_test/test/mocks/test_can_helper/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_helper/Mockdiag.c", + "build/unit_test/test/mocks/test_can_helper/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_helper/Mockimd.c", + "build/unit_test/test/mocks/test_can_helper/Mockos.c", + "src/app/driver/can/cbs/can_helper.c", + "tests/unit/app/driver/can/cbs/test_can_helper.c", + "build/unit_test/test/runners/test_can_helper_runner.c" + ] + }, + "src/app/driver/can/cbs/rx/can_cbs_rx_aerosol-sensor.c": { + "include": [ + "build/unit_test/include", + "build_unit_test/test/mocks/test_can_cbs_rx_aerosol-sensor" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_rx_aerosol-sensor/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_rx_aerosol-sensor/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_rx_aerosol-sensor/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_rx_aerosol-sensor/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_rx_aerosol-sensor/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_rx_aerosol-sensor/Mockos.c", + "src/app/driver/can/cbs/rx/can_cbs_rx_aerosol-sensor.c", + "test/unit/app/driver/can/cbs/rx/test_can_cbs_rx_aerosol-sensor.c", + "build_unit_test/test/runners/test_can_cbs_rx_aerosol-sensor_runner.c" + ] + }, + "src/app/driver/can/cbs/rx/can_cbs_rx_bms-state-request.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mockbal.c", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mockbal_cfg.c", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mockbms_cfg.c", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mockos.c", + "build/unit_test/test/mocks/test_can_cbs_rx_bms-state-request/Mocksys_mon.c", + "src/app/driver/can/cbs/rx/can_cbs_rx_bms-state-request.c", + "tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_bms-state-request.c", + "build/unit_test/test/runners/test_can_cbs_rx_bms-state-request_runner.c" + ] + }, + "src/app/driver/can/cbs/rx/can_cbs_rx_current-sensor.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_rx_current-sensor" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_rx_current-sensor/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_rx_current-sensor/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_rx_current-sensor/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_rx_current-sensor/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_rx_current-sensor/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_rx_current-sensor/Mockos.c", + "src/app/driver/can/cbs/rx/can_cbs_rx_current-sensor.c", + "tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_current-sensor.c", + "build/unit_test/test/runners/test_can_cbs_rx_current-sensor_runner.c" + ] + }, + "src/app/driver/can/cbs/rx/can_cbs_rx_debug.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_rx_debug" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockcan_cbs_tx_debug-response.c", + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockcan_cbs_tx_unsupported-message.c", + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockfram.c", + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockos.c", + "build/unit_test/test/mocks/test_can_cbs_rx_debug/Mockreset.c", + "src/app/driver/can/cbs/rx/can_cbs_rx_debug.c", + "tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_debug.c", + "build/unit_test/test/runners/test_can_cbs_rx_debug_runner.c" + ] + }, + "src/app/driver/can/cbs/rx/can_cbs_rx_imd-info.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-info" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_rx_imd-info/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-info/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-info/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-info/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-info/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-info/Mockos.c", + "src/app/driver/can/cbs/rx/can_cbs_rx_imd-info.c", + "tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-info.c", + "build/unit_test/test/runners/test_can_cbs_rx_imd-info_runner.c" + ] + }, + "src/app/driver/can/cbs/rx/can_cbs_rx_imd-response.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-response" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_rx_imd-response/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-response/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-response/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-response/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-response/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_rx_imd-response/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_rx_imd-response.c", + "tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-response.c", + "build/unit_test/test/runners/test_can_cbs_rx_imd-response_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_bms-state-details.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_bms_state" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state-details/Mockbms.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state-details/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state-details/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state-details/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state-details/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state-details/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state-details/Mockos.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state-details/Mocksys_mon.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_bms-state-details.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state-details.c", + "build/unit_test/test/runners/test_can_cbs_tx_bms-state-details_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_bms-state.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_bms_state" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state/Mockbms.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state/Mockos.c", + "build/unit_test/test/mocks/test_can_cbs_tx_bms-state/Mocksys_mon.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_bms-state.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_bms-state.c", + "build/unit_test/test/runners/test_can_cbs_tx_bms-state_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_cell-temperatures.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-temperatures" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_cell-temperatures/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-temperatures/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-temperatures/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-temperatures/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-temperatures/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-temperatures/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_cell-temperatures.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-temperatures.c", + "build/unit_test/test/runners/test_can_cbs_tx_cell-temperatures_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_cell-voltages.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-voltages" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_cell-voltages/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-voltages/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-voltages/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-voltages/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-voltages/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_cell-voltages/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_cell-voltages.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_cell-voltages.c", + "build/unit_test/test/runners/test_can_cbs_tx_cell-voltages_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_crash-dump" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_crash-dump/Mockcan.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_crash-dump.c", + "build/unit_test/test/runners/test_can_cbs_tx_crash-dump_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-response" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_debug-response/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-response/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-response/Mockrtc.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_debug-response.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-response.c", + "build/unit_test/test/runners/test_can_cbs_tx_debug-response_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-unsupported-multiplexer-values" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_debug-unsupported-multiplexer-values/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-unsupported-multiplexer-values/Mockcan_helper.c", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-unsupported-multiplexer-values/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-unsupported-multiplexer-values/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-unsupported-multiplexer-values/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-unsupported-multiplexer-values/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_debug-unsupported-multiplexer-values/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_debug-unsupported-multiplexer-values.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_debug-unsupported-multiplexer-values.c", + "build/unit_test/test/runners/test_can_cbs_tx_debug-unsupported-multiplexer-values_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_imd-request.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_imd-request" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_imd-request/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_imd-request/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_imd-request/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_imd-request/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_imd-request/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_imd-request/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_imd-request.c", + "tests/unit/app/driver/can/cbs/rx/test_can_cbs_tx_imd-request.c", + "build/unit_test/test/runners/test_can_cbs_tx_imd-request_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-limits.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-limits" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_pack-limits/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-limits/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-limits/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-limits/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-limits/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-limits/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-limits.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-limits.c", + "build/unit_test/test/runners/test_can_cbs_tx_pack-limits_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-minimum-maximum-values.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-minimum-maximum-values" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_pack-minimum-maximum-values/Mockbms.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-minimum-maximum-values/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-minimum-maximum-values/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-minimum-maximum-values/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-minimum-maximum-values/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-minimum-maximum-values/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-minimum-maximum-values/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-minimum-maximum-values.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-minimum-maximum-values.c", + "build/unit_test/test/runners/test_can_cbs_tx_pack-minimum-maximum-values_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-state-estimation.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-state-estimation" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_pack-state-estimation/Mockbms.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-state-estimation/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-state-estimation/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-state-estimation/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-state-estimation/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-state-estimation/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-state-estimation/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-state-estimation.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-state-estimation.c", + "build/unit_test/test/runners/test_can_cbs_tx_pack-state-estimation_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p0.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values-p0" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values-p0/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values-p0/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values-p0/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values-p0/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values-p0/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values-p0/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p0.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values-p0.c", + "build/unit_test/test/runners/test_can_cbs_tx_pack-values-p0_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p1.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_pack-values/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_pack-values-p1.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_pack-values.c", + "build/unit_test/test/runners/test_can_cbs_tx_pack-values_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_string-minimum-maximum-values.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_string-minimum-maximum-values" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_string-minimum-maximum-values/Mockbms.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-minimum-maximum-values/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-minimum-maximum-values/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-minimum-maximum-values/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-minimum-maximum-values/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-minimum-maximum-values/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-minimum-maximum-values/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_string-minimum-maximum-values.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-minimum-maximum-values.c", + "build/unit_test/test/runners/test_can_cbs_tx_string-minimum-maximum-values_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_string-state-estimation.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state-estimation" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_string-state-estimation/Mockbms.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state-estimation/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state-estimation/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state-estimation/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state-estimation/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state-estimation/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state-estimation/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_string-state-estimation.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state-estimation.c", + "build/unit_test/test/runners/test_can_cbs_tx_string-state-estimation_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_string-state.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_string-state/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-state/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_string-state.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-state.c", + "build/unit_test/test/runners/test_can_cbs_tx_string-state_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p0.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values-p0" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_string-values-p0/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values-p0/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values-p0/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values-p0/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values-p0/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values-p0/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p0.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values-p0.c", + "build/unit_test/test/runners/test_can_cbs_tx_string-values-p0_runner.c" + ] + }, + "src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p1.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cbs_tx_string-values/Mockcan.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values/Mockimd.c", + "build/unit_test/test/mocks/test_can_cbs_tx_string-values/Mockos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_string-values-p1.c", + "tests/unit/app/driver/can/cbs/tx/test_can_cbs_tx_string-values.c", + "build/unit_test/test/runners/test_can_cbs_tx_string-values_runner.c" + ] + }, + "src/app/driver/checksum/checksum.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_checksum" + ], + "sources": [ + "src/app/driver/checksum/checksum.c", + "tests/unit/app/driver/checksum/test_checksum.c", + "build/unit_test/test/runners/test_checksum_runner.c" + ] + }, + "src/app/driver/config/can_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cfg/Mockcan.c", + "build/unit_test/test/mocks/test_can_cfg/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cfg/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cfg/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cfg/Mockftask.c", + "build/unit_test/test/mocks/test_can_cfg/Mockimd.c", + "build/unit_test/test/mocks/test_can_cfg/Mockmpu_prototypes.c", + "build/unit_test/test/mocks/test_can_cfg/Mockos.c", + "src/app/driver/config/can_cfg.c", + "tests/unit/app/driver/config/test_can_cfg.c", + "build/unit_test/test/runners/test_can_cfg_runner.c" + ] + }, + "src/app/driver/config/can_cfg_rx.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cfg_rx" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cfg_rx/Mockcan.c", + "build/unit_test/test/mocks/test_can_cfg_rx/Mockcan_cbs_rx.c", + "build/unit_test/test/mocks/test_can_cfg_rx/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cfg_rx/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cfg_rx/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cfg_rx/Mockftask.c", + "build/unit_test/test/mocks/test_can_cfg_rx/Mockimd.c", + "build/unit_test/test/mocks/test_can_cfg_rx/Mockmpu_prototypes.c", + "build/unit_test/test/mocks/test_can_cfg_rx/Mockos.c", + "src/app/driver/config/can_cfg_rx.c", + "tests/unit/app/driver/config/test_can_cfg_rx.c", + "build/unit_test/test/runners/test_can_cfg_rx_runner.c" + ] + }, + "src/app/driver/config/can_cfg_tx.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_can_cfg_tx" + ], + "sources": [ + "build/unit_test/test/mocks/test_can_cfg_tx/Mockcan.c", + "build/unit_test/test/mocks/test_can_cfg_tx/Mockcan_cbs_tx.c", + "build/unit_test/test/mocks/test_can_cfg_tx/Mockdatabase.c", + "build/unit_test/test/mocks/test_can_cfg_tx/Mockdiag.c", + "build/unit_test/test/mocks/test_can_cfg_tx/Mockfoxmath.c", + "build/unit_test/test/mocks/test_can_cfg_tx/Mockftask.c", + "build/unit_test/test/mocks/test_can_cfg_tx/Mockimd.c", + "build/unit_test/test/mocks/test_can_cfg_tx/Mockmpu_prototypes.c", + "build/unit_test/test/mocks/test_can_cfg_tx/Mockos.c", + "src/app/driver/config/can_cfg_tx.c", + "tests/unit/app/driver/config/test_can_cfg_tx.c", + "build/unit_test/test/runners/test_can_cfg_tx_runner.c" + ] + }, + "src/app/driver/config/contactor_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_contactor_cfg" + ], + "sources": [ + "src/app/driver/config/contactor_cfg.c", + "tests/unit/app/driver/config/test_contactor_cfg.c", + "build/unit_test/test/runners/test_contactor_cfg_runner.c" + ] + }, + "src/app/driver/config/dma_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_dma_cfg" + ], + "sources": [ + "src/app/driver/config/dma_cfg.c", + "tests/unit/app/driver/config/test_dma_cfg.c", + "build/unit_test/test/runners/test_dma_cfg_runner.c" + ] + }, + "src/app/driver/config/fram_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_fram_cfg" + ], + "sources": [ + "src/app/driver/config/fram_cfg.c", + "tests/unit/app/driver/config/test_fram_cfg.c", + "build/unit_test/test/runners/test_fram_cfg_runner.c" + ] + }, + "src/app/driver/config/pex_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_pex_cfg" + ], + "sources": [ + "src/app/driver/config/pex_cfg.c", + "tests/unit/app/driver/config/test_pex_cfg.c", + "build/unit_test/test/runners/test_pex_cfg_runner.c" + ] + }, + "src/app/driver/config/spi_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_spi_cfg" + ], + "sources": [ + "src/app/driver/config/spi_cfg.c", + "tests/unit/app/driver/config/test_spi_cfg.c", + "build/unit_test/test/runners/test_spi_cfg_runner.c" + ] + }, + "src/app/driver/config/sps_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sps_cfg" + ], + "sources": [ + "src/app/driver/config/sps_cfg.c", + "tests/unit/app/driver/config/test_sps_cfg.c", + "build/unit_test/test/runners/test_sps_cfg_runner.c" + ] + }, + "src/app/driver/contactor/contactor.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_contactor" + ], + "sources": [ + "build/unit_test/test/mocks/test_contactor/Mockcontactor_cfg.c", + "build/unit_test/test/mocks/test_contactor/Mockdiag.c", + "build/unit_test/test/mocks/test_contactor/Mockfassert.c", + "build/unit_test/test/mocks/test_contactor/Mockio.c", + "build/unit_test/test/mocks/test_contactor/Mockmcu.c", + "build/unit_test/test/mocks/test_contactor/Mocksps.c", + "build/unit_test/test/mocks/test_contactor/Mocksps_cfg.c", + "src/app/driver/contactor/contactor.c", + "tests/unit/app/driver/contactor/test_contactor.c", + "build/unit_test/test/runners/test_contactor_runner.c" + ] + }, + "src/app/driver/crc/crc.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_crc", + "src/app/driver/crc", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_crc/Mockfassert.c", + "src/app/driver/crc/crc.c", + "tests/unit/app/driver/crc/test_crc.c", + "build/unit_test/test/runners/test_crc_runner.c" + ] + }, + "src/app/driver/dma/dma.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_dma" + ], + "sources": [ + "build/unit_test/test/mocks/test_dma/MockHL_i2c.c", + "build/unit_test/test/mocks/test_dma/MockHL_spi.c", + "build/unit_test/test/mocks/test_dma/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_dma/Mockafe_dma.c", + "build/unit_test/test/mocks/test_dma/Mocki2c.c", + "build/unit_test/test/mocks/test_dma/Mockio.c", + "build/unit_test/test/mocks/test_dma/Mockspi.c", + "build/unit_test/test/mocks/test_dma/Mocktask.c", + "src/app/driver/dma/dma.c", + "tests/unit/app/driver/dma/test_dma.c", + "build/unit_test/test/runners/test_dma_runner.c" + ] + }, + "src/app/driver/foxmath/foxmath.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_foxmath", + "src/app/driver/foxmath", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "src/app/driver/foxmath/foxmath.c", + "tests/unit/app/driver/foxmath/test_foxmath.c", + "build/unit_test/test/runners/test_foxmath_runner.c" + ] + }, + "src/app/driver/fram/fram.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_fram" + ], + "sources": [ + "build/unit_test/test/mocks/test_fram/MockHL_spi.c", + "build/unit_test/test/mocks/test_fram/Mockcrc.c", + "build/unit_test/test/mocks/test_fram/Mockdiag.c", + "build/unit_test/test/mocks/test_fram/Mockio.c", + "build/unit_test/test/mocks/test_fram/Mockmcu.c", + "build/unit_test/test/mocks/test_fram/Mockspi.c", + "src/app/driver/fram/fram.c", + "tests/unit/app/driver/fram/test_fram.c", + "build/unit_test/test/runners/test_fram_runner.c" + ] + }, + "src/app/driver/htsensor/htsensor.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_htsensor" + ], + "sources": [ + "build/unit_test/test/mocks/test_htsensor/MockHL_i2c.c", + "build/unit_test/test/mocks/test_htsensor/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_htsensor/Mockdatabase.c", + "build/unit_test/test/mocks/test_htsensor/Mocki2c.c", + "build/unit_test/test/mocks/test_htsensor/Mockos.c", + "src/app/driver/htsensor/htsensor.c", + "tests/unit/app/driver/htsensor/test_htsensor.c", + "build/unit_test/test/runners/test_htsensor_runner.c" + ] + }, + "src/app/driver/i2c/i2c.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_i2c" + ], + "sources": [ + "build/unit_test/test/mocks/test_i2c/MockHL_i2c.c", + "build/unit_test/test/mocks/test_i2c/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_i2c/Mockmcu.c", + "build/unit_test/test/mocks/test_i2c/Mockos.c", + "build/unit_test/test/mocks/test_i2c/Mocktask.c", + "src/app/driver/i2c/i2c.c", + "tests/unit/app/driver/i2c/test_i2c.c", + "build/unit_test/test/runners/test_i2c_runner.c" + ] + }, + "src/app/driver/imd/bender/ir155/bender_ir155.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_bender_ir155" + ], + "sources": [ + "build/unit_test/test/mocks/test_bender_ir155/Mockbender_ir155_helper.c", + "build/unit_test/test/mocks/test_bender_ir155/Mockdatabase.c", + "build/unit_test/test/mocks/test_bender_ir155/Mockdiag.c", + "build/unit_test/test/mocks/test_bender_ir155/Mockfram.c", + "build/unit_test/test/mocks/test_bender_ir155/Mockio.c", + "build/unit_test/test/mocks/test_bender_ir155/Mockos.c", + "src/app/driver/imd/bender/ir155/bender_ir155.c", + "tests/unit/app/driver/imd/bender/ir155/test_bender_ir155.c", + "build/unit_test/test/runners/test_bender_ir155_runner.c" + ] + }, + "src/app/driver/imd/bender/ir155/bender_ir155_helper.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_bender_ir155_helper" + ], + "sources": [ + "build/unit_test/test/mocks/test_bender_ir155_helper/Mockfram.c", + "build/unit_test/test/mocks/test_bender_ir155_helper/Mockio.c", + "build/unit_test/test/mocks/test_bender_ir155_helper/Mockpwm.c", + "src/app/driver/imd/bender/ir155/bender_ir155_helper.c", + "tests/unit/app/driver/imd/bender/ir155/test_bender_ir155_helper.c", + "build/unit_test/test/runners/test_bender_ir155_helper_runner.c" + ] + }, + "src/app/driver/imd/bender/iso165c/bender_iso165c.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_bender_iso165c" + ], + "sources": [ + "build/unit_test/test/mocks/test_bender_iso165c/Mockcan.c", + "build/unit_test/test/mocks/test_bender_iso165c/Mockcan_cfg.c", + "build/unit_test/test/mocks/test_bender_iso165c/Mockdatabase.c", + "build/unit_test/test/mocks/test_bender_iso165c/Mockdiag.c", + "build/unit_test/test/mocks/test_bender_iso165c/Mockftask.c", + "build/unit_test/test/mocks/test_bender_iso165c/Mockio.c", + "build/unit_test/test/mocks/test_bender_iso165c/Mockmcu.c", + "build/unit_test/test/mocks/test_bender_iso165c/Mockmpu_prototypes.c", + "build/unit_test/test/mocks/test_bender_iso165c/Mockos.c", + "src/app/driver/imd/bender/iso165c/bender_iso165c.c", + "tests/unit/app/driver/imd/bender/iso165c/test_bender_iso165c.c", + "build/unit_test/test/runners/test_bender_iso165c_runner.c" + ] + }, + "src/app/driver/imd/imd.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_imd" + ], + "sources": [ + "build/unit_test/test/mocks/test_imd/Mockdatabase.c", + "build/unit_test/test/mocks/test_imd/Mockdiag.c", + "build/unit_test/test/mocks/test_imd/Mockos.c", + "src/app/driver/imd/imd.c", + "tests/unit/app/driver/imd/test_imd.c", + "build/unit_test/test/runners/test_imd_runner.c" + ] + }, + "src/app/driver/imd/none/no-imd.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_no-imd" + ], + "sources": [ + "build/unit_test/test/mocks/test_no-imd/Mockdatabase.c", + "src/app/driver/imd/none/no-imd.c", + "tests/unit/app/driver/imd/none/test_no-imd.c", + "build/unit_test/test/runners/test_no-imd_runner.c" + ] + }, + "src/app/driver/interlock/interlock.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_interlock" + ], + "sources": [ + "build/unit_test/test/mocks/test_interlock/MockHL_het.c", + "build/unit_test/test/mocks/test_interlock/Mockdatabase.c", + "build/unit_test/test/mocks/test_interlock/Mockdiag.c", + "build/unit_test/test/mocks/test_interlock/Mockfassert.c", + "build/unit_test/test/mocks/test_interlock/Mockio.c", + "build/unit_test/test/mocks/test_interlock/Mockos.c", + "src/app/driver/interlock/interlock.c", + "tests/unit/app/driver/interlock/test_interlock.c", + "build/unit_test/test/runners/test_interlock_runner.c" + ] + }, + "src/app/driver/io/io.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_io" + ], + "sources": [ + "build/unit_test/test/mocks/test_io/Mockmcu.c", + "src/app/driver/io/io.c", + "tests/unit/app/driver/io/test_io.c", + "build/unit_test/test/runners/test_io_runner.c" + ] + }, + "src/app/driver/led/led.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_led" + ], + "sources": [ + "build/unit_test/test/mocks/test_led/Mockio.c", + "build/unit_test/test/mocks/test_led/Mockos.c", + "src/app/driver/led/led.c", + "tests/unit/app/driver/led/test_led.c", + "build/unit_test/test/runners/test_led_runner.c" + ] + }, + "src/app/driver/mcu/mcu.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_mcu" + ], + "sources": [ + "src/app/driver/mcu/mcu.c", + "tests/unit/app/driver/mcu/test_mcu.c", + "build/unit_test/test/runners/test_mcu_runner.c" + ] + }, + "src/app/driver/meas/meas.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_meas" + ], + "sources": [ + "build/unit_test/test/mocks/test_meas/Mockafe.c", + "src/app/driver/meas/meas.c", + "tests/unit/app/driver/meas/test_meas.c", + "build/unit_test/test/runners/test_meas_runner.c" + ] + }, + "src/app/driver/pex/pex.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_pex" + ], + "sources": [ + "build/unit_test/test/mocks/test_pex/MockHL_i2c.c", + "build/unit_test/test/mocks/test_pex/Mockdatabase.c", + "build/unit_test/test/mocks/test_pex/Mockdiag.c", + "build/unit_test/test/mocks/test_pex/Mocki2c.c", + "build/unit_test/test/mocks/test_pex/Mockos.c", + "build/unit_test/test/mocks/test_pex/Mockportmacro.c", + "src/app/driver/pex/pex.c", + "tests/unit/app/driver/pex/test_pex.c", + "build/unit_test/test/runners/test_pex_runner.c" + ] + }, + "src/app/driver/pwm/pwm.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_pwm" + ], + "sources": [ + "build/unit_test/test/mocks/test_pwm/MockHL_etpwm.c", + "src/app/driver/pwm/pwm.c", + "tests/unit/app/driver/pwm/test_pwm.c", + "build/unit_test/test/runners/test_pwm_runner.c" + ] + }, + "src/app/driver/rtc/rtc.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_rtc" + ], + "sources": [ + "build/unit_test/test/mocks/test_rtc/MockHL_i2c.c", + "build/unit_test/test/mocks/test_rtc/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_rtc/Mockdatabase.c", + "build/unit_test/test/mocks/test_rtc/Mockdiag.c", + "build/unit_test/test/mocks/test_rtc/Mocki2c.c", + "build/unit_test/test/mocks/test_rtc/Mockos.c", + "src/app/driver/rtc/rtc.c", + "tests/unit/app/driver/rtc/test_rtc.c", + "build/unit_test/test/runners/test_rtc_runner.c" + ] + }, + "src/app/driver/sbc/fs8x_driver/sbc_fs8x.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sbc_fs8x" + ], + "sources": [ + "src/app/driver/sbc/fs8x_driver/sbc_fs8x.c", + "tests/unit/app/driver/sbc/fs8x_driver/test_sbc_fs8x.c", + "None" + ] + }, + "src/app/driver/sbc/fs8x_driver/sbc_fs8x_communication.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sbc_fs8x_communication" + ], + "sources": [ + "src/app/driver/sbc/fs8x_driver/sbc_fs8x_communication.c", + "tests/unit/app/driver/sbc/fs8x_driver/test_sbc_fs8x_communication.c", + "None" + ] + }, + "src/app/driver/sbc/nxpfs85xx.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_nxpfs85xx" + ], + "sources": [ + "build/unit_test/test/mocks/test_nxpfs85xx/Mockdiag.c", + "build/unit_test/test/mocks/test_nxpfs85xx/Mockdma.c", + "build/unit_test/test/mocks/test_nxpfs85xx/Mockfassert.c", + "build/unit_test/test/mocks/test_nxpfs85xx/Mockfram.c", + "build/unit_test/test/mocks/test_nxpfs85xx/Mockio.c", + "build/unit_test/test/mocks/test_nxpfs85xx/Mockmaster_info.c", + "build/unit_test/test/mocks/test_nxpfs85xx/Mockmcu.c", + "build/unit_test/test/mocks/test_nxpfs85xx/Mocksbc_fs8x.c", + "build/unit_test/test/mocks/test_nxpfs85xx/Mocksbc_fs8x_communication.c", + "build/unit_test/test/mocks/test_nxpfs85xx/Mockspi.c", + "src/app/driver/sbc/nxpfs85xx.c", + "tests/unit/app/driver/sbc/test_nxpfs85xx.c", + "build/unit_test/test/runners/test_nxpfs85xx_runner.c" + ] + }, + "src/app/driver/sbc/sbc.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sbc" + ], + "sources": [ + "build/unit_test/test/mocks/test_sbc/Mockdma.c", + "build/unit_test/test/mocks/test_sbc/Mockio.c", + "build/unit_test/test/mocks/test_sbc/Mockmcu.c", + "build/unit_test/test/mocks/test_sbc/Mocknxpfs85xx.c", + "build/unit_test/test/mocks/test_sbc/Mockos.c", + "build/unit_test/test/mocks/test_sbc/Mockportmacro.c", + "build/unit_test/test/mocks/test_sbc/Mocksbc_fs8x.c", + "build/unit_test/test/mocks/test_sbc/Mocksbc_fs8x_communication.c", + "build/unit_test/test/mocks/test_sbc/Mockspi.c", + "src/app/driver/sbc/sbc.c", + "tests/unit/app/driver/sbc/test_sbc.c", + "build/unit_test/test/runners/test_sbc_runner.c" + ] + }, + "src/app/driver/spi/spi.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_spi" + ], + "sources": [ + "build/unit_test/test/mocks/test_spi/MockHL_spi.c", + "build/unit_test/test/mocks/test_spi/MockHL_sys_dma.c", + "build/unit_test/test/mocks/test_spi/Mockdma_cfg.c", + "build/unit_test/test/mocks/test_spi/Mockio.c", + "build/unit_test/test/mocks/test_spi/Mockmcu.c", + "build/unit_test/test/mocks/test_spi/Mockos.c", + "build/unit_test/test/mocks/test_spi/Mockspi_cfg.c", + "src/app/driver/spi/spi.c", + "tests/unit/app/driver/spi/test_spi.c", + "build/unit_test/test/runners/test_spi_runner.c" + ] + }, + "src/app/driver/sps/sps.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sps" + ], + "sources": [ + "build/unit_test/test/mocks/test_sps/Mockcontactor.c", + "build/unit_test/test/mocks/test_sps/Mockcontactor_cfg.c", + "build/unit_test/test/mocks/test_sps/Mockdatabase.c", + "build/unit_test/test/mocks/test_sps/Mockio.c", + "build/unit_test/test/mocks/test_sps/Mockmcu.c", + "build/unit_test/test/mocks/test_sps/Mockos.c", + "build/unit_test/test/mocks/test_sps/Mockpex.c", + "build/unit_test/test/mocks/test_sps/Mockpex_cfg.c", + "build/unit_test/test/mocks/test_sps/Mockspi.c", + "build/unit_test/test/mocks/test_sps/Mockspi_cfg.c", + "build/unit_test/test/mocks/test_sps/Mocksps_cfg.c", + "build/unit_test/test/mocks/test_sps/Mocksps_types.c", + "src/app/driver/sps/sps.c", + "tests/unit/app/driver/sps/test_sps.c", + "build/unit_test/test/runners/test_sps_runner.c" + ] + }, + "src/app/driver/ts/api/tsi_limits.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_tsi_limits" + ], + "sources": [ + "build/unit_test/test/mocks/test_tsi_limits/Mocktsi_plausibility_cfg.c", + "src/app/driver/ts/api/tsi_limits.c", + "tests/unit/app/driver/ts/api/test_tsi_limits.c", + "build/unit_test/test/runners/test_tsi_limits_runner.c" + ] + }, + "src/app/driver/ts/beta.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_beta" + ], + "sources": [ + "src/app/driver/ts/beta.c", + "tests/unit/app/driver/ts/test_beta.c", + "build/unit_test/test/runners/test_beta_runner.c" + ] + }, + "src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_epcos_b57251v5103j060" + ], + "sources": [ + "src/app/driver/ts/epcos/b57251v5103j060/epcos_b57251v5103j060.c", + "tests/unit/app/driver/ts/epcos/b57251v5103j060/test_epcos_b57251v5103j060.c", + "build/unit_test/test/runners/test_epcos_b57251v5103j060_runner.c" + ] + }, + "src/app/driver/ts/epcos/b57251v5103j060/lookup-table/epcos_b57251v5103j060_lookup-table.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_epcos_b57251v5103j060_lookup-table" + ], + "sources": [ + "build/unit_test/test/mocks/test_epcos_b57251v5103j060_lookup-table/Mockepcos_b57251v5103j060.c", + "src/app/driver/ts/epcos/b57251v5103j060/lookup-table/epcos_b57251v5103j060_lookup-table.c", + "tests/unit/app/driver/ts/epcos/b57251v5103j060/lookup-table/test_epcos_b57251v5103j060_lookup-table.c", + "build/unit_test/test/runners/test_epcos_b57251v5103j060_lookup-table_runner.c" + ] + }, + "src/app/driver/ts/epcos/b57251v5103j060/polynomial/epcos_b57251v5103j060_polynomial.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_epcos_b57251v5103j060_polynomial" + ], + "sources": [ + "build/unit_test/test/mocks/test_epcos_b57251v5103j060_polynomial/Mockepcos_b57251v5103j060.c", + "src/app/driver/ts/epcos/b57251v5103j060/polynomial/epcos_b57251v5103j060_polynomial.c", + "tests/unit/app/driver/ts/epcos/b57251v5103j060/polynomial/test_epcos_b57251v5103j060_polynomial.c", + "build/unit_test/test/runners/test_epcos_b57251v5103j060_polynomial_runner.c" + ] + }, + "src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_epcos_b57861s0103f045" + ], + "sources": [ + "src/app/driver/ts/epcos/b57861s0103f045/epcos_b57861s0103f045.c", + "tests/unit/app/driver/ts/epcos/b57861s0103f045/test_epcos_b57861s0103f045.c", + "build/unit_test/test/runners/test_epcos_b57861s0103f045_runner.c" + ] + }, + "src/app/driver/ts/epcos/b57861s0103f045/lookup-table/epcos_b57861s0103f045_lookup-table.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_epcos_b57861s0103f045_lookup-table" + ], + "sources": [ + "build/unit_test/test/mocks/test_epcos_b57861s0103f045_lookup-table/Mockepcos_b57861s0103f045.c", + "src/app/driver/ts/epcos/b57861s0103f045/lookup-table/epcos_b57861s0103f045_lookup-table.c", + "tests/unit/app/driver/ts/epcos/b57861s0103f045/lookup-table/test_epcos_b57861s0103f045_lookup-table.c", + "build/unit_test/test/runners/test_epcos_b57861s0103f045_lookup-table_runner.c" + ] + }, + "src/app/driver/ts/epcos/b57861s0103f045/polynomial/epcos_b57861s0103f045_polynomial.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_epcos_b57861s0103f045_polynomial" + ], + "sources": [ + "build/unit_test/test/mocks/test_epcos_b57861s0103f045_polynomial/Mockepcos_b57861s0103f045.c", + "src/app/driver/ts/epcos/b57861s0103f045/polynomial/epcos_b57861s0103f045_polynomial.c", + "tests/unit/app/driver/ts/epcos/b57861s0103f045/polynomial/test_epcos_b57861s0103f045_polynomial.c", + "build/unit_test/test/runners/test_epcos_b57861s0103f045_polynomial_runner.c" + ] + }, + "src/app/driver/ts/fake/none/fake_none.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_fake_none" + ], + "sources": [ + "src/app/driver/ts/fake/none/fake_none.c", + "tests/unit/app/driver/ts/fake/none/test_fake_none.c", + "build/unit_test/test/runners/test_fake_none_runner.c" + ] + }, + "src/app/driver/ts/fake/none/lookup-table/fake_none_lookup-table.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_fake_none_lookup-table" + ], + "sources": [ + "src/app/driver/ts/fake/none/lookup-table/fake_none_lookup-table.c", + "tests/unit/app/driver/ts/fake/none/lookup-table/test_fake_none_lookup-table.c", + "build/unit_test/test/runners/test_fake_none_lookup-table_runner.c" + ] + }, + "src/app/driver/ts/fake/none/polynomial/fake_none_polynomial.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_fake_none_polynomial" + ], + "sources": [ + "src/app/driver/ts/fake/none/polynomial/fake_none_polynomial.c", + "tests/unit/app/driver/ts/fake/none/polynomial/test_fake_none_polynomial.c", + "build/unit_test/test/runners/test_fake_none_polynomial_runner.c" + ] + }, + "src/app/driver/ts/murata/ncxxxxh103/lookup-table/murata_ncxxxxh103_lookup-table.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_murata_ncxxxxh103_lookup-table" + ], + "sources": [ + "build/unit_test/test/mocks/test_murata_ncxxxxh103_lookup-table/Mockmurata_ncxxxxh103.c", + "src/app/driver/ts/murata/ncxxxxh103/lookup-table/murata_ncxxxxh103_lookup-table.c", + "tests/unit/app/driver/ts/murata/ncxxxxh103/lookup-table/test_murata_ncxxxxh103_lookup-table.c", + "build/unit_test/test/runners/test_murata_ncxxxxh103_lookup-table_runner.c" + ] + }, + "src/app/driver/ts/murata/ncxxxxh103/murata_ncxxxxh103.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_murata_ncxxxxh103" + ], + "sources": [ + "src/app/driver/ts/murata/ncxxxxh103/murata_ncxxxxh103.c", + "tests/unit/app/driver/ts/murata/ncxxxxh103/test_murata_ncxxxxh103.c", + "build/unit_test/test/runners/test_murata_ncxxxxh103_runner.c" + ] + }, + "src/app/driver/ts/murata/ncxxxxh103/polynomial/murata_ncxxxxh103_polynomial.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_murata_ncxxxxh103_polynomial" + ], + "sources": [ + "build/unit_test/test/mocks/test_murata_ncxxxxh103_polynomial/Mockmurata_ncxxxxh103.c", + "src/app/driver/ts/murata/ncxxxxh103/polynomial/murata_ncxxxxh103_polynomial.c", + "tests/unit/app/driver/ts/murata/ncxxxxh103/polynomial/test_murata_ncxxxxh103_polynomial.c", + "build/unit_test/test/runners/test_murata_ncxxxxh103_polynomial_runner.c" + ] + }, + "src/app/driver/ts/vishay/ntcalug01a103g/lookup-table/vishay_ntcalug01a103g_lookup-table.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_vishay_ntcalug01a103g_lookup-table" + ], + "sources": [ + "build/unit_test/test/mocks/test_vishay_ntcalug01a103g_lookup-table/Mockvishay_ntcalug01a103g.c", + "src/app/driver/ts/vishay/ntcalug01a103g/lookup-table/vishay_ntcalug01a103g_lookup-table.c", + "tests/unit/app/driver/ts/vishay/ntcalug01a103g/lookup-table/test_vishay_ntcalug01a103g_lookup-table.c", + "build/unit_test/test/runners/test_vishay_ntcalug01a103g_lookup-table_runner.c" + ] + }, + "src/app/driver/ts/vishay/ntcalug01a103g/polynomial/vishay_ntcalug01a103g_polynomial.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_vishay_ntcalug01a103g_polynomial" + ], + "sources": [ + "build/unit_test/test/mocks/test_vishay_ntcalug01a103g_polynomial/Mockvishay_ntcalug01a103g.c", + "src/app/driver/ts/vishay/ntcalug01a103g/polynomial/vishay_ntcalug01a103g_polynomial.c", + "tests/unit/app/driver/ts/vishay/ntcalug01a103g/polynomial/test_vishay_ntcalug01a103g_polynomial.c", + "build/unit_test/test/runners/test_vishay_ntcalug01a103g_polynomial_runner.c" + ] + }, + "src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_vishay_ntcalug01a103g" + ], + "sources": [ + "src/app/driver/ts/vishay/ntcalug01a103g/vishay_ntcalug01a103g.c", + "tests/unit/app/driver/ts/vishay/ntcalug01a103g/test_vishay_ntcalug01a103g.c", + "build/unit_test/test/runners/test_vishay_ntcalug01a103g_runner.c" + ] + }, + "src/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/vishay_ntcle317e4103sba_lookup-table.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_vishay_ntcle317e4103sba_lookup-table" + ], + "sources": [ + "build/unit_test/test/mocks/test_vishay_ntcle317e4103sba_lookup-table/Mockvishay_ntcle317e4103sba.c", + "src/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/vishay_ntcle317e4103sba_lookup-table.c", + "tests/unit/app/driver/ts/vishay/ntcle317e4103sba/lookup-table/test_vishay_ntcle317e4103sba_lookup-table.c", + "build/unit_test/test/runners/test_vishay_ntcle317e4103sba_lookup-table_runner.c" + ] + }, + "src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_vishay_ntcle317e4103sba" + ], + "sources": [ + "src/app/driver/ts/vishay/ntcle317e4103sba/vishay_ntcle317e4103sba.c", + "tests/unit/app/driver/ts/vishay/ntcle317e4103sba/test_vishay_ntcle317e4103sba.c", + "build/unit_test/test/runners/test_vishay_ntcle317e4103sba_runner.c" + ] + }, + "src/app/driver/ts/vishay/ntcle413e2103f102l/lookup-table/vishay_ntcle413e2103f102l_lookup-table.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_vishay_ntcle413e2103f102l_lookup-table" + ], + "sources": [ + "build/unit_test/test/mocks/test_vishay_ntcle413e2103f102l_lookup-table/Mockvishay_ntcle413e2103f102l.c", + "src/app/driver/ts/vishay/ntcle413e2103f102l/lookup-table/vishay_ntcle413e2103f102l_lookup-table.c", + "tests/unit/app/driver/ts/vishay/ntcle413e2103f102l/lookup-table/test_vishay_ntcle413e2103f102l_lookup-table.c", + "build/unit_test/test/runners/test_vishay_ntcle413e2103f102l_lookup-table_runner.c" + ] + }, + "src/app/driver/ts/vishay/ntcle413e2103f102l/vishay_ntcle413e2103f102l.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_vishay_ntcle413e2103f102l" + ], + "sources": [ + "src/app/driver/ts/vishay/ntcle413e2103f102l/vishay_ntcle413e2103f102l.c", + "tests/unit/app/driver/ts/vishay/ntcle413e2103f102l/test_vishay_ntcle413e2103f102l.c", + "build/unit_test/test/runners/test_vishay_ntcle413e2103f102l_runner.c" + ] + }, + "src/app/engine/config/database_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_database_cfg" + ], + "sources": [ + "src/app/engine/config/database_cfg.c", + "tests/unit/app/engine/config/test_database_cfg.c", + "build/unit_test/test/runners/test_database_cfg_runner.c" + ] + }, + "src/app/engine/config/diag_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cfg/Mockdatabase.c", + "build/unit_test/test/mocks/test_diag_cfg/Mockdiag_cbs.c", + "src/app/engine/config/diag_cfg.c", + "tests/unit/app/engine/config/test_diag_cfg.c", + "build/unit_test/test/runners/test_diag_cfg_runner.c" + ] + }, + "src/app/engine/config/sys_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sys_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_sys_cfg/Mockcan_cbs_tx_debug-response.c", + "build/unit_test/test/mocks/test_sys_cfg/Mockcan_cfg.c", + "src/app/engine/config/sys_cfg.c", + "tests/unit/app/engine/config/test_sys_cfg.c", + "build/unit_test/test/runners/test_sys_cfg_runner.c" + ] + }, + "src/app/engine/config/sys_mon_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sys_mon_cfg" + ], + "sources": [ + "src/app/engine/config/sys_mon_cfg.c", + "tests/unit/app/engine/config/test_sys_mon_cfg.c", + "build/unit_test/test/runners/test_sys_mon_cfg_runner.c" + ] + }, + "src/app/engine/database/database.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_database" + ], + "sources": [ + "build/unit_test/test/mocks/test_database/Mockfassert.c", + "build/unit_test/test/mocks/test_database/Mockftask.c", + "build/unit_test/test/mocks/test_database/Mockmpu_prototypes.c", + "build/unit_test/test/mocks/test_database/Mockos.c", + "src/app/engine/database/database.c", + "tests/unit/app/engine/database/test_database.c", + "build/unit_test/test/runners/test_database_runner.c" + ] + }, + "src/app/engine/database/database_helper.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_database_helper" + ], + "sources": [ + "build/unit_test/test/mocks/test_database_helper/Mockfassert.c", + "build/unit_test/test/mocks/test_database_helper/Mockmpu_prototypes.c", + "build/unit_test/test/mocks/test_database_helper/Mockos.c", + "src/app/engine/database/database_helper.c", + "tests/unit/app/engine/database/test_database_helper.c", + "build/unit_test/test/runners/test_database_helper_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_aerosol-sensor.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_aerosol-sensor" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_aerosol-sensor/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_aerosol-sensor.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_aerosol-sensor.c", + "build/unit_test/test/runners/test_diag_cbs_aerosol-sensor_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_afe.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_afe" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_afe/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_afe.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_afe.c", + "build/unit_test/test/runners/test_diag_cbs_afe_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_bms.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_bms" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_bms/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_bms.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_bms.c", + "build/unit_test/test/runners/test_diag_cbs_bms_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_can.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_can" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_can/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_can.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_can.c", + "build/unit_test/test/runners/test_diag_cbs_can_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_contactor.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_contactor" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_contactor/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_contactor.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_contactor.c", + "build/unit_test/test/runners/test_diag_cbs_contactor_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_current-sensor.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_current-sensor" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_current-sensor/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_current-sensor.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_current-sensor.c", + "build/unit_test/test/runners/test_diag_cbs_current-sensor_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_current.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_current" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_current/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_current.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_current.c", + "build/unit_test/test/runners/test_diag_cbs_current_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_deep-discharge.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_deep-discharge" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_deep-discharge/Mockdiag_cfg.c", + "build/unit_test/test/mocks/test_diag_cbs_deep-discharge/Mockfram.c", + "src/app/engine/diag/cbs/diag_cbs_deep-discharge.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_deep-discharge.c", + "build/unit_test/test/runners/test_diag_cbs_deep-discharge_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_dummy.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_dummy" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_dummy/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_dummy.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_dummy.c", + "build/unit_test/test/runners/test_diag_cbs_dummy_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_fram.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_fram" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_fram/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_fram.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_fram.c", + "build/unit_test/test/runners/test_diag_cbs_fram_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_i2c.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_i2c" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_i2c/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_i2c.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_i2c.c", + "build/unit_test/test/runners/test_diag_cbs_i2c_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_insulation.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_insulation" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_insulation/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_insulation.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_insulation.c", + "build/unit_test/test/runners/test_diag_cbs_insulation_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_interlock.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_interlock" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_interlock/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_interlock.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_interlock.c", + "build/unit_test/test/runners/test_diag_cbs_interlock_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_plausibility.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_plausibility" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_plausibility/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_plausibility.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_plausibility.c", + "build/unit_test/test/runners/test_diag_cbs_plausibility_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_power-measurement.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_power-measurement" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_power-measurement/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_power-measurement.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_power-measurement.c", + "build/unit_test/test/runners/test_diag_cbs_power-measurement_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_rtc.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_rtc" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_rtc/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_rtc.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_rtc.c", + "build/unit_test/test/runners/test_diag_cbs_rtc_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_sbc.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_sbc" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_sbc/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_sbc.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_sbc.c", + "build/unit_test/test/runners/test_diag_cbs_sbc_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_sys-mon.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_sys-mon" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_sys-mon/Mockdiag_cfg.c", + "build/unit_test/test/mocks/test_diag_cbs_sys-mon/Mocksys_mon_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_sys-mon.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_sys-mon.c", + "build/unit_test/test/runners/test_diag_cbs_sys-mon_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_temperature.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_temperature" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_temperature/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_temperature.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_temperature.c", + "build/unit_test/test/runners/test_diag_cbs_temperature_runner.c" + ] + }, + "src/app/engine/diag/cbs/diag_cbs_voltage.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag_cbs_voltage" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag_cbs_voltage/Mockdiag_cfg.c", + "src/app/engine/diag/cbs/diag_cbs_voltage.c", + "tests/unit/app/engine/diag/cbs/test_diag_cbs_voltage.c", + "build/unit_test/test/runners/test_diag_cbs_voltage_runner.c" + ] + }, + "src/app/engine/diag/diag.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_diag" + ], + "sources": [ + "build/unit_test/test/mocks/test_diag/Mockdatabase.c", + "build/unit_test/test/mocks/test_diag/Mockdiag_cbs.c", + "src/app/engine/diag/diag.c", + "tests/unit/app/engine/diag/test_diag.c", + "build/unit_test/test/runners/test_diag_runner.c" + ] + }, + "src/app/engine/hw_info/master_info.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_master_info" + ], + "sources": [ + "src/app/engine/hw_info/master_info.c", + "tests/unit/app/engine/hw_info/test_master_info.c", + "build/unit_test/test/runners/test_master_info_runner.c" + ] + }, + "src/app/engine/sys/reset.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_reset" + ], + "sources": [ + "src/app/engine/sys/reset.c", + "tests/unit/app/engine/sys/test_reset.c", + "build/unit_test/test/runners/test_reset_runner.c" + ] + }, + "src/app/engine/sys/sys.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sys" + ], + "sources": [ + "build/unit_test/test/mocks/test_sys/Mockafe.c", + "build/unit_test/test/mocks/test_sys/Mockalgorithm.c", + "build/unit_test/test/mocks/test_sys/Mockbal.c", + "build/unit_test/test/mocks/test_sys/Mockbms.c", + "build/unit_test/test/mocks/test_sys/Mockcan.c", + "build/unit_test/test/mocks/test_sys/Mockcontactor.c", + "build/unit_test/test/mocks/test_sys/Mockdatabase.c", + "build/unit_test/test/mocks/test_sys/Mockdiag.c", + "build/unit_test/test/mocks/test_sys/Mockfassert.c", + "build/unit_test/test/mocks/test_sys/Mockfram.c", + "build/unit_test/test/mocks/test_sys/Mockimd.c", + "build/unit_test/test/mocks/test_sys/Mockinterlock.c", + "build/unit_test/test/mocks/test_sys/Mockmeas.c", + "build/unit_test/test/mocks/test_sys/Mockos.c", + "build/unit_test/test/mocks/test_sys/Mocksbc.c", + "build/unit_test/test/mocks/test_sys/Mocksof_trapezoid.c", + "build/unit_test/test/mocks/test_sys/Mockstate_estimation.c", + "build/unit_test/test/mocks/test_sys/Mocksys_cfg.c", + "src/app/engine/sys/sys.c", + "tests/unit/app/engine/sys/test_sys.c", + "build/unit_test/test/runners/test_sys_runner.c" + ] + }, + "src/app/engine/sys_mon/sys_mon.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_sys_mon" + ], + "sources": [ + "build/unit_test/test/mocks/test_sys_mon/Mockdiag.c", + "build/unit_test/test/mocks/test_sys_mon/Mockfram.c", + "build/unit_test/test/mocks/test_sys_mon/Mockfram_cfg.c", + "build/unit_test/test/mocks/test_sys_mon/Mockos.c", + "build/unit_test/test/mocks/test_sys_mon/Mocksys_mon_cfg.c", + "src/app/engine/sys_mon/sys_mon.c", + "tests/unit/app/engine/sys_mon/test_sys_mon.c", + "build/unit_test/test/runners/test_sys_mon_runner.c" + ] + }, + "src/app/main/fassert.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_fassert" + ], + "sources": [ + "src/app/main/fassert.c", + "tests/unit/app/main/test_fassert.c", + "build/unit_test/test/runners/test_fassert_runner.c" + ] + }, + "src/app/main/fstartup.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_fstartup" + ], + "sources": [ + "src/app/main/fstartup.c", + "tests/unit/app/main/test_fstartup.c", + "build/unit_test/test/runners/test_fstartup_runner.c" + ] + }, + "src/app/main/main.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_main" + ], + "sources": [ + "src/app/main/main.c", + "tests/unit/app/main/test_main.c", + "build/unit_test/test/runners/test_main_runner.c" + ] + }, + "src/app/task/config/ftask_cfg.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ftask_cfg" + ], + "sources": [ + "build/unit_test/test/mocks/test_ftask_cfg/MockHL_gio.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockadc.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockafe.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockalgorithm.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockbal.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockbms.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockcan.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockcontactor.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockdatabase.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockdiag.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockdiag_cfg.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockfram.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockhtsensor.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mocki2c.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockimd.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockinterlock.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockled.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockmeas.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockmpu_prototypes.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockos.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockpex.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockredundancy.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockrtc.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mocksbc.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mocksof_trapezoid.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mocksps.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mockstate_estimation.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mocksys.c", + "build/unit_test/test/mocks/test_ftask_cfg/Mocksys_mon.c", + "src/app/task/config/ftask_cfg.c", + "tests/unit/app/task/config/test_ftask_cfg.c", + "build/unit_test/test/runners/test_ftask_cfg_runner.c" + ] + }, + "src/app/task/ftask/freertos/ftask_freertos.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ftask_freertos" + ], + "sources": [ + "build/unit_test/test/mocks/test_ftask_freertos/Mockftask_cfg.c", + "build/unit_test/test/mocks/test_ftask_freertos/Mockmpu_prototypes.c", + "build/unit_test/test/mocks/test_ftask_freertos/Mockos.c", + "build/unit_test/test/mocks/test_ftask_freertos/Mocksys_mon.c", + "src/app/task/ftask/freertos/ftask_freertos.c", + "tests/unit/app/task/ftask/freertos/test_ftask_freertos.c", + "build/unit_test/test/runners/test_ftask_freertos_runner.c" + ] + }, + "src/app/task/ftask/ftask.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_ftask" + ], + "sources": [ + "build/unit_test/test/mocks/test_ftask/MockHL_gio.c", + "build/unit_test/test/mocks/test_ftask/Mockadc.c", + "build/unit_test/test/mocks/test_ftask/Mockafe.c", + "build/unit_test/test/mocks/test_ftask/Mockalgorithm.c", + "build/unit_test/test/mocks/test_ftask/Mockbal.c", + "build/unit_test/test/mocks/test_ftask/Mockbms.c", + "build/unit_test/test/mocks/test_ftask/Mockcan.c", + "build/unit_test/test/mocks/test_ftask/Mockcontactor.c", + "build/unit_test/test/mocks/test_ftask/Mockdatabase.c", + "build/unit_test/test/mocks/test_ftask/Mockdiag.c", + "build/unit_test/test/mocks/test_ftask/Mockdiag_cfg.c", + "build/unit_test/test/mocks/test_ftask/Mockfram.c", + "build/unit_test/test/mocks/test_ftask/Mockhtsensor.c", + "build/unit_test/test/mocks/test_ftask/Mocki2c.c", + "build/unit_test/test/mocks/test_ftask/Mockimd.c", + "build/unit_test/test/mocks/test_ftask/Mockinterlock.c", + "build/unit_test/test/mocks/test_ftask/Mockled.c", + "build/unit_test/test/mocks/test_ftask/Mockmeas.c", + "build/unit_test/test/mocks/test_ftask/Mockmpu_prototypes.c", + "build/unit_test/test/mocks/test_ftask/Mockos.c", + "build/unit_test/test/mocks/test_ftask/Mockpex.c", + "build/unit_test/test/mocks/test_ftask/Mockredundancy.c", + "build/unit_test/test/mocks/test_ftask/Mockrtc.c", + "build/unit_test/test/mocks/test_ftask/Mocksbc.c", + "build/unit_test/test/mocks/test_ftask/Mocksof_trapezoid.c", + "build/unit_test/test/mocks/test_ftask/Mocksps.c", + "build/unit_test/test/mocks/test_ftask/Mockstate_estimation.c", + "build/unit_test/test/mocks/test_ftask/Mocksys.c", + "build/unit_test/test/mocks/test_ftask/Mocksys_mon.c", + "src/app/task/ftask/ftask.c", + "tests/unit/app/task/ftask/test_ftask.c", + "build/unit_test/test/runners/test_ftask_runner.c" + ] + }, + "src/app/task/os/freertos/os_freertos.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_os_freertos" + ], + "sources": [ + "build/unit_test/test/mocks/test_os_freertos/Mockcan_cbs_tx_fatal-errors.c", + "build/unit_test/test/mocks/test_os_freertos/Mockftask.c", + "build/unit_test/test/mocks/test_os_freertos/Mockftask_cfg.c", + "build/unit_test/test/mocks/test_os_freertos/Mockportmacro.c", + "build/unit_test/test/mocks/test_os_freertos/Mockqueue.c", + "build/unit_test/test/mocks/test_os_freertos/Mockrtc.c", + "build/unit_test/test/mocks/test_os_freertos/Mocktask.c", + "src/app/task/os/freertos/os_freertos.c", + "tests/unit/app/task/os/freertos/test_os_freertos.c", + "build/unit_test/test/runners/test_os_freertos_runner.c" + ] + }, + "src/app/task/os/os.c": { + "include": [ + "build/unit_test/include", + "build/unit_test/test/mocks/test_os", + "src/app/driver/can", + "src/app/driver/can/cbs", + "src/app/driver/can/cbs/tx", + "src/app/driver/config", + "src/app/driver/rtc", + "src/app/task/config", + "src/app/task/ftask", + "src/app/application/config", + "src/app/driver/mcu", + "src/app/engine/config", + "src/app/engine/database", + "src/app/main/include", + "src/app/main/include/config", + "src/app/task/os", + "src/os/freertos/include", + "src/os/freertos/portable/ccs/arm_cortex-r5" + ], + "sources": [ + "build/unit_test/test/mocks/test_os/Mockcan.c", + "build/unit_test/test/mocks/test_os/Mockftask.c", + "build/unit_test/test/mocks/test_os/Mockftask_cfg.c", + "build/unit_test/test/mocks/test_os/Mockportmacro.c", + "build/unit_test/test/mocks/test_os/Mockqueue.c", + "build/unit_test/test/mocks/test_os/Mockrtc.c", + "build/unit_test/test/mocks/test_os/Mocktask.c", + "src/app/task/os/freertos/os_freertos.c", + "src/app/driver/can/cbs/tx/can_cbs_tx_crash-dump.c", + "src/app/driver/config/can_cfg.c", + "src/app/task/os/os.c", + "tests/unit/app/task/os/test_os.c", + "build/unit_test/test/runners/test_os_runner.c" + ] + } +} diff --git a/tests/unit/doxygen_tests.h b/tests/unit/doxygen_tests.h index 16a51793..64846133 100644 --- a/tests/unit/doxygen_tests.h +++ b/tests/unit/doxygen_tests.h @@ -43,8 +43,8 @@ * @file doxygen_tests.h * @author foxBMS Team * @date 2019-06-02 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix DX * @@ -67,6 +67,8 @@ /*========== Includes =======================================================*/ +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Macros and Definitions =========================================*/ /*========== Extern Constant and Variable Declarations ======================*/ diff --git a/tests/unit/opt/cells/config/test_lg_inr18650mj1.c b/tests/unit/opt/cells/config/test_lg_inr18650mj1.c index 797ad742..ab8b2fe9 100644 --- a/tests/unit/opt/cells/config/test_lg_inr18650mj1.c +++ b/tests/unit/opt/cells/config/test_lg_inr18650mj1.c @@ -43,8 +43,8 @@ * @file test_lg_inr18650mj1.c * @author foxBMS Team * @date 2020-07-31 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -57,6 +57,9 @@ #include "lg_inr18650mj1.h" +/*========== Unit Testing Framework Directives ==============================*/ +TEST_INCLUDE_PATH("../../src/opt/cells/config") + /*========== Definitions and Implementations for Unit Test ==================*/ /*========== Setup and Teardown =============================================*/ diff --git a/tests/unit/run_ut_gcc_build.bat b/tests/unit/run_ut_gcc_build.bat new file mode 100644 index 00000000..6c5a01a2 --- /dev/null +++ b/tests/unit/run_ut_gcc_build.bat @@ -0,0 +1,65 @@ +@REM Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +@REM All rights reserved. +@REM +@REM SPDX-License-Identifier: BSD-3-Clause +@REM +@REM Redistribution and use in source and binary forms, with or without +@REM modification, are permitted provided that the following conditions are met: +@REM +@REM 1. Redistributions of source code must retain the above copyright notice, this +@REM list of conditions and the following disclaimer. +@REM +@REM 2. Redistributions in binary form must reproduce the above copyright notice, +@REM this list of conditions and the following disclaimer in the documentation +@REM and/or other materials provided with the distribution. +@REM +@REM 3. Neither the name of the copyright holder nor the names of its +@REM contributors may be used to endorse or promote products derived from +@REM this software without specific prior written permission. +@REM +@REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +@REM AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +@REM IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +@REM DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +@REM FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +@REM DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +@REM SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +@REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +@REM OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +@REM OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +@REM +@REM We kindly request you to use one or more of the following phrases to refer to +@REM foxBMS in your hardware, software, documentation or advertising materials: +@REM +@REM - "This product uses parts of foxBMS®" +@REM - "This product includes parts of foxBMS®" +@REM - "This product is derived from foxBMS®" + +@SETLOCAL EnableExtensions EnableDelayedExpansion + +@PUSHD %~dp0 + +@FOR /F "usebackq tokens=*" %%A in ("%~dp0\..\..\conf\env\paths_win32.txt") do @( + @IF EXIST %%A ( + @CALL SET "NewPath=%%NewPath%%;%%A" + ) +) + +@IF DEFINED NewPath ( + @SET "PATH=%NewPath:~1%;%PATH%" +) + +@SET CONDA_BASE_ENVIRONMENT_ACTIVATE_SCRIPT="" +@CALL %~dp0\..\..\tools\utils\cmd\find_base_conda.bat + +@IF %CONDA_BASE_ENVIRONMENT_ACTIVATE_SCRIPT%=="" ( + pause + @EXIT /b 1 +) + +@SET BAUHAUS_CONFIG=%~dp0axivion +@CALL %CONDA_BASE_ENVIRONMENT_ACTIVATE_SCRIPT% %CONDA_DEVELOPMENT_ENVIRONMENT_NAME% + +@python %~dp0..\..\tools\waf --top %~dp0 %* + +@POPD diff --git a/tests/unit/support/test_algorithm_stubs.h b/tests/unit/support/test_algorithm_stubs.h index 034d5892..dc2da132 100644 --- a/tests/unit/support/test_algorithm_stubs.h +++ b/tests/unit/support/test_algorithm_stubs.h @@ -43,8 +43,8 @@ * @file test_algorithm_stubs.h * @author foxBMS Team * @date 2020-12-09 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -63,6 +63,8 @@ #include "fstd_types.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Macros and Definitions =========================================*/ /** a compute function for mocking for the algorithm module */ extern void TEST_AlgorithmComputeFunction(void); diff --git a/tests/unit/support/test_assert_helper.h b/tests/unit/support/test_assert_helper.h index b00ac6d7..e0970bd0 100644 --- a/tests/unit/support/test_assert_helper.h +++ b/tests/unit/support/test_assert_helper.h @@ -43,8 +43,8 @@ * @file test_assert_helper.h * @author foxBMS Team * @date 2020-07-22 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -61,6 +61,8 @@ #include "CException.h" +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Macros and Definitions =========================================*/ /** diff --git a/tests/unit/support/test_can_mpu_prototype_queue_create_stub.h b/tests/unit/support/test_can_mpu_prototype_queue_create_stub.h index 9afb22c8..b3eb1f65 100644 --- a/tests/unit/support/test_can_mpu_prototype_queue_create_stub.h +++ b/tests/unit/support/test_can_mpu_prototype_queue_create_stub.h @@ -43,8 +43,8 @@ * @file test_can_mpu_prototype_queue_create_stub.h * @author foxBMS Team * @date 2021-06-09 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,6 +58,8 @@ /*========== Includes =======================================================*/ +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Macros and Definitions =========================================*/ QueueHandle_t MPU_xQueueGenericCreateStatic( diff --git a/src/app/application/algorithm/state_estimation/soc/counting/soc_counting.h b/tests/unit/support/test_ignore_list.h similarity index 62% rename from src/app/application/algorithm/state_estimation/soc/counting/soc_counting.h rename to tests/unit/support/test_ignore_list.h index a8b9c7f9..9e58f95e 100644 --- a/src/app/application/algorithm/state_estimation/soc/counting/soc_counting.h +++ b/tests/unit/support/test_ignore_list.h @@ -40,37 +40,41 @@ */ /** - * @file soc_counting.h + * @file test_ignore_list.h * @author foxBMS Team - * @date 2020-10-07 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 - * @ingroup APPLICATION - * @prefix SOC - * - * @brief Header for SOC module, responsible for calculation of SOC + * @date 2023-07-21 (date of creation) + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 + * @ingroup UNIT_TEST_IMPLEMENTATION + * @prefix TEST * + * @brief Warnings that need to be ignored in the unit test build + * @details 'unknown-pragmas' needs to ignored as the GCC would otherwise + * complain about the TI pragmas, which are however required. + * 'unused-parameter' needs to ignored as there are generic + * interfaces, where then it can appear that some parameters are then + * unused. */ -#ifndef FOXBMS__SOC_COUNTING_H_ -#define FOXBMS__SOC_COUNTING_H_ +#ifndef FOXBMS__TEST_IGNORE_LIST_H_ +#define FOXBMS__TEST_IGNORE_LIST_H_ /*========== Includes =======================================================*/ -#include "battery_system_cfg.h" -#include "soc_counting_cfg.h" - -#include "state_estimation.h" -#include +/*========== Unit Testing Framework Directives ==============================*/ /*========== Macros and Definitions =========================================*/ -/*========== Extern Constant and Variable Declarations ======================*/ - -/*========== Extern Function Prototypes =====================================*/ - -/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/ -#ifdef UNITY_UNIT_TEST -#endif - -#endif /* FOXBMS__SOC_COUNTING_H_ */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma GCC diagnostic ignored "-Wunused-parameter" +/* GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 + TODO: check if we can upgrade to a later, specific GCC version */ +#pragma GCC diagnostic ignored "-Wmissing-braces" +/* TODO: Check if this is really required */ +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +/* TODO: fix state machines */ +#pragma GCC diagnostic ignored "-Wswitch" +/* TODO: fix once CMock creates correct '*ReturnThruPtr*' mocks */ +#pragma GCC diagnostic ignored "-Wpointer-arith" +#endif /* FOXBMS__TEST_IGNORE_LIST_H_ */ diff --git a/tests/unit/support/test_pec_helper.h b/tests/unit/support/test_pec_helper.h index 8663b8e9..033a01b1 100644 --- a/tests/unit/support/test_pec_helper.h +++ b/tests/unit/support/test_pec_helper.h @@ -43,8 +43,8 @@ * @file test_pec_helper.h * @author foxBMS Team * @date 2020-12-16 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup UNIT_TEST_IMPLEMENTATION * @prefix TEST * @@ -58,6 +58,8 @@ /*========== Includes =======================================================*/ +/*========== Unit Testing Framework Directives ==============================*/ + /*========== Macros and Definitions =========================================*/ #define TEST_ASSERT_PEC_CORRECT_IN_ARRAY(array) \ { \ diff --git a/tests/unit/wscript b/tests/unit/wscript new file mode 100644 index 00000000..9b13ceb0 --- /dev/null +++ b/tests/unit/wscript @@ -0,0 +1,305 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Host and SPA build of the unit test suite""" + +# pylint: disable=missing-function-docstring + +import os +from pathlib import Path + +from waflib import Build, Context, Logs +from waflib.Build import BuildContext, CleanContext +from waflib.Configure import ConfigurationContext +from waflib.Node import Node +from waflib.Options import OptionsContext +from waflib.Tools import waf_unit_test + + +def get_bld(self: Node): + """Based on the implementation get_bld(): + https://gitlab.com/ita1024/waf/-/blob/ad7b733fc60852f77eff200b79e8b6f9562494d2/waflib/Node.py#L783-807 + but we do not need the '__root__' feature + """ + cur = self + lst = [] + while cur.parent: + if cur is self.ctx.bldnode: + return self + if cur is self.ctx.srcnode: + lst.reverse() + return self.ctx.bldnode.make_node(lst) + lst.append(cur.name) + cur = cur.parent + lst.reverse() + lst = list( + filter(("..").__ne__, str(self.path_from(self.ctx.bldnode)).split(os.sep)) + ) + return self.ctx.bldnode.make_node(lst) + + +Node.get_bld = get_bld + +COMMON_CFLAGS = [ + "-g", + "-DGNU_COMPILER", + "-DUNITY_UNIT_TEST", + "-DUNITY_INCLUDE_EXEC_TIME", + "-std=c11", + "-Wextra", + "-Wall", + "-pedantic", + "-include", + "test_ignore_list.h", +] + +VARIANTS = ["host", "axivion"] + + +for x in VARIANTS: + for y in (BuildContext, CleanContext): + NAME = y.__name__.replace("Context", "").lower() + + class TMP(y): # pylint: disable=missing-class-docstring + __doc__ = f"""{NAME} command for the '{x}' variant""" + + cmd = NAME + "_" + x + variant = x + + +def options(opt: OptionsContext): + """Available build options""" + opt.load("compiler_c") + opt.load("waf_unit_test") + + # remove unsupported options + all_contexts = Context.classes + all_contexts.remove(Build.InstallContext) + all_contexts.remove(Build.UninstallContext) + for k in ( + "--targets", + "--distcheck-args", + "--out", + "--prefix", + "--destdir", + "--bindir", + "--libdir", + "--msvc_version", + "--msvc_targets", + "--no-msvc-lazy", + "--force", + "--testcmd", + "--check-c-compiler", + ): + option = opt.parser.get_option(k) + if option: + opt.parser.remove_option(k) + + remaining_options = [] + for i in opt.parser.option_groups: + if i.title not in ( + "Installation and uninstallation options", + "Configuration options", + ): + remaining_options.append(i) + opt.parser.option_groups = remaining_options + + +def configure(cnf: ConfigurationContext): + """configures gcc for the host build (gcc) and cafeCC for the SPA build.""" + # copy environments + cnf.setenv("host") # gcc (native) + cnf.setenv("axivion") # cafeCC (SPA) + + # host + cnf.setenv("host") + cnf.load("python") + + cnf.define("FAS_ASSERT_LEVEL", 2) + cnf.define("FOXBMS_USES_FREERTOS", 1) + cnf.env.append_unique("CFLAGS", COMMON_CFLAGS) + cnf.env.append_value("INCLUDES", [cnf.path.find_node("support").abspath()]) + + cnf.options.check_c_compiler = "gcc" + cnf.load("compiler_c") + + if cnf.env.CC_NAME.lower() == "gcc": # test are only executable for gcc-builds + cnf.load("waf_unit_test") + + fragment = "#include \n\nint sum(int a, int b){\n return (a + b);}\n" + cnf.check(features="c cstlib", fragment=fragment) + fragment = "int main() {\n return 0;\n}" + cnf.check(features="c cprogram", fragment=fragment) + + # Axivion + cnf.setenv("axivion") + cnf.load("python") + + cnf.define("FAS_ASSERT_LEVEL", 2) + cnf.define("FOXBMS_USES_FREERTOS", 1) + cnf.env.append_unique("CFLAGS", COMMON_CFLAGS) + cnf.env.append_value("INCLUDES", [cnf.path.find_node("support").abspath()]) + + cnf.options.check_c_compiler = "gcc" + cnf.load("compiler_c") + cnf.env.append_unique("LINKFLAGS", ["-echo", "-larg", "--show_plan"]) + + cnf.find_program("axivion_config", var="AXIVION_CONFIG") + cnf.find_program("cafecc", var="AXIVION_CC") + cnf.find_program("irdump", var="AXIVION_IR_DUMP") + cnf.env.append_unique("AXIVION_IR_DUMP_ARGS", "-m") + + cnf.env.CC = cnf.env.AXIVION_CC + cnf.env.LINK_CC = cnf.env.AXIVION_CC + + fragment = "#include \n\nint sum(int a, int b){\n return (a + b);}\n" + cnf.check(features="c cstlib", fragment=fragment) + fragment = "int main() {\n return 0;\n}" + cnf.check(features="c cprogram", fragment=fragment) + + +def build(bld: BuildContext): + """High level definition of the build details""" + if not bld.variant: + supported_cmds = ", ".join([f"{bld.cmd}_{i}" for i in VARIANTS]).strip() + bld.fatal(f"supported build commands: {supported_cmds}") + + bld.env = bld.all_envs[bld.variant] + + # when cleaning(!), no further processing of needed + if not bld.cmd.startswith("build"): + return + + root = bld.root.find_dir(os.path.join(bld.path.abspath(), "..", "..")) + utr = bld.root.find_dir(os.path.join(str(root.abspath()), "build", "unit_test")) + + inc_unity = utr.find_dir("vendor/unity/src") + unity = "unity" + bld( + features="c", + source=[inc_unity.find_node("unity.c").relpath()], + includes=[inc_unity], + target="unity", + ) + + inc_cmock = utr.find_dir("vendor/cmock/src") + cmock = "cmock" + bld.objects( + source=[inc_cmock.find_node("cmock.c")], + includes=[inc_cmock, inc_unity], + target=cmock, + ) + + inc_c_exception = utr.find_dir("vendor/c_exception/lib") + c_exception = "CException" + bld.objects( + source=[inc_c_exception.find_node("CException.c")], + includes=[inc_c_exception], + target=c_exception, + ) + + units_under_test_file: dict = bld.path.find_node("build.json") + units_under_test = units_under_test_file.read_json() + err = 0 + listed_files = [] + for k, v in units_under_test.items(): + if not root.find_node(k): + err += 1 + Logs.error(f"Could not find source file '{k}'.") + else: + listed_files.append(k) + if err: + bld.fatal("Missing source files.") + + files = [] + for i in root.ant_glob("src/app/**/*.c"): + files.append(Path(i.path_from(root)).as_posix()) + if diff := set(files) - set(listed_files): + bld.fatal( + "The files in the sources tree do not match the files defined " + f"in the build configuration '{units_under_test_file.relpath()}':\n{', '.join(diff)}" + ) + for i, (k, v) in enumerate(units_under_test.items()): + if not k.endswith( # TODO remove this once it is working for all tests + ( + "/adc.c", + "/adi_ades1830_gpio_voltages.c", + "/crc.c", + "/foxmath.c", + "/algorithm.c", + "/algorithm_cfg.c", + "/moving_average.c", + "/soc_counting.c", + "/soc_debug.c", + "/soc_none.c", + "/soe_counting.c", + "/soe_debug.c", + "/os.c", + ) + ): + continue + test_base_name = k.rsplit("/", maxsplit=1) + test_runner = "/".join([f"test_{test_base_name[1]}.{i}.exe"]) + sources = [root.find_node(i) for i in v["sources"]] + defines = v.get("defines", []) + bld( + features="c", + source=sources, + defines=defines, + use=[unity, cmock, c_exception], + includes=[inc_c_exception, inc_cmock, inc_unity] + + [root.find_dir(i) for i in v["include"]], + target=f"objects-{i}", + idx=i, + ) + features = "c cprogram" + if bld.variant == "host": + features += " test" + bld( + features=features, + use=[f"objects-{i}", unity, cmock, c_exception], + includes=[inc_c_exception, inc_cmock, inc_unity] + + [root.find_dir(i) for i in v["include"]], + target=bld.path.find_or_declare(test_runner), + idx=i, + ) + + if bld.variant == "host": + bld.add_post_fun(waf_unit_test.summary) diff --git a/tests/variants/README.md b/tests/variants/README.md index a067c703..363b27b0 100644 --- a/tests/variants/README.md +++ b/tests/variants/README.md @@ -23,5 +23,5 @@ must be named: ``freertos_ltc-6813-1_vbb_cc-cc-tr-none_none-no-imd.json`` For more complex build variants a directory must be created the all required -files must be placed in that directory. See the library build in ``lib-build`` -to see how it can be done. +files must be placed in that directory. +See the library build in ``lib-build`` to see how it can be done. diff --git a/tests/variants/freertos_adi-ades1830_hbb_cc-cc-tr-none_none-no-imd.json b/tests/variants/freertos_adi-ades1830_hbb_cc-cc-tr-none_none-no-imd.json new file mode 100644 index 00000000..68864d6e --- /dev/null +++ b/tests/variants/freertos_adi-ades1830_hbb_cc-cc-tr-none_none-no-imd.json @@ -0,0 +1,31 @@ +{ + "slave-unit": { + "analog-front-end": { + "manufacturer": "adi", + "ic": "ades1830" + }, + "temperature-sensor": { + "manufacturer": "epcos", + "model": "b57251v5103j060", + "method": "polynomial" + } + }, + "application": { + "algorithm": { + "state-estimation": { + "soc": "counting", + "soe": "counting", + "sof": "trapezoid", + "soh": "none" + } + }, + "balancing-strategy": "history", + "insulation-monitoring-device": { + "manufacturer": "none", + "model": "" + } + }, + "rtos": { + "name": "freertos" + } +} diff --git a/tests/variants/freertos_adi-ades1830_vbb_cc-cc-tr-none_none-no-imd.json b/tests/variants/freertos_adi-ades1830_vbb_cc-cc-tr-none_none-no-imd.json new file mode 100644 index 00000000..c71b8868 --- /dev/null +++ b/tests/variants/freertos_adi-ades1830_vbb_cc-cc-tr-none_none-no-imd.json @@ -0,0 +1,31 @@ +{ + "slave-unit": { + "analog-front-end": { + "manufacturer": "adi", + "ic": "ades1830" + }, + "temperature-sensor": { + "manufacturer": "epcos", + "model": "b57251v5103j060", + "method": "polynomial" + } + }, + "application": { + "algorithm": { + "state-estimation": { + "soc": "counting", + "soe": "counting", + "sof": "trapezoid", + "soh": "none" + } + }, + "balancing-strategy": "voltage", + "insulation-monitoring-device": { + "manufacturer": "none", + "model": "" + } + }, + "rtos": { + "name": "freertos" + } +} diff --git a/tests/variants/freertos_ltc-6813-1_vbb_cc-cc-tr-none_none-no-imd.json b/tests/variants/freertos_ltc-6813-1_vbb_cc-cc-tr-none_none-no-imd.json new file mode 100644 index 00000000..66318ddd --- /dev/null +++ b/tests/variants/freertos_ltc-6813-1_vbb_cc-cc-tr-none_none-no-imd.json @@ -0,0 +1,31 @@ +{ + "slave-unit": { + "analog-front-end": { + "manufacturer": "ltc", + "ic": "6813-1" + }, + "temperature-sensor": { + "manufacturer": "epcos", + "model": "b57251v5103j060", + "method": "polynomial" + } + }, + "application": { + "algorithm": { + "state-estimation": { + "soc": "counting", + "soe": "counting", + "sof": "trapezoid", + "soh": "none" + } + }, + "balancing-strategy": "none", + "insulation-monitoring-device": { + "manufacturer": "none", + "model": "" + } + }, + "rtos": { + "name": "freertos" + } +} diff --git a/tests/variants/freertos_ti-dummy_vbb_cc-cc-tr-none_none-no-imd.json b/tests/variants/freertos_ti-dummy_vbb_cc-cc-tr-none_none-no-imd.json new file mode 100644 index 00000000..3fe4a0ac --- /dev/null +++ b/tests/variants/freertos_ti-dummy_vbb_cc-cc-tr-none_none-no-imd.json @@ -0,0 +1,31 @@ +{ + "slave-unit": { + "analog-front-end": { + "manufacturer": "ti", + "ic": "dummy" + }, + "temperature-sensor": { + "manufacturer": "epcos", + "model": "b57251v5103j060", + "method": "polynomial" + } + }, + "application": { + "algorithm": { + "state-estimation": { + "soc": "counting", + "soe": "counting", + "sof": "trapezoid", + "soh": "none" + } + }, + "balancing-strategy": "voltage", + "insulation-monitoring-device": { + "manufacturer": "none", + "model": "" + } + }, + "rtos": { + "name": "freertos" + } +} diff --git a/tests/variants/lib-build/lib-build_main.c b/tests/variants/lib-build/lib-build_main.c index b0789077..c52e390b 100644 --- a/tests/variants/lib-build/lib-build_main.c +++ b/tests/variants/lib-build/lib-build_main.c @@ -43,8 +43,8 @@ * @file lib-build_main.c * @author foxBMS Team * @date 2020-10-06 (date of creation) - * @updated 2023-02-23 (date of last update) - * @version v1.5.1 + * @updated 2023-10-12 (date of last update) + * @version v1.6.0 * @ingroup GENERAL * @prefix TODO * @@ -67,7 +67,7 @@ #include "diag.h" #include "dma.h" #include "libproject-example.h" -#include "masterinfo.h" +#include "master_info.h" #include "meas.h" #include "os.h" #include "spi.h" diff --git a/tools/README.md b/tools/README.md index 1c304166..2cb169c0 100644 --- a/tools/README.md +++ b/tools/README.md @@ -10,7 +10,7 @@ of foxBMS 2. | ``debugger/*`` | Configuration files for debugger settings. | | ``gui/*`` | foxBMS 2 GUI. | | ``ide/vscode/*`` | Configuration file templates for VS Code settings. | -| ``utils/*`` | Helper scripts for batch and shellscript. | +| ``utils/*`` | Helper scripts for batch and shell script. | | ``vendor/ceedling/*`` | Vendored ceedling files. | | ``waf-tools/*`` | Tools required for the build toolchain that do not come bundled with the default waf binary. | | ``waf`` | The build tool binary. | diff --git a/tools/crc/build-crc-snippets.bat b/tools/crc/build-crc-snippets.bat new file mode 100644 index 00000000..30d5dc72 --- /dev/null +++ b/tools/crc/build-crc-snippets.bat @@ -0,0 +1,74 @@ +@REM Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +@REM All rights reserved. +@REM +@REM SPDX-License-Identifier: BSD-3-Clause +@REM +@REM Redistribution and use in source and binary forms, with or without +@REM modification, are permitted provided that the following conditions are met: +@REM +@REM 1. Redistributions of source code must retain the above copyright notice, this +@REM list of conditions and the following disclaimer. +@REM +@REM 2. Redistributions in binary form must reproduce the above copyright notice, +@REM this list of conditions and the following disclaimer in the documentation +@REM and/or other materials provided with the distribution. +@REM +@REM 3. Neither the name of the copyright holder nor the names of its +@REM contributors may be used to endorse or promote products derived from +@REM this software without specific prior written permission. +@REM +@REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +@REM AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +@REM IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +@REM DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +@REM FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +@REM DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +@REM SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +@REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +@REM OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +@REM OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +@REM +@REM We kindly request you to use one or more of the following phrases to refer to +@REM foxBMS in your hardware, software, documentation or advertising materials: +@REM +@REM - "This product uses parts of foxBMS®" +@REM - "This product includes parts of foxBMS®" +@REM - "This product is derived from foxBMS®" + +@SETLOCAL EnableExtensions EnableDelayedExpansion + +@PUSHD %~dp0 + +@FOR /F "usebackq tokens=*" %%A in ("%~dp0\..\..\conf\env\paths_win32.txt") do @( + @IF EXIST %%A ( + @CALL SET "NewPath=%%NewPath%%;%%A" + ) +) + +@IF DEFINED NewPath ( + @SET "PATH=%NewPath:~1%;%PATH%" +) + +@gcc %~dp0crc-15_0xc599.c -o%~dp0crc-15_0xc599.exe +@IF %ERRORLEVEL% neq 0 ( + @POPD + @EXIT /b 1 +) +@gcc %~dp0crc-10_0x48f.c -o%~dp0crc-10_0x48f.exe +@IF %ERRORLEVEL% neq 0 ( + @POPD + @EXIT /b 1 +) +@ECHO Running '%~dp0crc-15_0xc599' +@%~dp0crc-15_0xc599.exe +@IF %ERRORLEVEL% neq 0 ( + @POPD + @EXIT /b 1 +) +@ECHO. +@ECHO Running '%~dp0crc-10_0x48f' +@%~dp0crc-10_0x48f.exe +@IF %ERRORLEVEL% neq 0 ( + @POPD + @EXIT /b 1 +) diff --git a/tools/crc/crc-10_0x48f.c b/tools/crc/crc-10_0x48f.c new file mode 100644 index 00000000..a2ed7849 --- /dev/null +++ b/tools/crc/crc-10_0x48f.c @@ -0,0 +1,92 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file crc-10_0x48f.c + * @author foxBMS Team + * @date 2019-12-12 (date of creation) + * @updated 2023-09-05 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix NONE + * + * @brief CRC10 0x48F + * @details The CRC10 0x48F polynomial lookup table implementation + * + */ + +/*========== Includes =======================================================*/ +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ +int main() { + uint16_t adi_crc10Table[256]; + for (uint16_t i = 0u; i <= 255u; i++) { + uint16_t data = i << (10u - 8u); + for (uint8_t bit = 0u; bit < 8u; bit++) { + if ((data & (1u << (10u - 1u))) != 0u) { + data <<= 1; + data ^= 0x48Fu; + } else { + data <<= 1; + } + } + adi_crc10Table[i] = data & 0x3FFu; + printf("0x%04Xu, ", adi_crc10Table[i]); + } + printf("\n"); + return 0; +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/tools/crc/crc-10_0x48f.md b/tools/crc/crc-10_0x48f.md index 34f00033..0c577c42 100644 --- a/tools/crc/crc-10_0x48f.md +++ b/tools/crc/crc-10_0x48f.md @@ -8,7 +8,7 @@ (bin) 1 0 0 1 0 0 0 1 1 1 1 (hex) 0x48F ``` -- The resulting CRC-10 - 0x48F lookup table is then (generated by`crc_init.py --polynomial 0x48F --width 10`): +- The resulting CRC-10 - 0x48F lookup table is then (generated by `crc_init.py --polynomial 0x48F --width 10`): ```c /* precomputed CRC-10 Table */ static const unsigned int crc10Table[256] = { @@ -33,3 +33,5 @@ 0x12Fu, 0x1A0u, 0x031u, 0x0BEu, }; ``` +- A C-implementation to precompute this table is available in + [crc-10_0x48f.c](./crc-10_0x48f.c) diff --git a/tools/crc/crc-15_0xc599.c b/tools/crc/crc-15_0xc599.c new file mode 100644 index 00000000..d06c34ad --- /dev/null +++ b/tools/crc/crc-15_0xc599.c @@ -0,0 +1,92 @@ +/** + * + * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * We kindly request you to use one or more of the following phrases to refer to + * foxBMS in your hardware, software, documentation or advertising materials: + * + * - ″This product uses parts of foxBMS®″ + * - ″This product includes parts of foxBMS®″ + * - ″This product is derived from foxBMS®″ + * + */ + +/** + * @file crc-15_0xc599.c + * @author foxBMS Team + * @date 2019-12-12 (date of creation) + * @updated 2023-09-05 (date of last update) + * @version v1.6.0 + * @ingroup DRIVERS + * @prefix NONE + * + * @brief CRC15 0xC599 + * @details The CRC15 0xC599 polynomial lookup table implementation + * + */ + +/*========== Includes =======================================================*/ +#include +#include + +/*========== Macros and Definitions =========================================*/ + +/*========== Static Constant and Variable Definitions =======================*/ + +/*========== Extern Constant and Variable Definitions =======================*/ + +/*========== Static Function Prototypes =====================================*/ + +/*========== Static Function Implementations ================================*/ + +/*========== Extern Function Implementations ================================*/ +int main() { + uint16_t adi_crc15Table[256]; + for (uint16_t i = 0u; i <= 255u; i++) { + uint16_t data = i << (15u - 8u); + for (uint8_t bit = 0u; bit < 8u; bit++) { + if ((data & (1u << (15u - 1u))) != 0u) { + data <<= 1; + data ^= 0xC599u; + } else { + data <<= 1; + } + } + adi_crc15Table[i] = data & 0x7FFFu; + printf("0x%04Xu, ", adi_crc15Table[i]); + } + printf("\n"); + return 0; +} + +/*========== Externalized Static Function Implementations (Unit Test) =======*/ +#ifdef UNITY_UNIT_TEST +#endif diff --git a/tools/crc/crc-15_0xc599.md b/tools/crc/crc-15_0xc599.md index 2546d2d4..5b167a0b 100644 --- a/tools/crc/crc-15_0xc599.md +++ b/tools/crc/crc-15_0xc599.md @@ -8,7 +8,7 @@ (bin) 1 1 0 0 0 1 0 1 1 0 0 1 1 0 0 1 (hex) 0xC599 ``` -- The resulting CRC-15 - 0xC599 lookup table is then (generated by`crc_init.py --polynomial 0xC599 --width 15`): +- The resulting CRC-15 - 0xC599 lookup table is then (generated by `crc_init.py --polynomial 0xC599 --width 15`): ```c /* precomputed CRC-15 Table */ @@ -35,3 +35,5 @@ 0x7492u, 0x5368u, 0x16F1u, 0x1DC3u, 0x585Au, 0x0BA7u, 0x4E3Eu, 0x450Cu, 0x0095u, }; ``` +- A C-implementation to precompute this table is available in + [crc-15_0xc599.c](./crc-15_0xc599.c) diff --git a/tools/dbc/.gitignore b/tools/dbc/.gitignore index d71da95d..2d3a953f 100644 --- a/tools/dbc/.gitignore +++ b/tools/dbc/.gitignore @@ -1,2 +1,3 @@ +combined_symbol_file.txt multiplexed_cell_voltages_for_sym_file.txt multiplexed_cell_temperatures_for_sym_file.txt diff --git a/tools/dbc/foxbms.dbc b/tools/dbc/foxbms.dbc index d9da79b9..ba49486c 100644 --- a/tools/dbc/foxbms.dbc +++ b/tools/dbc/foxbms.dbc @@ -979,6 +979,7 @@ SG_ foxBMS_GetMcuLotNumber m0 : 10|1@0+ (1,0) [0|1] "" Vector__XXX SG_ foxBMS_GetBmsSoftwareVersion m0 : 8|1@0+ (1,0) [0|1] "" Vector__XXX SG_ foxBMS_GetMcuUniqueDieId m0 : 9|1@0+ (1,0) [0|1] "" Vector__XXX SG_ foxBMS_GetMcuWaferInformation m0 : 11|1@0+ (1,0) [0|1] "" Vector__XXX +SG_ foxBMS_GetCommitHash m0 : 12|1@1+ (1,0) [0|1] "" Vector__XXX SG_ foxBMS_TriggerSoftwareReset m2 : 39|1@0+ (1,0) [0|1] "" Vector__XXX SG_ InitializeFram m3 : 27|1@0+ (1,0) [0|1] "" Vector__XXX SG_ foxBMS_RequestRtcTime m4 : 8|1@0+ (1,0) [0|1] "" Vector__XXX @@ -1100,6 +1101,7 @@ SG_ GetMonth m4 : 47|4@0+ (1,0) [0|15] "" Vector__XXX SG_ GetSeconds m4 : 8|6@0+ (1,0) [0|63] "" Vector__XXX SG_ GetWeekday m4 : 39|3@0+ (1,0) [0|7] "" Vector__XXX SG_ GetYear m4 : 43|7@0+ (1,0) [0|127] "" Vector__XXX +SG_ shortHash m5 : 15|56@0+ (1,0) [0|0] "" Vector__XXX BO_ 513 foxBMS_UnsupportedMultiplexerVal: 8 Vector__XXX @@ -1107,21 +1109,34 @@ SG_ foxBMS_MessageId : 7|32@0+ (1,0) [0|1] "" Vector__XXX SG_ foxBMS_MultiplexerValue : 39|32@0+ (1,0) [0|1] "" Vector__XXX -CM_ BO_ 546 "(in:can_cbs_tx_system-values.c:CANTX_PackValues, fv:tx)"; +BO_ 255 foxBMS_FatalErrors: 8 Vector__XXX +SG_ foxBMS_FatalErrors_Mux M : 7|8@0+ (1,0) [0|0] "" Vector__XXX + + +BO_ 964 foxBMS_AerosolSensor: 8 Vector__XXX +SG_ particulate_matter_concentration : 7|16@0+ (1,0) [0|65535] "" Vector__XXX +SG_ low_power_mode_wake_up_threshold : 23|16@0+ (1,0) [0|65535] "" Vector__XXX +SG_ sensor_status : 34|3@0+ (1,0) [0|7] "" Vector__XXX +SG_ sensor_faults : 39|5@0+ (1,0) [0|31] "" Vector__XXX +SG_ rolling_counter : 42|3@0+ (1,0) [0|7] "" Vector__XXX +SG_ CRC_check_code : 63|8@0+ (1,0) [0|255] "" Vector__XXX + + +CM_ BO_ 546 "(in:can_cbs_tx_pack-values-p0.c:CANTX_PackValues, fv:tx)"; CM_ SG_ 546 foxBMS_packCurrent "Battery pack current"; CM_ SG_ 546 foxBMS_batteryVoltage "Battery voltage between negative and positive pole of the battery"; CM_ SG_ 546 foxBMS_busVoltage "Battery voltage between negative pole and after main positive contactor"; CM_ SG_ 546 foxBMS_packPower "Battery power"; -CM_ BO_ 548 "(in:can_cbs_tx_limit-values.c:CANTX_LimitValues, fv:tx)"; +CM_ BO_ 548 "(in:can_cbs_tx_pack-limits.c:CANTX_LimitValues, fv:tx)"; CM_ SG_ 548 foxBMS_maxChargeCurrent "Maximum battery pack charge current"; CM_ SG_ 548 foxBMS_maxDischargeCurrent "Maximum battery pack discharge current"; -CM_ BO_ 547 "(in:can_cbs_tx_minimum-maximum-values.c:CANTX_MinimumMaximumValues, fv:tx)"; +CM_ BO_ 547 "(in:can_cbs_tx_pack-minimum-maximum-values.c:CANTX_MinimumMaximumValues, fv:tx)"; CM_ SG_ 547 foxBMS_minimumCellVoltage "Minimum cell voltage of all connected strings, if no string connected maximum value of whole system is transmitted"; CM_ SG_ 547 foxBMS_maximumCellVoltage "Maximum cell voltage of all connected strings, if no string connected maximum value of whole system is transmitted"; CM_ SG_ 547 foxBMS_maximumCellTemp "Maximum cell temperature of all connected strings, if no string connected maximum value of whole system is transmitted"; CM_ SG_ 547 foxBMS_minimumCellTemp "Minium cell temperature of all connected string, if no string connected maximum value of whole system is transmitted"; -CM_ BO_ 640 "Message contains string voltage, current and power (in:can_cbs_tx_system-values.c:CANTX_StringValuesP0, fv:tx)"; -CM_ BO_ 643 "Message contains energy counting value (in:can_cbs_tx_system-values.c:CANTX_StringValuesP1, fv:tx)"; +CM_ BO_ 640 "Message contains string voltage, current and power (in:can_cbs_tx_pack-values-p0.c:CANTX_StringValuesP0, fv:tx)"; +CM_ BO_ 643 "Message contains energy counting value (in:can_cbs_tx_pack-values-p0.c:CANTX_StringValuesP1, fv:tx)"; CM_ SG_ 643 foxBMS_String0EnergyCount "Current sensor string 0 energy counting value"; CM_ BO_ 549 "(in:can_cbs_tx_pack-state-estimation.c:CANTX_PackStateEstimation, fv:tx)"; CM_ SG_ 549 foxBMS_packSoc "SOC currently connected to HV bus (100% if all strings connected and all strings at 100%)"; @@ -1129,7 +1144,7 @@ CM_ SG_ 549 foxBMS_packSoe "SOE currently connected to HV bus (100% if all strin CM_ SG_ 549 foxBMS_packEnergy "Energy left in Wh that is currently connected to HV bus"; CM_ BO_ 576 "(in:can_cbs_tx_cell-voltages.c:CANTX_CellVoltages, fv:tx)"; CM_ BO_ 592 "(in:can_cbs_tx_cell-temperatures.c:CANTX_CellTemperatures, fv:tx)"; -CM_ BO_ 560 "(in:can_cbs_rx_state-request.c:CANRX_BmsStateRequest, fv:rx)"; +CM_ BO_ 560 "(in:can_cbs_rx_bms-state-request.c:CANRX_BmsStateRequest, fv:rx)"; CM_ SG_ 560 foxBMS_modeRequest "0x0: Disconnect strings from HV bus, 0x01: Connect strings to HV bus to start discharge, 0x02: Connect strings to HV bus to start charging"; CM_ SG_ 560 foxBMS_activateBalancing "0: Deactivate balancing, 1: Activate balancing"; CM_ SG_ 560 foxBMS_balancingThreshold "Required voltage difference to minimum cell voltage to activate balancing"; @@ -1139,7 +1154,7 @@ CM_ SG_ 560 foxBMS_chargerConnected "0x00: charger not connected, 0x01: charger CM_ SG_ 560 foxBMS_disableInsulationMon "0x00: Check battery system insulation, 0x01: Do not check insulation of battery system"; CM_ SG_ 560 foxBMS_heaterOverride_ON "0: no override active, 1: override active -> force heater on"; CM_ SG_ 560 foxBMS_heaterOverride_OFF "0: no override active, 1: override active -> force heater off"; -CM_ BO_ 544 "Message contains foxBMS state (in:can_cbs_tx_state.c:CANTX_BmsState, fv:tx)"; +CM_ BO_ 544 "Message contains foxBMS state (in:can_cbs_tx_bms-state.c:CANTX_BmsState, fv:tx)"; CM_ SG_ 544 foxBMS_generalError "0x00: No error detected, 0x01: Error detected"; CM_ SG_ 544 foxBMS_generalWarning "0x00: No warning detected, 0x01: Warning detected"; CM_ SG_ 544 foxBMS_Error_dieTemperatureMCU "0x00: No error, 0x01: Error detected"; @@ -1161,13 +1176,13 @@ CM_ SG_ 544 foxBMS_Error_PackOvercur_Dischrg "0x00: No error, 0x01: Error detect CM_ SG_ 544 foxBMS_SysMonError "If this bit is set, it indicates that a task has violated its timing requirements."; CM_ SG_ 544 foxBMS_alertFlag "foxBMS Alter flag: 0x00: No error, 0x01: Alert flag set"; CM_ SG_ 544 foxBMS_NvramCrcError "0x00: No NVRAM CRC Error detected, 0x01: NVRAM CRC Error detected"; -CM_ BO_ 545 "Message contains string related error and warning flags (in:can_cbs_tx_state.c:CANTX_StringState, fv:tx)"; +CM_ BO_ 545 "Message contains string related error and warning flags (in:can_cbs_tx_bms-state.c:CANTX_StringState, fv:tx)"; CM_ SG_ 545 String0_stringConnected "0x00: String not connected, 0x01: String connected to HV bus"; CM_ SG_ 545 String0_balancing_active "0x00: No balancing active, 0x01: Balancing in this string active"; -CM_ SG_ 545 String0_Err_overtemp_charge "0x00: No error, 0x01: Error: Flag will be set if maximum cell temperature is above 45 degree celsius."; -CM_ SG_ 545 String0_Err_undertemp_charge "0x00: No error, 0x01: Error: Flag will be set if minimum cell temperature is below 0 degree celsius."; -CM_ SG_ 545 String0_Err_overtemp_discharge "0x00: No error, 0x01: Error: Flag will be set if maximum cell temperature is above 60 degree celsius."; -CM_ SG_ 545 String0_Err_undertemp_discharge "0x00: No error, 0x01: Error: Flag will be set if minimum cell temperature is below -20 degree celsius."; +CM_ SG_ 545 String0_Err_overtemp_charge "0x00: No error, 0x01: Error: Flag will be set if maximum cell temperature is above 45 degree Celsius."; +CM_ SG_ 545 String0_Err_undertemp_charge "0x00: No error, 0x01: Error: Flag will be set if minimum cell temperature is below 0 degree Celsius."; +CM_ SG_ 545 String0_Err_overtemp_discharge "0x00: No error, 0x01: Error: Flag will be set if maximum cell temperature is above 60 degree Celsius."; +CM_ SG_ 545 String0_Err_undertemp_discharge "0x00: No error, 0x01: Error: Flag will be set if minimum cell temperature is below -20 degree Celsius."; CM_ SG_ 545 String0_Err_Overcurrent_charge "0x00: No error, 0x01: Error: Flag will be set if string charge current is above 30400mA."; CM_ SG_ 545 String0_Err_Overcurre_discharge "0x00: No error, 0x01: Error: Flag will be set if discharge current is above maximum string current."; CM_ SG_ 545 String0_Err_Overvoltage "0x00: No error, 0x01: Error: Flag will be set if maximum cell voltage is above 4200mV."; @@ -1194,7 +1209,7 @@ CM_ SG_ 545 String0_Err_CS_energyCountMeas "0x00: No error, 0x01: Error"; CM_ SG_ 545 String0_Err_plaus_volt_spread "0x00: No error, 0x01: Error"; CM_ SG_ 545 String0_Err_plaus_temp_spread "0x00: No error, 0x01: Error"; CM_ SG_ 545 String0_Err_negativeContactor "0x00: No error, 0x01: Error"; -CM_ BO_ 641 "Message contains minimum and maximum cell temperature and cell voltage values of respective string (in:can_cbs_tx_minimum-maximum-values.c:CANTX_StringMinimumMaximumValues, fv:tx)"; +CM_ BO_ 641 "Message contains minimum and maximum cell temperature and cell voltage values of respective string (in:can_cbs_tx_pack-minimum-maximum-values.c:CANTX_StringMinimumMaximumValues, fv:tx)"; CM_ SG_ 641 String0_minimumCellVoltage "Minimum cell voltage in this string"; CM_ SG_ 641 String0_maximumCellVoltage "Maximum cell voltage in this string"; CM_ SG_ 641 String0_maximumCellTemperature "Maximum cell temperature in this string"; @@ -1211,7 +1226,7 @@ CM_ BO_ 1317 "Current sensor string 0: temperature (in:can_cbs_rx_current-sensor CM_ BO_ 1318 "Current sensor string 0: power (in:can_cbs_rx_current-sensor.c:CANRX_CurrentSensor, fv:rx); Isabellenhuette data sheet name: IVT0_Msg_Result_W"; CM_ BO_ 1319 "Current sensor string 0: coulomb counting (in:can_cbs_rx_current-sensor.c:CANRX_CurrentSensor, fv:rx); Isabellenhuette data sheet name: IVT0_Msg_Result_As"; CM_ BO_ 1320 "Current sensor string 0: energy counting (in:can_cbs_rx_current-sensor.c:CANRX_CurrentSensor, fv:rx); Isabellenhuette data sheet name: IVT0_Msg_Result_Wh"; -CM_ BO_ 550 "Transmits details on flags transmitted by foxBMS_State (in:can_cbs_tx_state.c:CANTX_BmsStateDetails, fv:tx)"; +CM_ BO_ 550 "Transmits details on flags transmitted by foxBMS_State (in:can_cbs_tx_bms-state.c:CANTX_BmsStateDetails, fv:tx)"; CM_ SG_ 550 foxBMS_TimingViolationEngine "Indicates whether the timing of the engine task has been violated."; CM_ SG_ 550 foxBMS_TimingViolation1ms "Indicates whether the timing of the 1ms task has been violated."; CM_ SG_ 550 foxBMS_TimingViolation10ms "Indicates whether the timing of the 10ms task has been violated."; @@ -1228,15 +1243,19 @@ CM_ SG_ 551 MCU_xWaferCoordinate "x coordinate of the MCU die on the wafer (read CM_ SG_ 551 MCU_yWaferCoordinate "y coordinate of the MCU die on the wafer (read from DIEIDL register)"; CM_ SG_ 551 MCU_LotNumber "lot number of the MCU (read from DIEIDH register)"; CM_ SG_ 551 MCU_uniqueId "Content of Device Identification Register (DEVID)"; -CM_ BO_ 513 "(in:can_cbs_tx_unsupported-message.c:CANTX_UnsupportedMultiplexerValue, fv:tx)"; +CM_ BO_ 513 "(in:can_cbs_tx_debug-unsupported-multiplexer-values.c:CANTX_UnsupportedMultiplexerValue, fv:tx)"; +CM_ BO_ 255 "(in:can_cbs_tx_crash-dump.c:CANTX_SendReasonsForFatalErrors, fv:tx)"; +CM_ BO_ 964 "(in:can_cbs_rx_aerosol-sensor.c:CANRX_AerosolSensor, fv:rx)"; BA_DEF_ "BusType" STRING ; BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535; BA_DEF_ SG_ "GenSigStartValue" FLOAT -3.4E+038 3.4E+038; +BA_DEF_ SG_ "SigType" ENUM "Default","Range","RangeSigned","ASCII","Discrete","Control","ReferencePGN","DTC","StringDelimiter","StringLength","StringLengthControl","MessageCounter","MessageChecksum"; BA_DEF_DEF_ "BusType" "CAN"; BA_DEF_DEF_ "GenMsgCycleTime" 0; BA_DEF_DEF_ "GenSigStartValue" 0; +BA_DEF_DEF_ "SigType" "Default"; BA_ "BusType" "CAN"; @@ -1253,6 +1272,7 @@ BA_ "GenMsgCycleTime" BO_ 545 100; BA_ "GenMsgCycleTime" BO_ 641 100; BA_ "GenMsgCycleTime" BO_ 642 1000; BA_ "GenMsgCycleTime" BO_ 550 1000; +BA_ "GenMsgCycleTime" BO_ 964 1000; BA_ "GenSigStartValue" SG_ 546 foxBMS_packCurrent 0; BA_ "GenSigStartValue" SG_ 546 foxBMS_batteryVoltage 0; @@ -2178,6 +2198,7 @@ BA_ "GenSigStartValue" SG_ 512 foxBMS_GetMcuLotNumber 0; BA_ "GenSigStartValue" SG_ 512 foxBMS_GetBmsSoftwareVersion 0; BA_ "GenSigStartValue" SG_ 512 foxBMS_GetMcuUniqueDieId 0; BA_ "GenSigStartValue" SG_ 512 foxBMS_GetMcuWaferInformation 0; +BA_ "GenSigStartValue" SG_ 512 foxBMS_GetCommitHash 0; BA_ "GenSigStartValue" SG_ 512 foxBMS_TriggerSoftwareReset 0; BA_ "GenSigStartValue" SG_ 512 InitializeFram 0; BA_ "GenSigStartValue" SG_ 512 foxBMS_RequestRtcTime 0; @@ -2270,6 +2291,14 @@ BA_ "GenSigStartValue" SG_ 551 GetWeekday 0; BA_ "GenSigStartValue" SG_ 551 GetYear 0; BA_ "GenSigStartValue" SG_ 513 foxBMS_MessageId 0; BA_ "GenSigStartValue" SG_ 513 foxBMS_MultiplexerValue 0; +BA_ "GenSigStartValue" SG_ 964 particulate_matter_concentration 0; +BA_ "GenSigStartValue" SG_ 964 low_power_mode_wake_up_threshold 0; +BA_ "GenSigStartValue" SG_ 964 sensor_status 0; +BA_ "GenSigStartValue" SG_ 964 sensor_faults 0; +BA_ "GenSigStartValue" SG_ 964 rolling_counter 0; +BA_ "GenSigStartValue" SG_ 964 CRC_check_code 0; + +BA_ "SigType" SG_ 551 shortHash 3; VAL_ 640 foxBMS_StringValuesP0_Mux 0 "mux_valuesP0String_0" ; VAL_ 643 foxBMS_StringValuesP1_Mux 0 "mux_valuesP1String_0" ; @@ -2280,7 +2309,8 @@ VAL_ 545 foxBMS_StringState_Mux 0 "mux_stateString0" ; VAL_ 641 foxBMS_StringMinMaxValues_Mux 0 "mux_minMaxValuesString0" ; VAL_ 642 foxBMS_StringStateEstimation_Mux 0 "mux_String0_SOC_SOE" ; VAL_ 512 foxBMS_Debug_Mux 1 "foxBMS_Rtc" 0 "foxBMS_VersionInfo" 2 "foxBMS_SoftwareReset" 3 "foxBMS_FramInitialization" 4 "foxBMS_TimeInfo" ; -VAL_ 551 foxBMS_DebugResponse_Mux 3 "foxBMS_McuWaferInformation" 2 "foxBMS_McuLotNumber" 1 "foxBMS_McuUniqueDieId" 0 "foxBMS_BmsSoftwareVersionInfo" 15 "foxBMS_BootInformation" 4 "foxBMS_RtcTime" ; +VAL_ 551 foxBMS_DebugResponse_Mux 3 "foxBMS_McuWaferInformation" 2 "foxBMS_McuLotNumber" 1 "foxBMS_McuUniqueDieId" 0 "foxBMS_BmsSoftwareVersionInfo" 15 "foxBMS_BootInformation" 4 "foxBMS_RtcTime" 5 "foxBMS_CommitHash" ; +VAL_ 255 foxBMS_FatalErrors_Mux 0 "StackOverflow" ; VAL_ 560 foxBMS_modeRequest 0 "Standby" 1 "Discharge" 2 "Charge" ; VAL_ 544 foxBMS_State 0 "BMS_UNINITIALIZED" 1 "BMS_INITIALIZATION" 2 "BMS_INITIALIZED" 3 "BMS_IDLE" 4 "BMS_OPEN_CONTACTORS" 5 "BMS_STANDBY" 6 "BMS_PRECHARGE" 7 "BMS_NORMAL" 8 "BMS_DISCHARGE" 9 "BMS_CHARGE" 10 "BMS_ERROR" 11 "BMS_UNDEFINED" ; VAL_ 544 foxBMS_Error_dieTemperatureMCU 0 "No Error" 1 "Error" ; @@ -2292,8 +2322,8 @@ VAL_ 545 String0_Err_positiveContactor 0 "No Error" 1 "Error" ; VAL_ 545 String0_fuseBlown 0 "Fuse okay" 1 "Fuse blown" ; VAL_ 545 String0_Err_negativeContactor 0 "No Error" 1 "Error" ; VAL_ 512 SetWeekday 1 "Monday" 2 "Tuesday" 3 "Wednesday" 4 "Thursday" 5 "Friday" 6 "Saturday" 0 "Sunday" ; -VAL_ 512 SetMonth 1 "January" 2 "February" 3 "March" 4 "Mai" 5 "April" 6 "June" 7 "July" 8 "August" 9 "September" 10 "October" 11 "November" 12 "December" ; +VAL_ 512 SetMonth 1 "January" 2 "February" 3 "March" 4 "April" 5 "May" 6 "June" 7 "July" 8 "August" 9 "September" 10 "October" 11 "November" 12 "December" ; VAL_ 512 foxBMS_TriggerSoftwareReset 0 "NO_SOFTWARE_RESET" 1 "SOFTWARE_RESET" ; VAL_ 512 InitializeFram 0 "NO_FRAM_INITIALIZATION" 1 "FRAM_INITIALIZATION" ; -VAL_ 551 GetMonth 1 "January" 2 "February" 3 "March" 4 "Mai" 5 "April" 6 "June" 7 "July" 8 "August" 9 "September" 10 "October" 11 "November" 12 "December" ; +VAL_ 551 GetMonth 1 "January" 2 "February" 3 "March" 4 "April" 5 "May" 6 "June" 7 "July" 8 "August" 9 "September" 10 "October" 11 "November" 12 "December" ; VAL_ 551 GetWeekday 1 "Monday" 2 "Tuesday" 3 "Wednesday" 4 "Thursday" 5 "Friday" 6 "Saturday" 0 "Sunday" ; diff --git a/tools/dbc/foxbms.sym b/tools/dbc/foxbms.sym index e9709f07..573f6905 100644 --- a/tools/dbc/foxbms.sym +++ b/tools/dbc/foxbms.sym @@ -21,13 +21,13 @@ Enum=foxBMS_RtcWeekday(1="Monday", 2="Tuesday", 3="Wednesday", 4="Thursday", 5=" Enum=foxBMS_SoftwareReset(0="NO_SOFTWARE_RESET", // Do not trigger a software reset 1="SOFTWARE_RESET") // Trigger a software reset Enum=foxBMS_FramInitialization(0="NO_FRAM_INITIALIZATION", 1="FRAM_INITIALIZATION") -Enum=foxBMS_RtcMonth(1="January", 2="February", 3="March", 4="Mai", 5="April", 6="June", 7="July", 8="August", +Enum=foxBMS_RtcMonth(1="January", 2="February", 3="March", 4="April", 5="May", 6="June", 7="July", 8="August", 9="September", 10="October", 11="November", 12="December") {SENDRECEIVE} [foxBMS_PackValues] -ID=222h // (in:can_cbs_tx_system-values.c:CANTX_PackValues, fv:tx) +ID=222h // (in:can_cbs_tx_pack-values-p0.c:CANTX_PackValues, fv:tx) Len=8 CycleTime=100 -p Var=foxBMS_packCurrent signed 46,18 -m /u:A /f:0.01 // Battery pack current @@ -36,7 +36,7 @@ Var=foxBMS_busVoltage unsigned 14,14 -m /u:V /f:0.1 // Battery voltage between n Var=foxBMS_packPower signed 28,18 -m /u:kW /f:0.01 // Battery power [foxBMS_LimitValues] -ID=224h // (in:can_cbs_tx_limit-values.c:CANTX_LimitValues, fv:tx) +ID=224h // (in:can_cbs_tx_pack-limits.c:CANTX_LimitValues, fv:tx) Len=8 CycleTime=100 -p Var=foxBMS_maxChargeCurrent unsigned 12,12 -m /u:A /f:0.25 // Maximum battery pack charge current @@ -47,7 +47,7 @@ Var=foxBMS_maxBatteryVoltage unsigned 48,8 -m /u:V /f:4 Var=foxBMS_minBatteryVoltage unsigned 56,8 -m /u:V /f:4 [foxBMS_MinimumMaximumValues] -ID=223h // (in:can_cbs_tx_minimum-maximum-values.c:CANTX_MinimumMaximumValues, fv:tx) +ID=223h // (in:can_cbs_tx_pack-minimum-maximum-values.c:CANTX_MinimumMaximumValues, fv:tx) Len=8 CycleTime=100 -p Var=foxBMS_minimumCellVoltage unsigned 13,13 -m /u:mV // Minimum cell voltage of all connected strings, if no string connected maximum value of whole system is transmitted @@ -58,7 +58,7 @@ Var=foxBMS_inletTemperature signed 32,8 -m /u:degC Var=foxBMS_outletTemperature signed 40,8 -m /u:degC [foxBMS_StringValuesP0] -ID=280h // Message contains string voltage, current and power (in:can_cbs_tx_system-values.c:CANTX_StringValuesP0, fv:tx) +ID=280h // Message contains string voltage, current and power (in:can_cbs_tx_pack-values-p0.c:CANTX_StringValuesP0, fv:tx) Len=8 CycleTime=100 -p Mux=mux_valuesP0String_0 0,3 0 -m @@ -67,7 +67,7 @@ Var=foxBMS_String0Voltage unsigned 3,17 -m /u:V /f:0.01 Var=foxBMS_String0Power signed 38,18 -m /u:kW /f:0.01 [foxBMS_StringValuesP1] -ID=283h // Message contains energy counting value (in:can_cbs_tx_system-values.c:CANTX_StringValuesP1, fv:tx) +ID=283h // Message contains energy counting value (in:can_cbs_tx_pack-values-p0.c:CANTX_StringValuesP1, fv:tx) Len=8 CycleTime=100 -p Mux=mux_valuesP1String_0 0,4 0 -m @@ -1297,7 +1297,7 @@ Var=cellTemperature_178 signed 48,8 -m /u:degC Var=cellTemperature_179 signed 56,8 -m /u:degC [foxBMS_BmsStateRequest] -ID=230h // (in:can_cbs_rx_state-request.c:CANRX_BmsStateRequest, fv:rx) +ID=230h // (in:can_cbs_rx_bms-state-request.c:CANRX_BmsStateRequest, fv:rx) Len=8 Var=foxBMS_modeRequest unsigned 6,2 -m /e:foxBMS_ModeRequest // 0x0: Disconnect strings from HV bus, 0x01: Connect strings to HV bus to start discharge, 0x02: Connect strings to HV bus to start charging Var=foxBMS_activateBalancing bit 15,1 -m // 0: Deactivate balancing, 1: Activate balancing @@ -1310,7 +1310,7 @@ Var=foxBMS_heaterOverride_ON bit 1,1 -m // 0: no override active, 1: override ac Var=foxBMS_heaterOverride_OFF bit 0,1 -m // 0: no override active, 1: override active -> force heater off [foxBMS_BmsState] -ID=220h // Message contains foxBMS state (in:can_cbs_tx_state.c:CANTX_BmsState, fv:tx) +ID=220h // Message contains foxBMS state (in:can_cbs_tx_bms-state.c:CANTX_BmsState, fv:tx) Len=8 CycleTime=100 -p Var=foxBMS_State unsigned 4,4 -m /e:foxBMS_State @@ -1340,16 +1340,16 @@ Var=foxBMS_alertFlag bit 28,1 -m /e:foxBMS_ErrorFlag // foxBMS Alter flag: 0x00: Var=foxBMS_NvramCrcError bit 27,1 -m /e:foxBMS_ErrorFlag // 0x00: No NVRAM CRC Error detected, 0x01: NVRAM CRC Error detected [foxBMS_StringState] -ID=221h // Message contains string related error and warning flags (in:can_cbs_tx_state.c:CANTX_StringState, fv:tx) +ID=221h // Message contains string related error and warning flags (in:can_cbs_tx_bms-state.c:CANTX_StringState, fv:tx) Len=8 CycleTime=100 -p Mux=mux_stateString0 4,4 0 -m Var=String0_stringConnected bit 3,1 -m // 0x00: String not connected, 0x01: String connected to HV bus Var=String0_balancing_active bit 2,1 -m // 0x00: No balancing active, 0x01: Balancing in this string active -Var=String0_Err_overtemp_charge bit 15,1 -m // 0x00: No error, 0x01: Error: Flag will be set if maximum cell temperature is above 45 degree celsius. -Var=String0_Err_undertemp_charge bit 14,1 -m // 0x00: No error, 0x01: Error: Flag will be set if minimum cell temperature is below 0 degree celsius. -Var=String0_Err_overtemp_discharge bit 13,1 -m // 0x00: No error, 0x01: Error: Flag will be set if maximum cell temperature is above 60 degree celsius. -Var=String0_Err_undertemp_discharge bit 12,1 -m // 0x00: No error, 0x01: Error: Flag will be set if minimum cell temperature is below -20 degree celsius. +Var=String0_Err_overtemp_charge bit 15,1 -m // 0x00: No error, 0x01: Error: Flag will be set if maximum cell temperature is above 45 degree Celsius. +Var=String0_Err_undertemp_charge bit 14,1 -m // 0x00: No error, 0x01: Error: Flag will be set if minimum cell temperature is below 0 degree Celsius. +Var=String0_Err_overtemp_discharge bit 13,1 -m // 0x00: No error, 0x01: Error: Flag will be set if maximum cell temperature is above 60 degree Celsius. +Var=String0_Err_undertemp_discharge bit 12,1 -m // 0x00: No error, 0x01: Error: Flag will be set if minimum cell temperature is below -20 degree Celsius. Var=String0_Err_Overcurrent_charge bit 11,1 -m // 0x00: No error, 0x01: Error: Flag will be set if string charge current is above 30400mA. Var=String0_Err_Overcurre_discharge bit 10,1 -m // 0x00: No error, 0x01: Error: Flag will be set if discharge current is above maximum string current. Var=String0_Err_Overvoltage bit 9,1 -m // 0x00: No error, 0x01: Error: Flag will be set if maximum cell voltage is above 4200mV. @@ -1398,7 +1398,7 @@ Var=String0_Err_CS_voltage2Meas bit 40,1 -m Var=String0_Err_CS_voltage3Meas bit 55,1 -m [foxBMS_StringMinMaxValues] -ID=281h // Message contains minimum and maximum cell temperature and cell voltage values of respective string (in:can_cbs_tx_minimum-maximum-values.c:CANTX_StringMinimumMaximumValues, fv:tx) +ID=281h // Message contains minimum and maximum cell temperature and cell voltage values of respective string (in:can_cbs_tx_pack-minimum-maximum-values.c:CANTX_StringMinimumMaximumValues, fv:tx) Len=8 CycleTime=100 -p Mux=mux_minMaxValuesString0 4,4 0 -m @@ -1439,6 +1439,7 @@ Var=foxBMS_GetMcuLotNumber bit 13,1 -m Var=foxBMS_GetBmsSoftwareVersion bit 15,1 -m Var=foxBMS_GetMcuUniqueDieId bit 14,1 -m Var=foxBMS_GetMcuWaferInformation bit 12,1 -m +Var=foxBMS_GetCommitHash bit 12,1 [foxBMS_Debug] Len=8 @@ -1544,7 +1545,7 @@ Var=IVT0_MsgCount_Result_Wh unsigned 12,4 -m Var=IVT0_ID_Result_Wh unsigned 0,8 -m /min:7 /max:7 /d:7 [foxBMS_BmsStateDetails] -ID=226h // Transmits details on flags transmitted by foxBMS_State (in:can_cbs_tx_state.c:CANTX_BmsStateDetails, fv:tx) +ID=226h // Transmits details on flags transmitted by foxBMS_State (in:can_cbs_tx_bms-state.c:CANTX_BmsStateDetails, fv:tx) Len=8 CycleTime=1000 -p Var=foxBMS_TimingViolationEngine bit 7,1 -m /ln:"timing violation engine task" // Indicates whether the timing of the engine task has been violated. @@ -1604,8 +1605,29 @@ Var=GetSeconds unsigned 15,6 -m Var=GetWeekday unsigned 32,3 -m /e:foxBMS_RtcWeekday Var=GetYear unsigned 44,7 -m +[foxBMS_DebugResponse] +Len=8 +Mux=foxBMS_CommitHash 0,8 5 -m +Var=shortHash string 8,56 -m + [foxBMS_UnsupportedMultiplexerVal] -ID=201h // (in:can_cbs_tx_unsupported-message.c:CANTX_UnsupportedMultiplexerValue, fv:tx) +ID=201h // (in:can_cbs_tx_debug-unsupported-multiplexer-values.c:CANTX_UnsupportedMultiplexerValue, fv:tx) Len=8 Var=foxBMS_MessageId unsigned 0,32 -m /max:1 Var=foxBMS_MultiplexerValue unsigned 32,32 -m /max:1 + +[foxBMS_FatalErrors] +ID=0FFh // (in:can_cbs_tx_crash-dump.c:CANTX_SendReasonsForFatalErrors, fv:tx) +Len=8 +Mux=StackOverflow 0,8 0 -m + +[foxBMS_AerosolSensor] +ID=3C4h // (in:can_cbs_rx_aerosol-sensor.c:CANRX_AerosolSensor, fv:rx) +Len=8 +CycleTime=1000 +Var=particulate_matter_concentration unsigned 0,16 -m +Var=low_power_mode_wake_up_threshold unsigned 16,16 -m +Var=sensor_status unsigned 37,3 -m +Var=sensor_faults unsigned 32,5 -m +Var=rolling_counter unsigned 45,3 -m +Var=CRC_check_code unsigned 56,8 -m diff --git a/tools/dbc/third-party/README.md b/tools/dbc/third-party/README.md new file mode 100644 index 00000000..5d525308 --- /dev/null +++ b/tools/dbc/third-party/README.md @@ -0,0 +1,6 @@ +# Third Party DBC Files + +- Third party DBC files are copied into the repository verbatim. +- When messages are needed for the foxBMS project, the required messages, + signals etc. are copied to the ``tools/dbc/foxbms.sym`` and + ``tools/dbc/foxbms.dbc`` as needed as described in [tools/dbc/README.md](../README.md) diff --git a/tools/dbc/third-party/bender/iso165_IMD.dbc b/tools/dbc/third-party/bender/iso165_IMD.dbc new file mode 100644 index 00000000..b9968bb0 --- /dev/null +++ b/tools/dbc/third-party/bender/iso165_IMD.dbc @@ -0,0 +1,448 @@ +VERSION "HNNBNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN/4/%%%/4/'%**4NNN///" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: Master IMD_StandAlone +VAL_TABLE_ IMD_State_Executed 1 "NotExecuted" 0 "Executed" ; +VAL_TABLE_ D_IMC_R_ISO_BIAS 2 "HV_1_POS" 1 "HV_1_NEG" 0 "Unknown" ; +VAL_TABLE_ D_VIFC_POWER_MODE 100 "Unkown" 3 "PowerDown" 2 "PowerUp" 1 "PowerOn" 0 "PowerOff" ; +VAL_TABLE_ IMD_State_Activity 1 "Deactivated" 0 "Activated" ; +VAL_TABLE_ D_VIFC_IMC_ALIVE 100 "Unknown" 2 "OutOfRange" 1 "Error" 0 "Running" ; +VAL_TABLE_ D_VIFC_HV_RELAIS 100 "Unknown" 1 "HV_1_POS" 0 "HV_1_NEG" ; +VAL_TABLE_ D_VIFC_LOCK_MODE 100 "Unknown" 2 "BlockedToManyRetries" 1 "Locked" 0 "Unlocked" ; +VAL_TABLE_ D_VIFC_VERSION_INDEX 2 "Firmware ID" 1 "Firmware" 0 "Bootloader" ; +VAL_TABLE_ D_IMC_SELFTEST_SCR 2 "ParameterConfig" 1 "OverAll" 0 "NoAction" ; +VAL_TABLE_ D_IMC_CALIB_STEP 6 "GainCalibrationHV2" 5 "OffsetCalibrationHV2" 4 "ARef_12V_5V_Calibration" 3 "IsoCalibration" 2 "GainCalibrationHV1" 1 "OffsetCalibrationHV1" 0 "NoAction" ; +VAL_TABLE_ IMD_State_Warning 1 "Warning" 0 "NoWarning" ; +VAL_TABLE_ D_VIFC_HV_RELAIS_STATE 100 "Unknown" 1 "HVEnabled" 0 "HVDisabled" ; +VAL_TABLE_ D_IMD_ERROR_CODE 1040 "VIFC_InvalidResponseCmd" 1039 "VIFC_CommunicationError" 1038 "VIFC_NoResponseTimeout" 1037 "VIFC_RepeatedOrMissingFrame" 1035 "VIFC_UnknownCommand" 1034 "VIFC_InvalidParameter" 1033 "VIFC_ChecksumErrorInFrame" 1032 "VIFC_Timeout10msExpired" 1002 "VIFC_CmdUnavailable" 1001 "VIFC_QueueFullCommandRejected" 1000 "VIFC_CommandLocked" 37 "RepeatedOrMissingFrame" 36 "ErrorDuringWritingEEProms" 35 "UnknownCommand" 34 "InvalidParameter" 33 "ChecksumErrorInFrame" 32 "Timeout10msExpired" ; +VAL_TABLE_ IMD_Commands 255 "S_IMD_ERROR_FRAME" 226 "S_VIFC_GET_IMC_ALIVE" 225 "S_VIFC_GET_TEMP" 224 "S_VIFC_GET_LOCK" 223 "S_VIFC_GET_POWER_MODE" 222 "S_VIFC_GET_VERSION" 221 "S_VIFC_GET_HV_RELAIS" 220 "S_VIFC_GET_STATUS" 210 "S_VIFC_SET_HV_RELAIS" 203 "S_VIFC_CTL_MEASUREMENT" 202 "S_VIFC_CTL_LOCK" 201 "S_VIFC_CTL_POWER_MODE" 200 "S_VIFC_CTL_IMC_RESET" 90 "S_IMC_GET_TEST_CNT" 61 "S_IMC_GET_MANUFACTURER" 60 "S_IMC_GET_MEAN_FACTOR" 59 "S_IMC_GET_EEPROM" 58 "S_IMC_GET_HV_2" 57 "S_IMC_GET_R_ISO_WRN_THR" 55 "S_IMC_GET_STATUS" 54 "S_IMC_GET_HV_1" 53 "S_IMC_GET_R_ISO" 51 "S_IMC_GET_VERSION" 50 "S_IMC_GET_R_ISO_ERR_THR" 43 "S_IMC_SET_MEAN_FACTOR" 42 "S_IMC_SET_EEPROM" 41 "S_IMC_SET_R_ISO_WRN_THR" 40 "S_IMC_SET_R_ISO_ERR_THR" 35 "S_IMC_CTL_SYS_UPDATE" 34 "S_IMC_CTL_CALIB" 33 "S_IMC_CTL_SELFTEST" 0 "S_VIFC_CTL_DUMMY" ; +VAL_TABLE_ IMD_State_Run 100 "Unknown" 1 "Running" 0 "NotRunning" ; +VAL_TABLE_ IMD_State_Error 1 "Error" 0 "NoError" ; + + +BO_ 1912 UDS_IMD_FLASH_RESP: 8 IMD_StandAlone + SG_ UDS_IMD_FLASH_RESP_B7 : 56|8@1+ (1,0) [0|0] "" Master + SG_ UDS_IMD_FLASH_RESP_B6 : 48|8@1+ (1,0) [0|0] "" Master + SG_ UDS_IMD_FLASH_RESP_B5 : 40|8@1+ (1,0) [0|0] "" Master + SG_ UDS_IMD_FLASH_RESP_B4 : 32|8@1+ (1,0) [0|0] "" Master + SG_ UDS_IMD_FLASH_RESP_B3 : 24|8@1+ (1,0) [0|0] "" Master + SG_ UDS_IMD_FLASH_RESP_B2 : 16|8@1+ (1,0) [0|0] "" Master + SG_ UDS_IMD_FLASH_RESP_B1 : 8|8@1+ (1,0) [0|0] "" Master + SG_ UDS_IMD_FLASH_RESP_B0 : 0|8@1+ (1,0) [0|0] "" Master + +BO_ 1806 UDS_IMD_FLASH_REQ: 8 Master + SG_ UDS_IMD_FLASH_REQ_B7 : 56|8@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ UDS_IMD_FLASH_REQ_B6 : 48|8@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ UDS_IMD_FLASH_REQ_B5 : 40|8@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ UDS_IMD_FLASH_REQ_B4 : 32|8@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ UDS_IMD_FLASH_REQ_B3 : 24|8@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ UDS_IMD_FLASH_REQ_B2 : 16|8@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ UDS_IMD_FLASH_REQ_B1 : 8|8@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ UDS_IMD_FLASH_REQ_B0 : 0|8@1+ (1,0) [0|0] "" IMD_StandAlone + +BO_ 35 IMD_Response: 5 IMD_StandAlone + SG_ IG_VIFC_STATUS_04_VIFC_CmdError m220 : 12|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ IG_VIFC_STATUS_13_ST_ParamConfig m220 : 21|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ IG_VIFC_STATUS_12_ST_Overall m220 : 20|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ IG_IMC_STATUS_EXT_15_Reserved m55 : 39|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_06_Reserved m55 : 30|1@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_VERSION_MIN m222 : 24|8@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_VERSION_MIN m51 : 24|8@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_MANUFACT_INDEX m61 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_MANUFACT_DATA m61 : 24|16@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_14_IDString m55 : 38|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_13_HV2 m55 : 37|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_12_HV1 m55 : 36|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_11_FuseBits m55 : 35|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_R_ISO_CNT m53 : 32|8@1+ (1,0) [0|0] "Count" Master + SG_ IG_IMC_R_ISO_BIAS m53 : 24|8@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_TEMP m225 : 8|16@1+ (1,0) [0|0] "°C" Master + SG_ IG_VIFC_IMC_ALIVE m226 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_POWER_MODE m223 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IC_VIFC_POWER_MODE m201 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IS_IMC_MEAN_FACTOR m43 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IS_IMC_EEPROM_INDEX m42 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IS_IMC_EEPROM_DATA m42 : 24|16@1+ (1,0) [0|0] "" Master + SG_ IC_IMC_CALIB_STEP m34 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IS_IMC_R_ISO_WRN_THR m41 : 8|16@1+ (1,0) [0|0] "kOhm" Master + SG_ IS_IMC_R_ISO_ERR_THR m40 : 8|16@1+ (1,0) [0|0] "kOhm" Master + SG_ IC_VIFC_MEASURE_MODE m203 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IC_VIFC_LOCK_MODE m202 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IS_VIFC_HV_RELAIS_STATE m210 : 24|16@1+ (1,0) [0|0] "" Master + SG_ IS_VIFC_HV_RELAIS m210 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_EEPROM_DATA m59 : 24|16@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_EEPROM_INDEX m59 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_MEAN_FACTOR m60 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_LOCK_MODE m224 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_STATUS_08_Outdated m220 : 16|1@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_STATUS_02_IMC_Alive m220 : 10|1@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_STATUS_01_IMCConnection m220 : 9|1@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_STATUS_00_IsoMeasurement m220 : 8|1@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_VERSION_INDEX m222 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_HV_RELAIS_STATE m221 : 24|16@1+ (1,0) [0|0] "" Master + SG_ IG_VIFC_HV_RELAIS m221 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_10_12V_NEG m55 : 34|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_09_12V_POS m55 : 33|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_08_TestPulse m55 : 32|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_07_Parameter m55 : 31|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_05_Stack m55 : 29|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_04_RAM m55 : 28|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_03_Flash m55 : 27|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_02_EEPROM m55 : 26|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_01_Hardware m55 : 25|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_EXT_00_Calibration m55 : 24|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_05_IsoWarning m55 : 13|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_04_Selftest m55 : 12|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_03_Calibration m55 : 11|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_02_System m55 : 10|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_01_Ground m55 : 9|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_STATUS_00_IsoFailure m55 : 8|1@1+ (1,0) [0|0] "" Master + SG_ IG_IMD_ERROR_CODE m255 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_HV_2 m58 : 8|16@1+ (1,0) [0|0] "Volt" Master + SG_ IG_IMC_HV_1 m54 : 8|16@1+ (1,0) [0|0] "Volt" Master + SG_ IG_IMC_R_ISO_WRN_THR m57 : 8|16@1+ (1,0) [0|0] "kOhm" Master + SG_ IG_IMC_R_ISO_ERR_THR m50 : 8|16@1+ (1,0) [0|0] "kOhm" Master + SG_ IG_IMC_R_ISO m53 : 8|16@1+ (1,0) [0|0] "kOhm" Master + SG_ IC_IMC_SELFTEST_SCR m33 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_TEST_CNT m90 : 8|16@1+ (1,0) [0|0] "Calls" Master + SG_ IG_VIFC_VERSION_MAJ m222 : 32|8@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_VERSION_INDEX m51 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IG_IMC_VERSION_MAJ m51 : 32|8@1+ (1,0) [0|0] "" Master + SG_ IG_IMD_FAILED_CMD m255 : 24|8@1+ (1,0) [0|0] "" Master + SG_ IMD_Response_DataWord2 m0 : 24|16@1+ (1,0) [0|0] "" Master + SG_ IMD_Response_DataWord1 m0 : 8|16@1+ (1,0) [0|0] "" Master + SG_ IMD_Response_Command M : 0|8@1+ (1,0) [0|0] "" Master + +BO_ 34 IMD_Request: 5 Master + SG_ MG_IMC_MANUFACT_INDEX m61 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MG_VIFC_POWER_MODE m223 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MC_VIFC_POWER_MODE m201 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MG_VIFC_VERSION_INDEX m222 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MG_IMC_VERSION_INDEX m51 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MG_IMC_EEPROM_INDEX m59 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MC_VIFC_MEASURE_MODE m203 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MS_IMC_MEAN_FACTOR m43 : 8|16@1+ (1,0) [1|20] "" IMD_StandAlone + SG_ MS_IMC_EEPROM_DATA m42 : 24|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MS_IMC_EEPROM_INDEX m42 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MC_VIFC_LOCK_PWD m202 : 24|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MC_VIFC_LOCK_MODE m202 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ IMD_Request_DataWord2 m0 : 24|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ IMD_Request_DataWord1 m0 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ IMD_Request_Command M : 0|8@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MS_VIFC_HV_RELAIS_STATE m210 : 24|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MS_IMC_R_ISO_WRN_THR m41 : 8|16@1+ (1,0) [40|2000] "kOhm" IMD_StandAlone + SG_ MC_IMC_CALIB_STEP m34 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MS_VIFC_HV_RELAIS m210 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MC_IMC_SELFTEST_SCR m33 : 8|16@1+ (1,0) [0|0] "" IMD_StandAlone + SG_ MS_IMC_R_ISO_ERR_THR m40 : 8|16@1+ (1,0) [30|1000] "kOhm" IMD_StandAlone + +BO_ 55 IMD_Info: 6 IMD_StandAlone + SG_ II_VIFC_STATUS_04_VIFC_CmdError : 36|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ II_VIFC_STATUS_13_ST_ParamConfig : 45|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ II_VIFC_STATUS_12_ST_Overall : 44|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ II_VIFC_STATUS_08_Outdated : 40|1@1+ (1,0) [0|0] "" Master + SG_ II_VIFC_STATUS_02_IMC_Alive : 34|1@1+ (1,0) [0|0] "" Master + SG_ II_VIFC_STATUS_01_IMC_Connection : 33|1@1+ (1,0) [0|0] "" Master + SG_ II_VIFC_STATUS_00_IsoMeasurement : 32|1@1+ (1,0) [0|0] "" Master + SG_ II_IMC_R_ISO : 0|16@1+ (1,0) [0|0] "kOhm" Master + SG_ II_IMC_STATUS_05_IsoWarning : 21|1@1+ (1,0) [0|0] "" Master + SG_ II_IMC_STATUS_04_Selftest : 20|1@1+ (1,0) [0|0] "" Master + SG_ II_IMC_STATUS_03_Calibration : 19|1@1+ (1,0) [0|0] "" Master + SG_ II_IMC_STATUS_02_System : 18|1@1+ (1,0) [0|0] "" Master + SG_ II_IMC_STATUS_01_Ground : 17|1@1+ (1,0) [0|0] "" Master + SG_ II_IMC_STATUS_00_IsoFailure : 16|1@1+ (1,0) [0|0] "" Master + + + +BA_DEF_ "BusType" STRING ; +BA_DEF_ "GenNWMApBusSleep" STRING ; +BA_DEF_ "GenNWMApCanNormal" STRING ; +BA_DEF_ "GenNWMApCanOff" STRING ; +BA_DEF_ "GenNWMApCanOn" STRING ; +BA_DEF_ "GenNWMApCanSleep" STRING ; +BA_DEF_ "GenNWMApCanWakeUp" STRING ; +BA_DEF_ "GenNWMGotoMode_Awake" STRING ; +BA_DEF_ "GenNWMGotoMode_BusSleep" STRING ; +BA_DEF_ "GenNWMSleepTime" INT 0 1000000; +BA_DEF_ "GenNWMTalkNM" STRING ; +BA_DEF_ "Manufacturer" STRING ; +BA_DEF_ "NmhBaseAddress" HEX 0 536870911; +BA_DEF_ "NmhMessageCount" INT 0 256; +BA_DEF_ "NmType" STRING ; +BA_DEF_ "VersionDay" INT 1 31; +BA_DEF_ "VersionMonth" INT 1 12; +BA_DEF_ "VersionWeek" INT 1 52; +BA_DEF_ "VersionYear" INT 0 99; +BA_DEF_ "VersionNumber" INT 0 65535; +BA_DEF_ "Baudrate" INT 0 250000; +BA_DEF_ "SamplePointMin" INT 1 100; +BA_DEF_ "SamplePointMax" INT 1 100; +BA_DEF_ "SyncJumpWidthMin" INT 1 4; +BA_DEF_ "SyncJumpWidthMax" INT 1 4; +BA_DEF_ "NmhTimeoutTimer" INT 0 65535; +BA_DEF_ "NmhWaitBusSleepTimer" INT 0 65535; +BA_DEF_ "NmhPrepareBusSleepTimer" INT 0 65535; +BA_DEF_ "NmhLongTimer" INT 0 65535; +BA_DEF_ "NmhNStart" INT 0 255; +BA_DEF_ BU_ "GenNodAutoGenDsp" ENUM "No","Yes"; +BA_DEF_ BU_ "GenNodAutoGenSnd" ENUM "No","Yes"; +BA_DEF_ BU_ "GenNodSleepTime" INT 0 1000000; +BA_DEF_ BU_ "ILUsed" ENUM "No","Yes"; +BA_DEF_ BU_ "ECUVariantDefault" ENUM "No","Yes"; +BA_DEF_ BU_ "ECUVariantGroup" STRING ; +BA_DEF_ BU_ "Fehlerort" HEX 0 1000000; +BA_DEF_ BU_ "NodeLayerModules" STRING ; +BA_DEF_ BU_ "NmhNode" ENUM "No","Yes"; +BA_DEF_ BU_ "NmNode" ENUM "No","Yes"; +BA_DEF_ BU_ "NmStationAddress" HEX 0 63; +BA_DEF_ BO_ "DiagRequest" ENUM "No","Yes"; +BA_DEF_ BO_ "DiagResponse" ENUM "No","Yes"; +BA_DEF_ BO_ "DiagState" ENUM "No","Yes"; +BA_DEF_ BO_ "GenMsgAutoGenDsp" ENUM "No","Yes"; +BA_DEF_ BO_ "GenMsgAutoGenSnd" ENUM "No","Yes"; +BA_DEF_ BO_ "GenMsgChkConstant" HEX 0 4095; +BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535; +BA_DEF_ BO_ "GenMsgCycleTimeFast" INT 0 65535; +BA_DEF_ BO_ "GenMsgDelayTime" INT 0 100000; +BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes"; +BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 100; +BA_DEF_ BO_ "GenMsgPDUConstants" STRING ; +BA_DEF_ BO_ "GenMsgSendType" ENUM "Cyclic","not_used","not_used","not_used","not_used","not_used","not_used","IfActive","NoMsgSendType"; +BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 100000; +BA_DEF_ BO_ "NmMessage" ENUM "No","Yes"; +BA_DEF_ BO_ "NmhMessage" ENUM "No","Yes"; +BA_DEF_ BO_ "MsgType" ENUM "Broadcast","Event","NM ","NMH","TP2.0","ISO-TP ","BAP","EID"; +BA_DEF_ BO_ "Timeoutzeit" INT 0 1000000; +BA_DEF_ SG_ "GenSigActiveRepetitions" INT -2147483648 2147483647; +BA_DEF_ SG_ "GenSigAutoGenDsp" ENUM "No","Yes"; +BA_DEF_ SG_ "GenSigAutoGenSnd" ENUM "No","Yes"; +BA_DEF_ SG_ "GenSigEnvVarType" ENUM "int","float","undef"; +BA_DEF_ SG_ "GenSigInactiveValue" INT -2147483648 2147483647; +BA_DEF_ SG_ "GenSigSendType" ENUM "Cyclic","OnWrite","OnWriteWithRepetition","OnChange","OnChangeWithRepetition","IfActive","IfActiveWithRepetition","NoSigSendType","OnChangeAndIfActive","OnChangeAndIfActiveWithRepetition"; +BA_DEF_ SG_ "GenSigStartValue" INT -2147483648 2147483647; +BA_DEF_ SG_ "NWM-WakeupAllowed" ENUM "No","Yes"; +BA_DEF_ SG_ "GenSigFuncType" ENUM "NoFunction","MsgCounter","CRC-8","XOR","XOR-2","DatedBit","SW-Kl15","CHK","Constant","Protocol"; +BA_DEF_ SG_ "GenSigSwitchedByIgnition" ENUM "No","Yes"; +BA_DEF_ SG_ "Fehlerwert" HEX 0 2147483647; +BA_DEF_ SG_ "GenSigMissingSourceValue" HEX 0 2147483647; +BA_DEF_REL_ BU_SG_REL_ "GenSigTimeoutTime" INT 0 65535; +BA_DEF_DEF_ "BusType" ""; +BA_DEF_DEF_ "GenNWMApBusSleep" ""; +BA_DEF_DEF_ "GenNWMApCanNormal" ""; +BA_DEF_DEF_ "GenNWMApCanOff" ""; +BA_DEF_DEF_ "GenNWMApCanOn" ""; +BA_DEF_DEF_ "GenNWMApCanSleep" ""; +BA_DEF_DEF_ "GenNWMApCanWakeUp" ""; +BA_DEF_DEF_ "GenNWMGotoMode_Awake" ""; +BA_DEF_DEF_ "GenNWMGotoMode_BusSleep" ""; +BA_DEF_DEF_ "GenNWMSleepTime" 0; +BA_DEF_DEF_ "GenNWMTalkNM" ""; +BA_DEF_DEF_ "Manufacturer" ""; +BA_DEF_DEF_ "NmhBaseAddress" 0; +BA_DEF_DEF_ "NmhMessageCount" 1; +BA_DEF_DEF_ "NmType" "None"; +BA_DEF_DEF_ "VersionDay" 20; +BA_DEF_DEF_ "VersionMonth" 8; +BA_DEF_DEF_ "VersionWeek" 33; +BA_DEF_DEF_ "VersionYear" 10; +BA_DEF_DEF_ "VersionNumber" 0; +BA_DEF_DEF_ "Baudrate" 0; +BA_DEF_DEF_ "SamplePointMin" 1; +BA_DEF_DEF_ "SamplePointMax" 1; +BA_DEF_DEF_ "SyncJumpWidthMin" 1; +BA_DEF_DEF_ "SyncJumpWidthMax" 1; +BA_DEF_DEF_ "NmhTimeoutTimer" 0; +BA_DEF_DEF_ "NmhWaitBusSleepTimer" 0; +BA_DEF_DEF_ "NmhPrepareBusSleepTimer" 0; +BA_DEF_DEF_ "NmhLongTimer" 0; +BA_DEF_DEF_ "NmhNStart" 0; +BA_DEF_DEF_ "GenNodAutoGenDsp" "Yes"; +BA_DEF_DEF_ "GenNodAutoGenSnd" "Yes"; +BA_DEF_DEF_ "GenNodSleepTime" 0; +BA_DEF_DEF_ "ILUsed" "Yes"; +BA_DEF_DEF_ "ECUVariantDefault" "Yes"; +BA_DEF_DEF_ "ECUVariantGroup" ""; +BA_DEF_DEF_ "Fehlerort" 0; +BA_DEF_DEF_ "NodeLayerModules" ""; +BA_DEF_DEF_ "NmhNode" "Yes"; +BA_DEF_DEF_ "NmNode" "No"; +BA_DEF_DEF_ "NmStationAddress" 0; +BA_DEF_DEF_ "DiagRequest" "No"; +BA_DEF_DEF_ "DiagResponse" "No"; +BA_DEF_DEF_ "DiagState" "No"; +BA_DEF_DEF_ "GenMsgAutoGenDsp" "Yes"; +BA_DEF_DEF_ "GenMsgAutoGenSnd" "Yes"; +BA_DEF_DEF_ "GenMsgChkConstant" 0; +BA_DEF_DEF_ "GenMsgCycleTime" 0; +BA_DEF_DEF_ "GenMsgCycleTimeFast" 0; +BA_DEF_DEF_ "GenMsgDelayTime" 0; +BA_DEF_DEF_ "GenMsgILSupport" "No"; +BA_DEF_DEF_ "GenMsgNrOfRepetition" 0; +BA_DEF_DEF_ "GenMsgPDUConstants" ""; +BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType"; +BA_DEF_DEF_ "GenMsgStartDelayTime" 0; +BA_DEF_DEF_ "NmMessage" "No"; +BA_DEF_DEF_ "NmhMessage" "No"; +BA_DEF_DEF_ "MsgType" "Broadcast"; +BA_DEF_DEF_ "Timeoutzeit" 0; +BA_DEF_DEF_ "GenSigActiveRepetitions" 0; +BA_DEF_DEF_ "GenSigAutoGenDsp" "No"; +BA_DEF_DEF_ "GenSigAutoGenSnd" "No"; +BA_DEF_DEF_ "GenSigEnvVarType" "undef"; +BA_DEF_DEF_ "GenSigInactiveValue" 0; +BA_DEF_DEF_ "GenSigSendType" "NoSigSendType"; +BA_DEF_DEF_ "GenSigStartValue" 0; +BA_DEF_DEF_ "NWM-WakeupAllowed" "No"; +BA_DEF_DEF_ "GenSigFuncType" "NoFunction"; +BA_DEF_DEF_ "GenSigSwitchedByIgnition" "Yes"; +BA_DEF_DEF_ "Fehlerwert" 0; +BA_DEF_DEF_ "GenSigMissingSourceValue" 0; +BA_DEF_DEF_REL_ "GenSigTimeoutTime" 0; +BA_ "BusType" "CAN"; +BA_ "GenNWMApBusSleep" "NMIndNetSDN()"; +BA_ "GenNWMApCanNormal" "apCanNormal()"; +BA_ "GenNWMApCanOff" "NMIndnetOff()"; +BA_ "GenNWMApCanOn" "NMIndnetOn()"; +BA_ "GenNWMApCanSleep" "apCanSleep()"; +BA_ "GenNWMApCanWakeUp" "apCanWakeUp()"; +BA_ "GenNWMGotoMode_Awake" "Nmh_ReqNetOn()"; +BA_ "GenNWMGotoMode_BusSleep" "Nmh_ReqNetOff()"; +BA_ "GenNWMSleepTime" 4000; +BA_ "GenNWMTalkNM" "Nmh_ReqNetOn()"; +BA_ "Manufacturer" "HMC"; +BA_ "NmhBaseAddress" 1824; +BA_ "NmhMessageCount" 32; +BA_ "NmType" "NM-High"; +BA_ "VersionDay" 20; +BA_ "VersionMonth" 8; +BA_ "VersionWeek" 33; +BA_ "VersionYear" 10; +BA_ "VersionNumber" 91; +BA_ "Baudrate" 250000; +BA_ "SamplePointMin" 80; +BA_ "SamplePointMax" 84; +BA_ "SyncJumpWidthMin" 1; +BA_ "SyncJumpWidthMax" 4; +BA_ "NmhTimeoutTimer" 1000; +BA_ "NmhWaitBusSleepTimer" 750; +BA_ "NmhPrepareBusSleepTimer" 500; +BA_ "NmhLongTimer" 200; +BA_ "NmhNStart" 5; +BA_ "NmhNode" BU_ IMD_StandAlone 0; +BA_ "GenMsgCycleTime" BO_ 55 1000; +BA_ "GenMsgSendType" BO_ 55 0; +BA_ "GenSigSendType" SG_ 35 IG_IMC_STATUS_04_Selftest 3; +BA_ "GenSigSendType" SG_ 35 IG_IMC_STATUS_03_Calibration 3; +BA_ "GenSigSendType" SG_ 35 IG_IMC_STATUS_02_System 3; +BA_ "GenSigSendType" SG_ 35 IG_IMC_STATUS_01_Ground 3; +BA_ "GenSigSendType" SG_ 35 IG_IMC_STATUS_00_IsoFailure 3; +BA_ "GenSigStartValue" SG_ 34 MS_IMC_MEAN_FACTOR 10; +BA_ "GenSigStartValue" SG_ 34 MS_IMC_R_ISO_WRN_THR 200; +BA_ "GenSigStartValue" SG_ 34 MC_IMC_SELFTEST_SCR 6; +BA_ "GenSigStartValue" SG_ 34 MS_IMC_R_ISO_ERR_THR 100; +BA_ "GenSigSendType" SG_ 55 II_IMC_STATUS_04_Selftest 3; +BA_ "GenSigSendType" SG_ 55 II_IMC_STATUS_03_Calibration 3; +BA_ "GenSigSendType" SG_ 55 II_IMC_STATUS_02_System 3; +BA_ "GenSigSendType" SG_ 55 II_IMC_STATUS_01_Ground 3; +BA_ "GenSigSendType" SG_ 55 II_IMC_STATUS_00_IsoFailure 3; +VAL_ 35 IG_VIFC_STATUS_04_VIFC_CmdError 1 "Error" 0 "NoError" ; +VAL_ 35 IG_VIFC_STATUS_13_ST_ParamConfig 1 "NotExecuted" 0 "Executed" ; +VAL_ 35 IG_VIFC_STATUS_12_ST_Overall 1 "NotExecuted" 0 "Executed" ; +VAL_ 35 IG_IMC_STATUS_EXT_15_Reserved 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_06_Reserved 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_14_IDString 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_13_HV2 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_12_HV1 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_11_FuseBits 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_R_ISO_BIAS 2 "HV_1_POS" 1 "HV_1_NEG" 0 "Unknown" ; +VAL_ 35 IG_VIFC_IMC_ALIVE 100 "Unknown" 2 "OutOfRange" 1 "Error" 0 "Running" ; +VAL_ 35 IG_VIFC_POWER_MODE 100 "Unkown" 3 "PowerDown" 2 "PowerUp" 1 "PowerOn" 0 "PowerOff" ; +VAL_ 35 IC_VIFC_POWER_MODE 100 "Unkown" 3 "PowerDown" 2 "PowerUp" 1 "PowerOn" 0 "PowerOff" ; +VAL_ 35 IC_IMC_CALIB_STEP 6 "GainCalibrationHV2" 5 "OffsetCalibrationHV2" 4 "ARef_12V_5V_Calibration" 3 "IsoCalibration" 2 "GainCalibrationHV1" 1 "OffsetCalibrationHV1" 0 "NoAction" ; +VAL_ 35 IC_VIFC_LOCK_MODE 100 "Unknown" 2 "BlockedToManyRetries" 1 "Locked" 0 "Unlocked" ; +VAL_ 35 IS_VIFC_HV_RELAIS_STATE 100 "Unknown" 1 "HVEnabled" 0 "HVDisabled" ; +VAL_ 35 IS_VIFC_HV_RELAIS 100 "Unknown" 1 "HV_1_POS" 0 "HV_1_NEG" ; +VAL_ 35 IG_VIFC_LOCK_MODE 100 "Unknown" 2 "BlockedToManyRetries" 1 "Locked" 0 "Unlocked" ; +VAL_ 35 IG_VIFC_STATUS_02_IMC_Alive 1 "Error" 0 "NoError" ; +VAL_ 35 IG_VIFC_STATUS_01_IMCConnection 1 "Error" 0 "NoError" ; +VAL_ 35 IG_VIFC_STATUS_00_IsoMeasurement 1 "Deactivated" 0 "Activated" ; +VAL_ 35 IG_VIFC_VERSION_INDEX 1 "Firmware" 0 "Bootloader" ; +VAL_ 35 IG_VIFC_HV_RELAIS_STATE 100 "Unknown" 1 "HVEnabled" 0 "HVDisabled" ; +VAL_ 35 IG_VIFC_HV_RELAIS 100 "Unknown" 1 "HV_1_POS" 0 "HV_1_NEG" ; +VAL_ 35 IG_IMC_STATUS_EXT_10_12V_NEG 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_09_12V_POS 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_08_TestPulse 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_07_Parameter 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_05_Stack 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_04_RAM 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_03_Flash 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_02_EEPROM 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_01_Hardware 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_EXT_00_Calibration 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_05_IsoWarning 1 "Warning" 0 "NoWarning" ; +VAL_ 35 IG_IMC_STATUS_04_Selftest 100 "Unknown" 1 "Running" 0 "NotRunning" ; +VAL_ 35 IG_IMC_STATUS_03_Calibration 100 "Unknown" 1 "Running" 0 "NotRunning" ; +VAL_ 35 IG_IMC_STATUS_02_System 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_01_Ground 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMC_STATUS_00_IsoFailure 1 "Error" 0 "NoError" ; +VAL_ 35 IG_IMD_ERROR_CODE 1038 "VIFC_NoResponseTimeout" 1037 "VIFC_RepeatedOrMissingFrame" 1035 "VIFC_UnknownCommand" 1034 "VIFC_InvalidParameter" 1033 "VIFC_ChecksumErrorInFrame" 1032 "VIFC_Timeout10msExpired" 1001 "VIFC_QueueFullCommandRejected" 1000 "VIFC_CommandLocked" 37 "RepeatedOrMissingFrame" 36 "ErrorDuringWritingEEProms" 35 "UnknownCommand" 34 "InvalidParameter" 33 "ChecksumErrorInFrame" 32 "Timeout10msExpired" ; +VAL_ 35 IC_IMC_SELFTEST_SCR 2 "ParameterConfig" 1 "OverAll" 0 "NoAction" ; +VAL_ 35 IG_IMC_VERSION_INDEX 3 "Firmware Hash" 2 "Firmware ID" 1 "Firmware" 0 "Bootloader" ; +VAL_ 35 IG_IMD_FAILED_CMD 255 "S_IMD_ERROR_FRAME" 226 "S_VIFC_GET_IMC_ALIVE" 225 "S_VIFC_GET_TEMP" 224 "S_VIFC_GET_LOCK" 223 "S_VIFC_GET_POWER_MODE" 222 "S_VIFC_GET_VERSION" 221 "S_VIFC_GET_HV_RELAIS" 220 "S_VIFC_GET_STATUS" 210 "S_VIFC_SET_HV_RELAIS" 203 "S_VIFC_CTL_MEASUREMENT" 202 "S_VIFC_CTL_LOCK" 201 "S_VIFC_CTL_POWER_MODE" 200 "S_VIFC_CTL_IMC_RESET" 90 "S_IMC_GET_TEST_CNT" 61 "S_IMC_GET_MANUFACTURER" 60 "S_IMC_GET_MEAN_FACTOR" 59 "S_IMC_GET_EEPROM" 58 "S_IMC_GET_HV_2" 57 "S_IMC_GET_R_ISO_WRN_THR" 55 "S_IMC_GET_STATUS" 54 "S_IMC_GET_HV_1" 53 "S_IMC_GET_R_ISO" 51 "S_IMC_GET_VERSION" 50 "S_IMC_GET_R_ISO_ERR_THR" 43 "S_IMC_SET_MEAN_FACTOR" 42 "S_IMC_SET_EEPROM" 41 "S_IMC_SET_R_ISO_WRN_THR" 40 "S_IMC_SET_R_ISO_ERR_THR" 35 "S_IMC_CTL_SYS_UPDATE" 34 "S_IMC_CTL_CALIB" 33 "S_IMC_CTL_SELFTEST" 0 "S_VIFC_CTL_DUMMY" ; +VAL_ 35 IMD_Response_Command 255 "S_IMD_ERROR_FRAME" 226 "S_VIFC_GET_IMC_ALIVE" 225 "S_VIFC_GET_TEMP" 224 "S_VIFC_GET_LOCK" 223 "S_VIFC_GET_POWER_MODE" 222 "S_VIFC_GET_VERSION" 221 "S_VIFC_GET_HV_RELAIS" 220 "S_VIFC_GET_STATUS" 210 "S_VIFC_SET_HV_RELAIS" 203 "S_VIFC_CTL_MEASUREMENT" 202 "S_VIFC_CTL_LOCK" 201 "S_VIFC_CTL_POWER_MODE" 200 "S_VIFC_CTL_IMC_RESET" 90 "S_IMC_GET_TEST_CNT" 61 "S_IMC_GET_MANUFACTURER" 60 "S_IMC_GET_MEAN_FACTOR" 59 "S_IMC_GET_EEPROM" 58 "S_IMC_GET_HV_2" 57 "S_IMC_GET_R_ISO_WRN_THR" 55 "S_IMC_GET_STATUS" 54 "S_IMC_GET_HV_1" 53 "S_IMC_GET_R_ISO" 51 "S_IMC_GET_VERSION" 50 "S_IMC_GET_R_ISO_ERR_THR" 43 "S_IMC_SET_MEAN_FACTOR" 42 "S_IMC_SET_EEPROM" 41 "S_IMC_SET_R_ISO_WRN_THR" 40 "S_IMC_SET_R_ISO_ERR_THR" 35 "S_IMC_CTL_SYS_UPDATE" 34 "S_IMC_CTL_CALIB" 33 "S_IMC_CTL_SELFTEST" 0 "S_VIFC_CTL_DUMMY" ; +VAL_ 34 MG_VIFC_POWER_MODE 100 "Unkown" 3 "PowerDown" 2 "PowerUp" 1 "PowerOn" 0 "PowerOff" ; +VAL_ 34 MC_VIFC_POWER_MODE 100 "Unkown" 3 "PowerDown" 2 "PowerUp" 1 "PowerOn" 0 "PowerOff" ; +VAL_ 34 MG_VIFC_VERSION_INDEX 2 "Firmware ID" 1 "Firmware" 0 "Bootloader" ; +VAL_ 34 MG_IMC_VERSION_INDEX 2 "Firmware ID" 1 "Firmware" 0 "Bootloader" ; +VAL_ 34 MC_VIFC_MEASURE_MODE 1 "Activated" 0 "Deactivated" ; +VAL_ 34 MC_VIFC_LOCK_MODE 100 "Unknown" 2 "BlockedToManyRetries" 1 "Locked" 0 "Unlocked" ; +VAL_ 34 IMD_Request_Command 255 "S_IMD_ERROR_FRAME" 226 "S_VIFC_GET_IMC_ALIVE" 225 "S_VIFC_GET_TEMP" 224 "S_VIFC_GET_LOCK" 223 "S_VIFC_GET_POWER_MODE" 222 "S_VIFC_GET_VERSION" 221 "S_VIFC_GET_HV_RELAIS" 220 "S_VIFC_GET_STATUS" 210 "S_VIFC_SET_HV_RELAIS" 203 "S_VIFC_CTL_MEASUREMENT" 202 "S_VIFC_CTL_LOCK" 201 "S_VIFC_CTL_POWER_MODE" 200 "S_VIFC_CTL_IMC_RESET" 90 "S_IMC_GET_TEST_CNT" 61 "S_IMC_GET_MANUFACTURER" 60 "S_IMC_GET_MEAN_FACTOR" 59 "S_IMC_GET_EEPROM" 58 "S_IMC_GET_HV_2" 57 "S_IMC_GET_R_ISO_WRN_THR" 55 "S_IMC_GET_STATUS" 54 "S_IMC_GET_HV_1" 53 "S_IMC_GET_R_ISO" 51 "S_IMC_GET_VERSION" 50 "S_IMC_GET_R_ISO_ERR_THR" 43 "S_IMC_SET_MEAN_FACTOR" 42 "S_IMC_SET_EEPROM" 41 "S_IMC_SET_R_ISO_WRN_THR" 40 "S_IMC_SET_R_ISO_ERR_THR" 35 "S_IMC_CTL_SYS_UPDATE" 34 "S_IMC_CTL_CALIB" 33 "S_IMC_CTL_SELFTEST" 0 "S_VIFC_CTL_DUMMY" ; +VAL_ 34 MS_VIFC_HV_RELAIS_STATE 100 "Unknown" 1 "HVEnabled" 0 "HVDisabled" ; +VAL_ 34 MC_IMC_CALIB_STEP 6 "GainCalibrationHV2" 5 "OffsetCalibrationHV2" 4 "ARef_12V_5V_Calibration" 3 "IsoCalibration" 2 "GainCalibrationHV1" 1 "OffsetCalibrationHV1" 0 "NoAction" ; +VAL_ 34 MS_VIFC_HV_RELAIS 100 "Unknown" 1 "HV_1_POS" 0 "HV_1_NEG" ; +VAL_ 34 MC_IMC_SELFTEST_SCR 2 "ParameterConfig" 1 "OverAll" 0 "NoAction" ; +VAL_ 55 II_VIFC_STATUS_04_VIFC_CmdError 1 "Error" 0 "NoError" ; +VAL_ 55 II_VIFC_STATUS_13_ST_ParamConfig 1 "NotExecuted" 0 "Executed" ; +VAL_ 55 II_VIFC_STATUS_12_ST_Overall 1 "NotExecuted" 0 "Executed" ; +VAL_ 55 II_VIFC_STATUS_02_IMC_Alive 1 "Error" 0 "NoError" ; +VAL_ 55 II_VIFC_STATUS_01_IMC_Connection 1 "Error" 0 "NoError" ; +VAL_ 55 II_VIFC_STATUS_00_IsoMeasurement 1 "Deactivated" 0 "Activated" ; +VAL_ 55 II_IMC_STATUS_05_IsoWarning 1 "Warning" 0 "NoWarning" ; +VAL_ 55 II_IMC_STATUS_04_Selftest 100 "Unknown" 1 "Running" 0 "NotRunning" ; +VAL_ 55 II_IMC_STATUS_03_Calibration 100 "Unknown" 1 "Running" 0 "NotRunning" ; +VAL_ 55 II_IMC_STATUS_02_System 1 "Error" 0 "NoError" ; +VAL_ 55 II_IMC_STATUS_01_Ground 1 "Error" 0 "NoError" ; +VAL_ 55 II_IMC_STATUS_00_IsoFailure 1 "Error" 0 "NoError" ; + diff --git a/tools/dbc/third-party/isabellenhuette/IVT-S_12082020.dbc b/tools/dbc/third-party/isabellenhuette/IVT-S_12082020.dbc new file mode 100644 index 00000000..2d1f1798 --- /dev/null +++ b/tools/dbc/third-party/isabellenhuette/IVT-S_12082020.dbc @@ -0,0 +1,471 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: Host IVT_Mod +VAL_TABLE_ _B9_Voltage_Channels 3 "3 Channels" 0 "0 Channels" ; +VAL_TABLE_ _B9_Supply_Voltage 1 "12 / 24 V nominal supply voltage" ; +VAL_TABLE_ _B9_Current 2500 "2500 A" 1000 "1000 A" 500 "500 A" 300 "300 A" 100 "100 A" ; +VAL_TABLE_ _B9_Device_Type 2 "IVT-S" 1 "IVT-Mod" ; +VAL_TABLE_ VtDevice_Com 2 "CAN 2 - not terminated" 1 "CAN 1 - terminated" 0 "none" ; +VAL_TABLE_ VtDevice_TOI 3 "I" ; +VAL_TABLE_ VtResetErrorLogdata 7 "Reset error current implausible" 6 "Reset error Vref" 5 "Reset error Underflow ADC ch2" 4 "Reset error Overflow ADC ch2" 3 "Reset error Underflow ADC ch1" 2 "Reset error Overflow ADC ch1" 1 "Reset error ADC interrupt" 0 "Reset all measurement errors" ; +VAL_TABLE_ VtID_Result 0 "Vt_Result_inaktive" 8 "Vt_Result_Wh" 7 "Vt_Result_Ah" 6 "Vt_Result_W" 5 "Vt_Result_T" 4 "Vt_Result_U3" 3 "Vt_Result_U2" 2 "Vt_Result_U1" 1 "Vt_Result_I" ; +VAL_TABLE_ VtID_Cmd 54 "Set_THRESHOLD_neg" 53 "Set_THRESHOLD_pos" 32 "Set_MODE_Result_I" 16 "Set_CAN_ID_Result_I" 52 "Set_MODE" 51 "START_OC_TEST" 50 "STORE" 49 "TRIGGER" 48 "Reset_Err_Log" 39 "Set_MODE_Result_Wh" 38 "Set_MODE_Result_Ah" 37 "Set_MODE_Result_W" 23 "Set_CAN_ID_Result_Wh" 22 "Set_CAN_ID_Result_Ah" 21 "Set_CAN_ID_Result_W" 20 "Set_CAN_ID_Result_T" 35 "Set_MODE_Result_U3" 31 "Set_CAN_ID_Cmd" 29 "Set_CAN_ID_Response" 19 "Set_CAN_ID_Result_U3" 18 "Set_CAN_ID_Result_U2" 36 "Set_MODE_Result_T" 34 "Set_MODE_Result_U2" 33 "Set_MODE_Result_U1" 17 "Set_CAN_ID_Result_U1" ; +VAL_TABLE_ VtTriggerMode 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_TABLE_ VtRunMode 1 "START" 0 "STOP" ; +VAL_TABLE_ VtID_Response 149 "ARTICLE_NUMBER" 148 "SERIAL NUMBER" 147 "SW_VERSION" 146 "DEVICE_ID" 145 "STATUS" 143 "CAN_ID" 142 "STORE_to_default" 134 "START_OC_TEST" 133 "Description for the value '0x85'" 132 "THRESHOLD" 131 "CONFIG" 130 "MODE" 129 "STORE" 128 "TRIGGER" ; + + +BO_ 3221225472 VECTOR__INDEPENDENT_SIG_MSG: 0 Vector__XXX + SG_ _B1_Resp_Trigger_Mask : 0|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B9_Resp_Device_spare : 0|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1320 IVT_Msg_Result_Wh: 6 IVT_Mod + SG_ IVT_Result_Wh_System_Error : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_Wh_OCS : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_Wh_Measurement_Error : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_Wh_Channel_Error : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_Wh : 23|32@0- (1,0) [-2147483648|2147483647] "Wh" Host + SG_ IVT_MsgCount_Result_Wh : 11|4@0+ (1,0) [0|0] "" Host + SG_ IVT_ID_Result_Wh : 7|8@0+ (1,0) [7|7] "" Host + +BO_ 1319 IVT_Msg_Result_As: 6 IVT_Mod + SG_ IVT_Result_As_System_Error : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_As_OCS : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_As_Measurement_Error : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_As_Channel_Error : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_As : 23|32@0- (1,0) [-21474836478|2147483647] "As" Host + SG_ IVT_MsgCount_Result_As : 11|4@0+ (1,0) [0|0] "" Host + SG_ IVT_ID_Result_As : 7|8@0+ (1,0) [6|6] "" Host + +BO_ 1318 IVT_Msg_Result_W: 6 IVT_Mod + SG_ IVT_Result_W_System_Error : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_W_OCS : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_W_Measurement_Error : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_W_Channel_Error : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_W : 23|32@0- (1,0) [-2147483648|2147483647] "W" Host + SG_ IVT_MsgCount_Result_W : 11|4@0+ (1,0) [0|0] "" Host + SG_ IVT_ID_Result_W : 7|8@0+ (1,0) [5|5] "" Host + +BO_ 1297 IVT_Msg_Response: 8 IVT_Mod + SG_ _B1_Trigger_spare m177 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B1_07_Trigger_WH m177 : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B1_06_Trigger_As m177 : 22|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B1_05_Trigger_W m177 : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B1_04_Trigger_T m177 : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B1_03_Trigger_U3 m177 : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B1_02_Trigger_U2 m177 : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B1_01_Trigger_U1 m177 : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B1_00_Trigger_I m177 : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B2_Resp_Store_Device_SN m178 : 23|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _FF_Wrong_Command m255 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BF_Restart_Alive_SN m191 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BF_Restart_Alive_Cmd_ID m191 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BA_Resp_SW_Ver_Vear m186 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BA_Resp_SW_Ver_Revision m186 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BA_Resp_SW_Ver_Month m186 : 40|8@1- (1,0) [0|0] "" Vector__XXX + SG_ _BA_Resp_SW_Ver_Minor m186 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BA_Resp_SW_Ver_Internal m186 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BA_Resp_SW_Ver_Day m186 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B9_Resp_Device_Com m185 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B9_Resp_Device_current m185 : 23|12@0+ (1,0) [0|0] "A" Vector__XXX + SG_ _B9_Resp_Device_TOI m185 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B9_Resp_Device_V_supply m185 : 55|8@0+ (1,0) [0|0] "V" Vector__XXX + SG_ _B9_Resp_Device_Voltage_chan m185 : 27|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ _80_Resp_MeasError_Item m128 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _80_Resp_MeasError_Count_Mask m128 : 23|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _81_Resp_SystemError_Item m129 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _81_Resp_SystemError_Count_Mask m129 : 23|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _82_Resp_AllLogData_Item m130 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _82_Resp_AllLogData_Counter m130 : 23|48@0+ (1,0) [0|0] "" Vector__XXX + SG_ _83_Resp_LogData_Item m131 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _83_Resp_LogData_Counter m131 : 23|48@0+ (1,0) [0|0] "" Vector__XXX + SG_ _90_Resp_Can_ID_SN_I m144 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _90_Resp_Can_ID_val_I m144 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _91_Resp_Can_ID_SN_U1 m145 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _91_Resp_Can_ID_val_U1 m145 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _92_Resp_Can_ID_SN_U2 m146 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _92_Resp_Can_ID_val_U2 m146 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _93_Resp_Can_ID_SN_U3 m147 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _93_Resp_Can_ID_val_U3 m147 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _94_Resp_Can_ID_SN_T m148 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _94_Resp_Can_ID_val_T m148 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _95_Resp_Can_ID_SN_W m149 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _95_Resp_Can_ID_val_W m149 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _96_Resp_Can_ID_SN_As m150 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _96_Resp_Can_ID_val_As m150 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _97_Resp_Can_ID_SN_Wh m151 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _97_Resp_Can_ID_val_Wh m151 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _9D_Resp_Can_ID_SN_Command m157 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _9D_Resp_Can_ID_val_Command m157 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _9F_Resp_Can_ID_SN_Response m159 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _9F_Resp_Can_ID_val_Response m159 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A0_Resp_CycleTime_I m160 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _A0_Resp_Endianess_I m160 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A0_Resp_Sign_I m160 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A0_Resp_TriggerMode_I m160 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _A1_Resp_CycleTime_U1 m161 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _A1_Resp_Endianess_U1 m161 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A1_Resp_Sign_U1 m161 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A1_Resp_TriggerMode_U1 m161 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _A2_Resp_CycleTime_U2 m162 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _A2_Resp_Endianess_U2 m162 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A2_Resp_Sign_U2 m162 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A2_Resp_TriggerMode_U2 m162 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _A3_Resp_CycleTime_U3 m163 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _A3_Resp_Endianess_U3 m163 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A3_Resp_Sign_U3 m163 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A3_Resp_TriggerMode_U3 m163 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _A4_Resp_CycleTime_T m164 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _A4_Resp_Endianess_T m164 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A4_Resp_Sign_T m164 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A4_Resp_TriggerMode_T m164 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _A5_Resp_CycleTime_W m165 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _A5_Resp_Endianess_W m165 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A5_Resp_Sign_W m165 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A5_Resp_TriggerMode_W m165 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _A6_Resp_CycleTime_As m166 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _A6_Resp_Endianess_As m166 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A6_Resp_Sign_As m166 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A6_Resp_TriggerMode_As m166 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _A7_Resp_CycleTime_WH m167 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _A7_Resp_Endianess_WH m167 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A7_Resp_Sign_WH m167 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _A7_Resp_TriggerMode_WH m167 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _B0_Resp_Reset_Item m176 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B0_Resp_Reset_Device_SN m176 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B2_Resp_Store_dummy m178 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B3_Resp_Oc_Test_Time m179 : 15|16@0+ (1,0) [0|65535] "ms" Vector__XXX + SG_ _B4_Resp_Actual_Mode m180 : 8|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B4_Resp_Code_Level m180 : 31|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B4_Resp_Startup_Mode m180 : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _B5_Resp_OC_Pos_Reset_Threshold m181 : 31|16@0- (1,0) [0|0] "" Vector__XXX + SG_ _B5_Resp_OC_Pos_Set_Threshold m181 : 15|16@0- (1,0) [0|0] "" Vector__XXX + SG_ _B6_Resp_OC_Neg_Reset_Threshold m182 : 31|16@0- (1,0) [0|0] "" Vector__XXX + SG_ _B6_Resp_OC_Neg_Set_Threshold m182 : 15|16@0- (1,0) [0|0] "" Vector__XXX + SG_ _B9_Resp_Device_type m185 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BA_Resp_SW_Ver_Major_HW m186 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BB_Resp_Serien_Nr m187 : 15|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _BC_Resp_Art_N m188 : 15|56@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_ID_Response M : 7|8@0+ (1,0) [0|0] "" Host + +BO_ 1317 IVT_Msg_Result_T: 6 IVT_Mod + SG_ IVT_Result_T_System_Error : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_T_OCS : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_T_Measurement_Error : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_T_Channel_Error : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_ID_Result_T : 7|8@0+ (1,0) [4|4] "" Host + SG_ IVT_Result_T : 23|32@0- (0.1,0) [-2147483648|2147483647] "°C" Host + SG_ IVT_MsgCount_Result_T : 11|4@0+ (1,0) [0|0] "" Host + +BO_ 1316 IVT_Msg_Result_U3: 6 IVT_Mod + SG_ IVT_Result_U3_System_Error : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_U3_OCS : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_U3_Measurement_Error : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_U3_Channel_Error : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_ID_Result_U3 : 7|8@0+ (1,0) [3|3] "" Host + SG_ IVT_Result_U3 : 23|32@0- (1,0) [-2147483648|2147483647] "mV" Host + SG_ IVT_MsgCount_Result_U3 : 11|4@0+ (1,0) [0|0] "" Host + +BO_ 1315 IVT_Msg_Result_U2: 6 IVT_Mod + SG_ IVT_Result_U2_System_Error : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_U2_OCS : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_U2_Measurement_Error : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_U2_Channel_Error : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_ID_Result_U2 : 7|8@0+ (1,0) [2|2] "" Host + SG_ IVT_MsgCount_Result_U2 : 11|4@0+ (1,0) [0|0] "" Host + SG_ IVT_Result_U2 : 23|32@0- (1,0) [-2147483648|2147483647] "mV" Host + +BO_ 1314 IVT_Msg_Result_U1: 6 IVT_Mod + SG_ IVT_Result_U1_System_Error : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_U1_Measurement_Error : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_U1_Channel_Error : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_U1_OCS : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_ID_Result_U1 : 7|8@0+ (1,0) [1|1] "" Host + SG_ IVT_Result_U1 : 23|32@0- (1,0) [-2147483648|2147483647] "mV" Host + SG_ IVT_MsgCount_Result_U1 : 11|4@0+ (1,0) [0|0] "" Host + +BO_ 1313 IVT_Msg_Result_I: 6 IVT_Mod + SG_ IVT_Result_I_System_Error : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_I_OCS : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_I_Measurement_Error : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_Result_I_Channel_Error : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_ID_Result_I : 7|8@0+ (1,0) [0|0] "" Host + SG_ IVT_MsgCount_Result_I : 11|4@0+ (1,0) [0|0] "" Host + SG_ IVT_Result_I : 23|32@0- (1,0) [-2147483648|2147483647] "mA" Host + +BO_ 1041 IVT_Msg_Cmd: 8 Host + SG_ _31_01_Trigger_U1 m49 : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _31_07_Trigger_WH m49 : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _31_06_Trigger_As m49 : 22|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _31_05_Trigger_W m49 : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _31_04_Trigger_T m49 : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _31_03_Trigger_U3 m49 : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _31_Trigger_spare m49 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _31_02_Trigger_U2 m49 : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _10_Set_Can_ID_SN_I m16 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _10_Set_Can_ID_val_I m16 : 15|16@0+ (1,0) [0|2047] "" IVT_Mod + SG_ _11_Set_Can_ID_SN_U1 m17 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _11_Set_Can_ID_val_U1 m17 : 15|16@0+ (1,0) [0|2047] "" Vector__XXX + SG_ _12_Set_Can_ID_SN_U2 m18 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _12_Set_Can_ID_val_U2 m18 : 15|16@0+ (1,0) [0|2047] "" Vector__XXX + SG_ _13_Set_Can_ID_SN_U3 m19 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _13_Set_Can_ID_val_U3 m19 : 15|16@0+ (1,0) [0|2047] "" Vector__XXX + SG_ _14_Set_Can_ID_SN_T m20 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _14_Set_Can_ID_val_T m20 : 15|16@0+ (1,0) [0|2047] "" Vector__XXX + SG_ _15_Set_Can_ID_SN_W m21 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _15_Set_Can_ID_val_W m21 : 15|16@0+ (1,0) [0|2047] "" Vector__XXX + SG_ _16_Set_Can_ID_SN_As m22 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _16_Set_Can_ID_val_As m22 : 15|16@0+ (1,0) [0|2047] "" Vector__XXX + SG_ _17_Set_Can_ID_SN_Wh m23 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _17_Set_Can_ID_val_Wh m23 : 15|16@0+ (1,0) [0|2047] "" Vector__XXX + SG_ _1D_Set_Can_ID_SN_Command m29 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _1D_Set_Can_ID_val_Command m29 : 15|16@0+ (1,0) [0|2047] "" Vector__XXX + SG_ _1F_Set_Can_ID_SN_Response m31 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _1F_Set_Can_ID_val_Response m31 : 15|16@0+ (1,0) [0|2047] "" Vector__XXX + SG_ _20_Conf_CycleTime_I m32 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _20_Conf_Endianess_I m32 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _20_Conf_Sign_I m32 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _20_Conf_TriggerMode_I m32 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _21_Conf_CycleTime_U1 m33 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _21_Conf_Endianess_U1 m33 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _21_Conf_Sign_U1 m33 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _21_Conf_TriggerMode_U1 m33 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _22_Conf_CycleTime_U2 m34 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _22_Conf_Endianess_U2 m34 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _22_Conf_Sign_U2 m34 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _22_Conf_TriggerMode_U2 m34 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _23_Conf_CycleTime_U3 m35 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _23_Conf_Endianess_U3 m35 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _23_Conf_Sign_U3 m35 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _23_Conf_TriggerMode_U3 m35 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _24_Conf_CycleTime_T m36 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _24_Conf_Endianess_T m36 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _24_Conf_Sign_T m36 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _24_Conf_TriggerMode_T m36 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _25_Conf_CycleTime_W m37 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _25_Conf_Endianess_W m37 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _25_Conf_Sign_W m37 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _25_Conf_TriggerMode_W m37 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _26_Conf_CycleTime_As m38 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _26_Conf_Endianess_As m38 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _26_Conf_Sign_As m38 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _26_Conf_TriggerMode_As m38 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _27_Conf_CycleTime_WH m39 : 23|16@0+ (1,0) [0|0] "ms" Vector__XXX + SG_ _27_Conf_Endianess_WH m39 : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _27_Conf_Sign_WH m39 : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _27_Conf_TriggerMode_WH m39 : 9|2@0+ (1,0) [0|2] "" Vector__XXX + SG_ _30_Reset_Item m48 : 15|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _30_Reset_Device_SN m48 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _31_00_Trigger_I m49 : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _32_Store_dummy m50 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _33_Oc_Test_Time m51 : 15|16@0+ (1,0) [0|65535] "ms" Vector__XXX + SG_ _34_Actual_Mode m52 : 8|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _34_Code_Level m52 : 31|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ _34_Startup_Mode m52 : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ _35_OC_Pos_Reset_Threshold m53 : 31|16@0- (1,0) [0|0] "A" Vector__XXX + SG_ _35_OC_Pos_Set_Threshold m53 : 15|16@0- (1,0) [0|0] "A" Vector__XXX + SG_ _36_OC_Neg_Reset_Threshold m54 : 31|16@0- (1,0) [0|0] "A" Vector__XXX + SG_ _36_OC_Neg_Set_Threshold m54 : 15|16@0- (1,0) [0|0] "A" Vector__XXX + SG_ _3A_RESTART_to_Bitrate m58 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _3D_Restart_Default_Dummy m61 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _3F_Restart_Dummy m63 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _40_Get_MeasError_Item m64 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _41_Get_SystemError_Item m65 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _42_Get_AllLogData_Item m66 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _43_Get_LogData_Item m67 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _50_Get_Can_ID_SN_I m80 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _51_Get_Can_ID_SN_U1 m81 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _52_Get_Can_ID_SN_U2 m82 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _53_Get_Can_ID_SN_U3 m83 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _54_Get_Can_ID_SN_T m84 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _55_Get_Can_ID_SN_W m85 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _56_Get_Can_ID_SN_As m86 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _57_Get_Can_ID_SN_Wh m87 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _5D_Get_Can_ID_SN_Command m93 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _5F_Get_Can_ID_SN_Response m95 : 31|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ _60_Get_Result_dummy_I m96 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _61_Get_Result_dummy_U1 m97 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _62_Get_Result_dummy_U2 m98 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _63_Get_Result_dummy_U3 m99 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _64_Get_Result_dummy_T m100 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _65_Get_Result_dummy_W m101 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _66_Get_Result_dummy_As m102 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _67_Get_Result_dummy_Wh m103 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _73_Get_OC_Test_dummy m115 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _74_Get_Mode_dummy m116 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _75_Get_OC_Pos_dummy m117 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _76_Get_OC_Neg_dummy m118 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _79_Get_Device_Id_dummy m121 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _7A_Get_SW_Version_dummy m122 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _7B_Get_Serien_Nr_dummy m123 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ _7C_Get_Art_Nr_dummy m124 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ IVT_ID_Cmd M : 7|8@0+ (1,0) [0|0] "" IVT_Mod + + + +CM_ BO_ 3221225472 "This is a message for not used signals, created by Vector CANdb++ DBC OLE DB Provider."; +BA_DEF_ BU_ "Manufacturer" STRING ; +BA_DEF_ BU_ "ILUsed" ENUM "No","Yes"; +BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 1000; +BA_DEF_ SG_ "NWM_WakeupAllowed" ENUM "no","yes"; +BA_DEF_ BO_ "NmMessage" ENUM "no","yes"; +BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes"; +BA_DEF_ BU_ "NmNode" ENUM "no","yes"; +BA_DEF_ BU_ "NmStationAddress" INT 0 63; +BA_DEF_ "NmBaseAddress" HEX 1024 1087; +BA_DEF_ BO_ "GenMsgCycleTimeFast" INT 0 1000; +BA_DEF_ "BusType" STRING ; +BA_DEF_ BO_ "GenMsgCycleTime" INT 0 1000; +BA_DEF_ BO_ "GenMsgDelayTime" INT 0 1000; +BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 10; +BA_DEF_ BO_ "GenMsgSendType" ENUM "Cyclic","NotUsed","NotUsed","NotUsed","NotUsed","Cyclic","NotUsed","IfActive","NoMsgSendType","NotUsed","vector_leerstring"; +BA_DEF_ SG_ "GenSigInactiveValue" INT 0 100000; +BA_DEF_ SG_ "GenSigSendType" ENUM "Cyclic","OnWrite","OnWriteWithRepetition","OnChange","OnChangeWithRepetition","IfActive","IfActiveWithRepetition","NoSigSendType","NotUsed","NotUsed","NotUsed","NotUsed","NotUsed"; +BA_DEF_ SG_ "GenSigStartValue" FLOAT 0 100000000000; +BA_DEF_DEF_ "Manufacturer" "Isabellenhuette"; +BA_DEF_DEF_ "ILUsed" "Yes"; +BA_DEF_DEF_ "GenMsgStartDelayTime" 0; +BA_DEF_DEF_ "NWM_WakeupAllowed" "no"; +BA_DEF_DEF_ "NmMessage" "no"; +BA_DEF_DEF_ "GenMsgILSupport" "Yes"; +BA_DEF_DEF_ "NmNode" "no"; +BA_DEF_DEF_ "NmStationAddress" 0; +BA_DEF_DEF_ "NmBaseAddress" 1024; +BA_DEF_DEF_ "GenMsgCycleTimeFast" 0; +BA_DEF_DEF_ "BusType" "CAN"; +BA_DEF_DEF_ "GenMsgCycleTime" 0; +BA_DEF_DEF_ "GenMsgDelayTime" 0; +BA_DEF_DEF_ "GenMsgNrOfRepetition" 0; +BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType"; +BA_DEF_DEF_ "GenSigInactiveValue" 0; +BA_DEF_DEF_ "GenSigSendType" "OnWrite"; +BA_DEF_DEF_ "GenSigStartValue" 0; +BA_ "ILUsed" BU_ IVT_Mod 1; +BA_ "NmNode" BU_ IVT_Mod 1; +BA_ "Manufacturer" BU_ IVT_Mod "Isabellenhuette"; +BA_ "GenMsgSendType" BO_ 1320 1; +BA_ "GenMsgSendType" BO_ 1319 1; +BA_ "GenMsgSendType" BO_ 1318 1; +BA_ "GenMsgSendType" BO_ 1297 1; +BA_ "GenMsgSendType" BO_ 1317 1; +BA_ "GenMsgSendType" BO_ 1316 1; +BA_ "GenMsgSendType" BO_ 1315 1; +BA_ "GenMsgSendType" BO_ 1314 1; +BA_ "GenMsgSendType" BO_ 1313 1; +BA_ "GenMsgSendType" BO_ 1041 7; +BA_ "NmMessage" BO_ 1041 1; +BA_ "GenSigSendType" SG_ 1320 IVT_Result_Wh 7; +BA_ "GenSigStartValue" SG_ 1320 IVT_Result_Wh 0; +BA_ "GenSigSendType" SG_ 1320 IVT_ID_Result_Wh 7; +BA_ "GenSigStartValue" SG_ 1320 IVT_ID_Result_Wh 7; +BA_ "GenSigStartValue" SG_ 1319 IVT_Result_As 0; +BA_ "GenSigSendType" SG_ 1319 IVT_ID_Result_As 7; +BA_ "GenSigStartValue" SG_ 1319 IVT_ID_Result_As 6; +BA_ "GenSigStartValue" SG_ 1318 IVT_Result_W 0; +BA_ "GenSigSendType" SG_ 1318 IVT_ID_Result_W 7; +BA_ "GenSigStartValue" SG_ 1318 IVT_ID_Result_W 5; +BA_ "GenSigStartValue" SG_ 1297 _A0_Resp_TriggerMode_I 2; +BA_ "GenSigStartValue" SG_ 1297 _A4_Resp_TriggerMode_T 2; +BA_ "GenSigStartValue" SG_ 1297 _A5_Resp_TriggerMode_W 2; +BA_ "GenSigStartValue" SG_ 1297 _A6_Resp_TriggerMode_As 2; +BA_ "GenSigStartValue" SG_ 1297 _A7_Resp_TriggerMode_WH 2; +BA_ "GenSigSendType" SG_ 1317 IVT_ID_Result_T 7; +BA_ "GenSigStartValue" SG_ 1317 IVT_ID_Result_T 4; +BA_ "GenSigStartValue" SG_ 1317 IVT_Result_T 0; +BA_ "GenSigSendType" SG_ 1316 IVT_ID_Result_U3 7; +BA_ "GenSigStartValue" SG_ 1316 IVT_ID_Result_U3 3; +BA_ "GenSigSendType" SG_ 1315 IVT_ID_Result_U2 7; +BA_ "GenSigStartValue" SG_ 1315 IVT_ID_Result_U2 2; +BA_ "GenSigSendType" SG_ 1314 IVT_ID_Result_U1 7; +BA_ "GenSigStartValue" SG_ 1314 IVT_ID_Result_U1 1; +BA_ "GenSigSendType" SG_ 1314 IVT_Result_U1 7; +BA_ "GenSigSendType" SG_ 1313 IVT_ID_Result_I 7; +BA_ "GenSigStartValue" SG_ 1313 IVT_ID_Result_I 0; +BA_ "GenSigSendType" SG_ 1313 IVT_Result_I 7; +BA_ "GenSigStartValue" SG_ 1313 IVT_Result_I 0; +BA_ "GenSigStartValue" SG_ 1041 _20_Conf_TriggerMode_I 2; +BA_ "GenSigStartValue" SG_ 1041 _24_Conf_TriggerMode_T 2; +BA_ "GenSigStartValue" SG_ 1041 _25_Conf_TriggerMode_W 2; +BA_ "GenSigStartValue" SG_ 1041 _26_Conf_TriggerMode_As 2; +BA_ "GenSigStartValue" SG_ 1041 _27_Conf_TriggerMode_WH 2; +VAL_ 1320 IVT_ID_Result_Wh 7 "Vt_Result_Wh" ; +VAL_ 1319 IVT_ID_Result_As 6 "Vt_Result_As" ; +VAL_ 1318 IVT_ID_Result_W 5 "Vt_Result_W" ; +VAL_ 1297 _B9_Resp_Device_Com 2 "CAN 2 - not terminated" 1 "CAN 1 - terminated" 0 "none" ; +VAL_ 1297 _B9_Resp_Device_current 2500 "2500 A" 1000 "1000 A" 500 "500 A" 300 "300 A" 100 "100 A" ; +VAL_ 1297 _B9_Resp_Device_TOI 3 "I" ; +VAL_ 1297 _B9_Resp_Device_V_supply 1 "12 / 24 V nominal supply voltage" ; +VAL_ 1297 _B9_Resp_Device_Voltage_chan 3 "3 Channels" 0 "0 Channels" ; +VAL_ 1297 _80_Resp_MeasError_Item 15 "Resp error calibration data" 14 "Resp error ntc-I OpenCirc" 13 "Resp error ntc-h OpenCirc" 12 "Resp error meas U3 OpenCirc" 11 "Resp error meas U2 OpenCirc" 10 "Resp error meas U1 OpenCirc" 9 "Resp error meas I1 OpenCirc" 8 "Resp error therm EMF correction" 7 "Resp error cur meas implausible" 6 "Resp error Vref" 5 "Resp error Underflow ADC ch 2" 4 "Resp error Overflow ADC ch 2" 3 "Resp error Underflow ADC ch 1" 2 "Reso error Overflow ADC ch 1" 1 "Resp error ADC interrupt" 0 "Resonse all meas errors" ; +VAL_ 1297 _81_Resp_SystemError_Item 16 "Resp error Reset EMC" 15 "Resp error Reset Watchdog" 14 "Resp error Reset illegal opcode" 13 "Resp error ADC Clock" 12 "Resp error eeprom r/w" 11 "Resp error Overcurrent detection" 10 "Resp error Configuration" 9 "Resp error System Init" 8 "Resp error System Clock" 7 "Resp error Power failure" 6 "Resp error Undertemp" 5 "Resp error Overtemp" 4 "Resp error CAN bus transmit Data" 3 "Resp error CAN bus receive Data" 2 "Resp error Parameter CRC" 1 "Resp error code CRC" 0 "Resonse all SystemErrors" ; +VAL_ 1297 _82_Resp_AllLogData_Item 42 "Resp temp minimum" 41 "Resp temp maxmimum" 40 "Resp U3 minimum" 39 "Resp U3 maximum" 38 "Resp U2 minimum" 37 "Resp U2 maxmimum" 36 "Resp U1 minimum" 35 "Resp U1 maximum" 34 "Resp current minimum" 33 "Resp current maximum" 28 "Resp oc negative activated" 27 "Resp oc positive activated" 26 "Resp run temp out spec limits" 25 "Resp run temp in spec limits" 24 "Resp run volt 3 out spec limits" 23 "Resp run volt 3 in spec limits" 22 "Resp run volt 2 out spec limits" 21 "Resp run volt 2 in spec limits" 20 "Resp run volt 1 out spec limits" 19 "Resp run volt 1 in spec limits" 18 "Resp run cur out spec limits" 17 "Resp run cur in spec limits" 16 "Resp run overall" 6 "Resp energy counter discharging" 5 "Resp energy counter charging" 4 "Resp energy counter overall" 3 "Resp Ah counter discharging" 2 "Resp Ah counter charging" 1 "Resp Ah counter overall" 0 "Response on Overall Logdata" ; +VAL_ 1297 _83_Resp_LogData_Item 42 "Resp temp minimum" 41 "Resp temp maxmimum" 40 "Resp U3 minimum" 39 "Resp U3 maximum" 38 "Resp U2 minimum" 37 "Resp U2 maxmimum" 36 "Resp U1 minimum" 35 "Resp U1 maximum" 34 "Resp current minimum" 33 "Resp current maximum" 28 "Resp oc negative activated" 27 "Resp oc positive activated" 26 "Resp run temp out spec limits" 25 "Resp run temp in spec limits" 24 "Resp run volt 3 out spec limits" 23 "Resp run volt 3 in spec limits" 22 "Resp run volt 2 out spec limits" 21 "Resp run volt 2 in spec limits" 20 "Resp run volt 1 out spec limits" 19 "Resp run volt 1 in spec limits" 18 "Resp run cur out spec limits" 17 "Resp run cur in spec limits" 16 "Resp run overall" 6 "Resp energy counter discharging" 5 "Resp energy counter charging" 4 "Resp energy counter overall" 3 "Resp Ah counter discharging" 2 "Resp Ah counter charging" 1 "Resp Ah counter overall" 0 "Response all Logdata SinceReset" ; +VAL_ 1297 _A0_Resp_TriggerMode_I 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1297 _A1_Resp_TriggerMode_U1 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1297 _A2_Resp_TriggerMode_U2 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1297 _A3_Resp_TriggerMode_U3 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1297 _A4_Resp_TriggerMode_T 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1297 _A5_Resp_TriggerMode_W 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1297 _A6_Resp_TriggerMode_As 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1297 _A7_Resp_TriggerMode_WH 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1297 _B0_Resp_Reset_Item 554 "Reset temp minimum" 553 "Reset temp maximum" 552 "Reset U3 minimum" 551 "Reset U3 maximum" 550 "Reset U2 minimum" 549 "Reset U2 maximum" 548 "Reset U1 minimum" 547 "Reset U1 maximum" 546 "Reset Current minimum" 545 "Reset Current maximum" 540 "Reset Run overcur neg activated" 539 "Reset Run overcur pos activated" 538 "Reset Run temp out spec limits" 537 "Reset Run temp in spec limits" 536 "Reset Run volt 3 out spec limits" 535 "Reset Run volt 3 in spec limits" 534 "Reset Run volt 2 out spec limits" 533 "Reset Run volt 2 in spec limits" 532 "Reset Run volt 1 out spec limits" 531 "Reset Run volt 1 in spec limits" 530 "Reset Run cur out spec limits" 529 "Reset Run cur in spec limits" 528 "Reset Runtime overall" 518 "Reset Energy counter discharging" 517 "Reset Energy counter charging" 516 "Reset Energy counter overall" 515 "Reset Ah counter discharging" 514 "Reset Ah counter charging" 513 "Reset Ah counter overall" 512 "Reset all Logdata Since Reset" 272 "Reset Reset EMC" 271 "Reset Reset Watchdog" 270 "Reset illegal opcode" 269 "Reset ADC Clock" 268 "Reset eeprom r/w" 267 "Reset overcurrent detection" 266 "Reset configuration" 265 "Reset system init" 264 "Reset system clock" 263 "Reset power failure" 262 "Reset undertemp" 261 "Reset overtemp" 260 "Reset CAN bus transmit Data" 259 "Reset CAN bus receive Data" 258 "Reset Parameter CRC" 257 "Reset Code CRC" 256 "Reset all System errors" 15 "Reset calibration data " 14 "Reset ntc-I OpenCircuit" 13 "Reset ntc-h OpenCircuit" 12 "Reset voltage measU3 OpenCircuit" 11 "Reset voltage measU2 OpenCircuit" 10 "Reset voltage measU1 OpenCircuit" 9 "Reset current measI1 OpenCircuit" 8 "Reset thermal EMF correction" 7 "Reset error current implausible" 6 "Reset error Vref" 5 "Reset error Underflow ADC ch2" 4 "Reset error Overflow ADC ch2" 3 "Reset error Underflow ADC ch1" 2 "Reset error Overflow ADC ch1" 1 "Reset error ADC interrupt" 0 "Reset all measurement errors" ; +VAL_ 1297 _B4_Resp_Actual_Mode 1 "RUN" 0 "STOP" ; +VAL_ 1297 _B4_Resp_Startup_Mode 1 "Run" 0 "Stop" ; +VAL_ 1297 _B9_Resp_Device_type 2 "IVT-S" 1 "IVT-Mod" ; +VAL_ 1297 IVT_ID_Response 255 "Resp_Cmd_Wrong_Command" 191 "Resp_Get_Set_ALIVE" 188 "Resp_Get_Set_ArtNr" 187 "Resp_Get_Set_Serialnumber" 186 "Resp_Get_Set_SW_VERSION" 185 "Resp_Get_Set_DEVICE_ID" 182 "Resp_Get_Set_THRESHOLD_NEG" 181 "Resp_Get_Set_THRESHOLD_POS" 180 "Resp_Get_Set_MODE" 179 "Resp_Get_Set_OC_TEST_TIME" 178 "Resp_Get_Set_STORE" 177 "Resp_Get_Set_TRIGGER" 176 "Resp_Get_Set_Reset_Error_Logdata" 167 "Resp_Config_Result_Wh" 166 "Resp_Config_Result_As" 165 "Resp_Config_Result_W" 164 "Resp_Config_Result_T" 163 "Resp_Config_Result_U3" 162 "Resp_Config_Result_U2" 161 "Resp_Config_Result_U1" 160 "Resp_Config_Result_I" 159 "Resp_CAN_ID_Response" 157 "Resp_CAN_ID_Command" 151 "Resp_CAN_ID_Res_Wh" 150 "Resp_CAN_ID_Res_As" 149 "Resp_CAN_ID_Res_W" 144 "Resp_CAN_ID_Res_I" 148 "Resp_CAN_ID_Res_T" 147 "Resp_CAN_ID_Res_U3" 146 "Resp_CAN_ID_Res_U2" 145 "Resp_CAN_ID_Res_U1" 131 "Resp_Error_Log_Logdata_Since_Res" 130 "Resp_Error_Log_Overall_Logdata" 129 "Resp_Error_Log_System_Error" 128 "Resp_Error_Log_Measurement_Error" ; +VAL_ 1317 IVT_ID_Result_T 4 "Vt_Result_T" ; +VAL_ 1316 IVT_ID_Result_U3 3 "Vt_Result_U3" ; +VAL_ 1315 IVT_ID_Result_U2 2 "Vt_Result_U2" ; +VAL_ 1314 IVT_ID_Result_U1 1 "Vt_Result_U1" ; +VAL_ 1313 IVT_ID_Result_I 0 "Vt_Result_I" ; +VAL_ 1041 _20_Conf_TriggerMode_I 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1041 _21_Conf_TriggerMode_U1 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1041 _22_Conf_TriggerMode_U2 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1041 _23_Conf_TriggerMode_U3 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1041 _24_Conf_TriggerMode_T 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1041 _25_Conf_TriggerMode_W 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1041 _26_Conf_TriggerMode_As 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1041 _27_Conf_TriggerMode_WH 2 "CYCLIC" 1 "TRIGGERED" 0 "DISABLED" ; +VAL_ 1041 _30_Reset_Item 554 "Reset temp minimum" 553 "Reset temp maximum" 552 "Reset U3 minimum" 551 "Reset U3 maximum" 550 "Reset U2 minimum" 549 "Reset U2 maximum" 548 "Reset U1 minimum" 547 "Reset U1 maximum" 546 "Reset Current minimum" 545 "Reset Current maximum" 540 "Reset Run overcur neg activated" 539 "Reset Run overcur pos activated" 538 "Reset Run temp out spec limits" 537 "Reset Run temp in spec limits" 536 "Reset Run volt 3 out spec limits" 535 "Reset Run volt 3 in spec limits" 534 "Reset Run volt 2 out spec limits" 533 "Reset Run volt 2 in spec limits" 532 "Reset Run volt 1 out spec limits" 531 "Reset Run volt 1 in spec limits" 530 "Reset Run cur out spec limits" 529 "Reset Run cur in spec limits" 528 "Reset Runtime overall" 518 "Reset Energy counter discharging" 517 "Reset Energy counter charging" 516 "Reset Energy counter overall" 515 "Reset Ah counter discharging" 514 "Reset Ah counter charging" 513 "Reset Ah counter overall" 512 "Reset all Logdata Since Reset" 272 "Reset Reset EMC" 271 "Reset Reset Watchdog" 270 "Reset illegal opcode" 269 "Reset ADC Clock" 268 "Reset eeprom r/w" 267 "Reset overcurrent detection" 266 "Reset configuration" 265 "Reset system init" 264 "Reset system clock" 263 "Reset power failure" 262 "Reset undertemp" 261 "Reset overtemp" 260 "Reset CAN bus transmit Data" 259 "Reset CAN bus receive Data" 258 "Reset Parameter CRC" 257 "Reset Code CRC" 256 "Reset all System errors" 15 "Reset calibration data " 14 "Reset ntc-I OpenCircuit" 13 "Reset ntc-h OpenCircuit" 12 "Reset voltage measU3 OpenCircuit" 11 "Reset voltage measU2 OpenCircuit" 10 "Reset voltage measU1 OpenCircuit" 9 "Reset current measI1 OpenCircuit" 8 "Reset thermal EMF correction" 7 "Reset error current implausible" 6 "Reset error Vref" 5 "Reset error Underflow ADC ch2" 4 "Reset error Overflow ADC ch2" 3 "Reset error Underflow ADC ch1" 2 "Reset error Overflow ADC ch1" 1 "Reset error ADC interrupt" 0 "Reset all measurement errors" ; +VAL_ 1041 _34_Actual_Mode 1 "START" 0 "STOP" ; +VAL_ 1041 _34_Startup_Mode 1 "START" 0 "STOP" ; +VAL_ 1041 _3A_RESTART_to_Bitrate 8 "250k" 4 "500k" 2 "1000k" ; +VAL_ 1041 _40_Get_MeasError_Item 15 "Get error calibration data" 14 "Get error ntc-I OpenCirc." 13 "Get error ntc-h OpenCirc." 12 "Get error volt meas U3 OpenCirc." 11 "Get error volt meas U2 OpenCirc." 10 "Get error volt meas U1 OpenCirc." 9 "Get error cur meas I1 OpenCirc." 8 "Get error thermal EMF correction" 7 "Get error cur meas implausible" 6 "Get error Vref" 5 "Get error Underflow ADC ch 2" 4 "Get error Overflow ADC ch 2" 3 "Get error Underflow ADC ch 1" 2 "Get error Overflow ADC ch 1" 1 "Get error ADC interrupt" 0 "Get all meas Errors" ; +VAL_ 1041 _41_Get_SystemError_Item 16 "Get error reset EMC" 15 "Get error reset Watchdog" 14 "Get error reset illegal opcode" 13 "Get error ADC clock" 12 "Get error eeprom r/w" 11 "Get error overcurrent detection" 10 "Get error configuration" 9 "Get error system init" 8 "Get error system clock" 7 "Get error power failure" 6 "Get error undertemp" 5 "Get error overtemp" 4 "Get error CAN bus transmit Data" 3 "Get error CAN bus receive Data" 2 "Get error Code Parameter CRC" 1 "Get error Code CRC" 0 "Get all System errors" ; +VAL_ 1041 _42_Get_AllLogData_Item 42 "Get Temperature minimum" 41 "Get Temperature maximum" 40 "Get U3 minimum" 39 "Get U3 maxmimum " 38 "Get U2 minimum" 37 "Get U2 maximum" 36 "Get U1 minimum" 35 "Get U1 maxmimum" 34 "Get current minimum" 33 "Get current maximum" 28 "Get run overcur neg activated" 27 "Get run overcur pos activated" 26 "Get run temp out spec limits" 25 "Get run temp in spec limits" 24 "Get run volt2 out spec limits" 23 "Get run volt3 in spec limits" 22 "Get run volt2 out spec limits" 21 "Get run volt2 in spec limits" 20 "Get run volt1 out spec limits" 19 "Get run volt1 in spec limits" 18 "Get run cur out spec limits" 17 "Get Run cur in spec limits" 16 "Get Runtime overall" 6 "Get Energy counter discharging" 5 "Get Energy counter charging" 4 "Get Energy counter overall" 3 "Get Ah counter discharging" 2 "Get Ah counter charging" 1 "Get Ah counter overall" 0 "Get Overall Logdata" ; +VAL_ 1041 _43_Get_LogData_Item 42 "Get Temperature minimum" 41 "Get Temperature maximum" 40 "Get U3 minimum" 39 "Get U3 maxmimum " 38 "Get U2 minimum" 37 "Get U2 maximum" 36 "Get U1 minimum" 35 "Get U1 maxmimum" 34 "Get current minimum" 33 "Get current maximum" 28 "Get run overcur neg activated" 27 "Get run overcur pos activated" 26 "Get run temp out spec limits" 25 "Get run temp in spec limits" 24 "Get run volt2 out spec limits" 23 "Get run volt3 in spec limits" 22 "Get run volt2 out spec limits" 21 "Get run volt2 in spec limits" 20 "Get run volt1 out spec limits" 19 "Get run volt1 in spec limits" 18 "Get run cur out spec limits" 17 "Get Run cur in spec limits" 16 "Get Runtime overall" 6 "Get Energy counter discharging" 5 "Get Energy counter charging" 4 "Get Energy counter overall" 3 "Get Ah counter discharging" 2 "Get Ah counter charging" 1 "Get Ah counter overall" 0 "Get Overall Logdata" ; +VAL_ 1041 IVT_ID_Cmd 124 "Get_cmd_and_info_ArtNr" 123 "Get_cmd_and_info_SN" 122 "Get_cmd_and_info_SW_Version" 121 "Get_cmd_and_info_DEVICE_ID" 118 "Get_cmd_and_info_THRESHOLD_NEG" 117 "Get_cmd_and_info_THRESHOLD_POS" 116 "Get_cmd_and_info_MODE" 115 "Get_cmd_and_info_OC_TEST_TIME" 103 "Get_Config_Res_Wh" 102 "Get_Config_Res_As" 101 "Get_Config_Res_W" 100 "Get_Config_Res_T" 99 "Get_Config_Res_U3" 98 "Get_Config_Res_U2" 97 "Get_Config_Res_U1" 96 "Get_Config_Res_I" 95 "Get_CAN_ID_Response" 93 "Get_CAN_ID_Command" 87 "Get_CAN_ID_Res_Wh" 86 "Get_CAN_ID_Res_As" 85 "Get_CAN_ID_Res_W" 84 "Get_CAN_ID_Res_T" 83 "Get_CAN_ID_Res_U3" 82 "Get_CAN_ID_Res_U2" 81 "Get_CAN_ID_Res_U1" 80 "Get_CAN_ID_Res_I" 67 "Get_Logdata_Since_Reset" 66 "Get_Overall_Logdata" 65 "Get_System_Errors" 64 "Get_Measurement_Errors" 63 "Set_RESTART" 61 "Set_RESTART_to_default" 58 "RESTART_to_Bitrate" 54 "Set_THRESHOLD_neg" 53 "Set_THRESHOLD_pos" 32 "Set_MODE_Result_I" 16 "Set_CAN_ID_Result_I" 52 "Set_MODE" 51 "START_OC_TEST" 50 "STORE" 49 "TRIGGER" 48 "Reset_Err_Log" 39 "Set_MODE_Result_Wh" 38 "Set_MODE_Result_As" 37 "Set_MODE_Result_W" 23 "Set_CAN_ID_Result_Wh" 22 "Set_CAN_ID_Result_As" 21 "Set_CAN_ID_Result_W" 20 "Set_CAN_ID_Result_T" 35 "Set_MODE_Result_U3" 31 "Set_CAN_ID_Response" 29 "Set_CAN_ID_Cmd" 19 "Set_CAN_ID_Result_U3" 18 "Set_CAN_ID_Result_U2" 36 "Set_MODE_Result_T" 34 "Set_MODE_Result_U2" 33 "Set_MODE_Result_U1" 17 "Set_CAN_ID_Result_U1" ; + diff --git a/tools/debugger/lauterbach/commands.md b/tools/debugger/lauterbach/commands.md index c7001ec8..5ea5b082 100644 --- a/tools/debugger/lauterbach/commands.md +++ b/tools/debugger/lauterbach/commands.md @@ -2,14 +2,12 @@ A list of some useful lauterbach command line commands: - ## Flash Manipulation 1. Unlock flash: ``FLASH.ReProgram ALL`` 1. Manipulate flash as needed 1. Lock flash: ``FLASH.ReProgram OFF`` - ## Deleting Flash 1. Unlock flash: ``FLASH.ReProgram ALL`` @@ -18,7 +16,6 @@ A list of some useful lauterbach command line commands: - Only certain memory range: ``FLASH.Erase (xxxxxx)--(yyyyyy)`` 1. Lock flash: ``FLASH.ReProgram OFF`` - ## Saving Flash to File 1. Save flash to file: ``DATA.SAVE.BINARY filename.bin 0x08000000--0x081FFFFF`` diff --git a/tools/debugger/lauterbach/config.t32.in b/tools/debugger/lauterbach/config.t32.in index acd7e55d..318b0f9a 100644 --- a/tools/debugger/lauterbach/config.t32.in +++ b/tools/debugger/lauterbach/config.t32.in @@ -4,11 +4,16 @@ ID=T32 TMP=@TMP@ SYS=@SYS@ +; T32 API Access (TCP recommended by Lauterbach) +RCL=NETTCP +PORT=20000 + ;SCREEN= ;MWI PBI= USB +CONNECTIONMODE=AUTOABORT ; Printer settings PRINTER=WINDOWS diff --git a/tools/debugger/lauterbach/get_macro_values.py b/tools/debugger/lauterbach/get_macro_values.py new file mode 100644 index 00000000..1ea25782 --- /dev/null +++ b/tools/debugger/lauterbach/get_macro_values.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Gets the macro values from the compiler output""" + +import argparse +import logging +import os +import sys + +from typing import List +from pathlib import Path +import git +from git.exc import InvalidGitRepositoryError + +SCRIPT_DIR = Path(__file__).parent.resolve() + +REPO_ROOT = SCRIPT_DIR.parent.parent.parent +try: + repo = git.Repo(SCRIPT_DIR, search_parent_directories=True) + REPO_ROOT = Path(repo.git.rev_parse("--show-toplevel")) +except InvalidGitRepositoryError: + pass + + +def get_ppm_files() -> List[Path]: + """creates a generator for all relevant macro files in the build directory""" + build_dir = REPO_ROOT / "build/bin" + return build_dir.rglob("*.ppm") + + +def main(): + """This script does this and that""" + parser = argparse.ArgumentParser() + parser.add_argument( + "-v", + "--verbosity", + dest="verbosity", + action="count", + default=0, + help="set verbosity level", + ) + args = parser.parse_args() + + if args.verbosity == 1: + logging.basicConfig(level=logging.INFO) + elif args.verbosity > 1: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.ERROR) + + macros = [] + for i in get_ppm_files(): + txt = i.read_text(encoding="utf-8") + for line in txt.splitlines(): + if not line.strip().startswith("#define"): + continue + if line.endswith("/* Predefined */"): + continue + if f"{os.sep}ccs{os.sep}tools" in line: # ignore compiler builtins + continue + try: + # ignore additional compiler builtins + if line.split(" ", maxsplit=1)[1].startswith("_"): + continue + except IndexError: + pass + if f"{os.sep}os{os.sep}freertos" in line: # ignore FreeRTOS macros + continue + if f"{os.sep}hal{os.sep}" in line: # ignore TI HAL macros + continue + try: + # ignore additional compiler builtins + if line.split(" ", maxsplit=1)[1].startswith("FOXBMS__"): + continue + except IndexError: + pass + + # remove comment + line = line.split("/*")[0].strip() + try: + line = line.split(" ", maxsplit=1)[1] + except IndexError as err: + logging.debug(err) + continue + try: + macro, value = line.split(" ", maxsplit=1) + except ValueError: + logging.debug(f"{macro} has no value. Ignoring...") + continue + if not value.startswith("("): + value = f"({value})" + macros.append((macro, value)) + macros = list(set((tuple(i) for i in macros))) + logging.info(f"Adding {len(macros)} macro(s).") + + macro_cmm_file_in = REPO_ROOT / "tools/debugger/lauterbach/load_macro_values.cmm.in" + if not macro_cmm_file_in.is_file(): + sys.exit(f"Could not find file {macro_cmm_file_in}") + logging.info(f"Reading configuration file '{macro_cmm_file_in}'") + txt = macro_cmm_file_in.read_text(encoding="utf-8") + replacement = "\n".join( + [f"sYmbol.CREATE.MACRO {macro} {value}" for macro, value in macros] + ) + macro_cmm_file_out = REPO_ROOT / "build/load_macro_values.cmm" + REPO_ROOT.mkdir(exist_ok=True) + txt = txt.replace("@MACROS_AND_VALUES@", replacement) + logging.info(f"Writing configuration file '{macro_cmm_file_out}'") + macro_cmm_file_out.write_text(txt, encoding="utf-8") + logging.info("Done...") + + +if __name__ == "__main__": + main() diff --git a/tools/debugger/lauterbach/init.cmm.in b/tools/debugger/lauterbach/init.cmm.in index 1cc1387e..9b5af3a3 100644 --- a/tools/debugger/lauterbach/init.cmm.in +++ b/tools/debugger/lauterbach/init.cmm.in @@ -10,6 +10,9 @@ GLOBAL &elf_file ; set default elf file relativ to this cmm-file &elf_file=OS.PPD()+"\@ELF_FILE@" +; list of macros +¯o_values = OS.PPD()+"\load_macro_values.cmm" + ;set default search path to this cmm-file &elf_searchpath=OS.PPD()+"\@ELF_SEARCHPATH@" @@ -36,7 +39,7 @@ cd &working_path Var.Frame /Locals /Caller WinPOS 50% 50% 50% 50% Var.Watch %E - Var.AddWatch fas_assertLocation os_timer ilck_state sys_state bms_state data_blockCellVoltage data_blockCellTemperature data_blockCurrentSensor data_blockErrors data_blockMsl data_blockRsl data_blockMol + Var.AddWatch os_timer ilck_state sys_state bms_state data_blockCellVoltage data_blockCellTemperature data_blockCurrentSensor data_blockErrors data_blockMsl data_blockRsl data_blockMol ;choose hex mode for input radix hex @@ -267,6 +270,9 @@ SYStem.Up TASK.CONFIG ~~/demo/arm/kernel/freertos/freertos.t32 MENU.ReProgram ~~/demo/arm/kernel/freertos/freertos.men HELP.FILTER.Add rtosfreertos +Data.LOAD.Elf &elf_file /NOCODE +IF OS.FILE(¯o_values) + do ¯o_values PRINT "Initialization successful, foxBMS ready " ENDDO diff --git a/tools/debugger/lauterbach/load_macro_values.cmm.in b/tools/debugger/lauterbach/load_macro_values.cmm.in new file mode 100644 index 00000000..d1408379 --- /dev/null +++ b/tools/debugger/lauterbach/load_macro_values.cmm.in @@ -0,0 +1,3 @@ +@MACROS_AND_VALUES@ +sYmbol.CREATE.Done +sYmbol.List.MACRO diff --git a/tools/debugger/ozone/README.md b/tools/debugger/ozone/README.md index 406b47f3..189542b9 100644 --- a/tools/debugger/ozone/README.md +++ b/tools/debugger/ozone/README.md @@ -7,12 +7,3 @@ software has been found on the system. For more information on using this, please search the foxBMS documentation for `Ozone`. - -## J-Flash -With the ``foxbms.jflash`` file, the J-Flash tool can be used to program a -connected MCU. -The call to JFlash looks like this from the root of this project: - -``` -{path to Segger J-Flash}JFlash.exe -openprjtools/debugger/ozone/foxbms.jflash -openbuild/bin/foxbms.elf -auto -exit -``` diff --git a/tools/gui/fgui/__init__.py b/tools/gui/fgui/__init__.py index 835bbc0d..f1eab84e 100644 --- a/tools/gui/fgui/__init__.py +++ b/tools/gui/fgui/__init__.py @@ -42,10 +42,10 @@ import os from pathlib import Path - +import ssl import httplib2 -__version__ = "1.5.1" +__version__ = "1.6.0" __appname__ = "foxBMS 2" __author__ = "The foxBMS Team" __copyright__ = "(c) 2010 - 2023 foxBMS" @@ -65,6 +65,9 @@ except TimeoutError: resp = [] resp.append({"status": 401}) +except ssl.SSLCertVerificationError: + resp = [] + resp.append({"status": 401}) if int(resp[0]["status"]) >= 400: FOXBMS_DOC_URL = f"{FOXBMS_DOC_BASE_URL}/foxbms/gen2/docs/html/latest/" # use latest if it correct version does not exist diff --git a/tools/gui/fgui/entry/entry_frame.py b/tools/gui/fgui/entry/entry_frame.py index 8dd918c0..d0eb767a 100644 --- a/tools/gui/fgui/entry/entry_frame.py +++ b/tools/gui/fgui/entry/entry_frame.py @@ -163,7 +163,7 @@ def _add_menu_bar(self): mb.Append(hm, "?") - # menu bau fully constructed + # menu build fully constructed self.SetMenuBar(mb) def _add_status_bar(self): diff --git a/tools/gui/fgui/log_parser/log_parser.py b/tools/gui/fgui/log_parser/log_parser.py index 064cd85c..a8fdabd3 100644 --- a/tools/gui/fgui/log_parser/log_parser.py +++ b/tools/gui/fgui/log_parser/log_parser.py @@ -71,7 +71,7 @@ def __init__(self, parent=None): self.Centre() self.basic_gui() self.all_checked_sig = [] - self.plot_dfs = [] + self.plot_data_frames = [] self.all_sig = [] self.is_running = True self.dbc_file = str( @@ -253,7 +253,7 @@ def append_plot_df(self, signal_timestamp, signal_val, signal_name, unit): plot_df.insert( 1, signal_name + " in " + unit.replace("°C", "°C"), signal_val ) - self.plot_dfs.append(plot_df) + self.plot_data_frames.append(plot_df) def read_pcan_log_v1(self): # pylint: disable=too-many-locals """Read data to selected signals from PCAN log v1 file""" @@ -303,7 +303,7 @@ def read_pcan_log_v1(self): # pylint: disable=too-many-locals except KeyError: msg = "Signal" + str(signal_name) + " is not in dictionary." wx.MessageBox(msg, "Error", wx.OK | wx.ICON_ERROR) - self.plot_dfs.clear() + self.plot_data_frames.clear() return signal_timestamp.append(timestamp) signal_val.append(decoded_sig_val) @@ -361,7 +361,7 @@ def read_pcan_log_v2(self): # pylint: disable=too-many-locals except KeyError: msg = "Signal" + str(signal_name) + " is not in dictionary." wx.MessageBox(msg, "Error", wx.OK | wx.ICON_ERROR) - self.plot_dfs.clear() + self.plot_data_frames.clear() return signal_timestamp.append(timestamp) signal_val.append(decoded_sig_val) @@ -420,7 +420,7 @@ def read_can_log(self): # pylint: disable=too-many-locals msg = "Signal" + str(signal_name) + " is not in dictionary." wx.MessageBox(msg, "Error", wx.OK | wx.ICON_ERROR) - self.plot_dfs.clear() + self.plot_data_frames.clear() return signal_timestamp.append(timestamp) signal_val.append(decoded_sig_val) @@ -433,10 +433,10 @@ def read_can_log(self): # pylint: disable=too-many-locals def plot_selected_signals(self, units): """Plot the data of the selected signals from the read log file""" - if len(self.plot_dfs) < 1: + if len(self.plot_data_frames) < 1: msg = "No signals chosen or signals not in Log files." wx.MessageBox(msg, "Error", wx.OK | wx.ICON_ERROR) - self.plot_dfs.clear() + self.plot_data_frames.clear() return # set figure size depending on subplot count @@ -454,8 +454,10 @@ def plot_selected_signals(self, units): axes_units[0].append(first_ax) axes_units[1].append(units[0]) - # check all dataframes if a new plot is needed or a suiting subplot exists - for i_df, df in enumerate(self.plot_dfs): # pylint: disable=invalid-name + # check all data-frames if a new plot is needed or a suiting subplot exists + for i_df, data_frame in enumerate( + self.plot_data_frames + ): # pylint: disable=invalid-name new_ax = True for i_unit, unit in enumerate(axes_units[1]): if unit == units[i_df]: @@ -468,10 +470,12 @@ def plot_selected_signals(self, units): axes_units[0].append(plt_ax) axes_units[1].append(units[i_df]) - df.plot(x=df.columns[0], y=df.columns[1], kind="line", ax=plt_ax) + data_frame.plot( + x=data_frame.columns[0], y=data_frame.columns[1], kind="line", ax=plt_ax + ) plt.xlabel("Time(ms)") plt_ax.legend(bbox_to_anchor=(0, 1.02, 1, 0.2), loc="lower left") - self.plot_dfs.clear() + self.plot_data_frames.clear() plt.show() diff --git a/tools/gui/fgui/lvac/bms_state.py b/tools/gui/fgui/lvac/bms_state.py new file mode 100644 index 00000000..690446ad --- /dev/null +++ b/tools/gui/fgui/lvac/bms_state.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + + +"""Display the BMS state""" + +import re + +import can +import wx +import wx.grid as gridlib +from cantools.database.can import Database + +from ..misc.gui_helpers import get_icon + +FRAME_STYLE = ( + wx.DEFAULT_FRAME_STYLE & (~wx.CLOSE_BOX) & (~wx.MAXIMIZE_BOX) ^ wx.RESIZE_BORDER +) + + +class BmsStateFrame( # pylint: disable=too-many-ancestors,too-many-instance-attributes + wx.Frame +): + """ + Frame to display the cell voltages in a table. + """ + + # pylint: disable=too-many-arguments + def __init__(self, title, parent=None, dbc: Database = None, pos=None): + wx.Frame.__init__(self, parent=parent, title=title, style=FRAME_STYLE) + self.SetPosition(pos) + self.SetIcon(get_icon()) + + # dbc stuff + self.bms_state_msg_name = "foxBMS_BmsState" + self.dbc = dbc + self.bms_state_msg = self.dbc.get_message_by_name(self.bms_state_msg_name) + panel = wx.Panel(self) + self.grid_table = gridlib.Grid(panel) + self.grid_table.CreateGrid(len(self.bms_state_msg.signals), 1) + self.grid_table.SetRowLabelSize(200) + self.grid_table.SetColSize(0, 100) + self.msg_to_idx = {} + for i, val in enumerate(self.bms_state_msg.signals): + self.msg_to_idx[val.name] = i + label_name = val.name.replace("foxBMS_", "") + label_name = label_name.replace("_", " ") + label_name = " ".join(re.sub(r"([A-Z])", r" \1", label_name).split()) + self.grid_table.SetRowLabelValue(i, label_name) + self.grid_table.SetColLabelValue(0, "Status") + self.grid_table.SetRowLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE) + self.grid_table.EnableEditing(False) + self.grid_table.DisableDragRowSize() + self.grid_table.DisableDragColSize() + + sizer = wx.BoxSizer() + sizer.Add(self.grid_table, 1, wx.EXPAND | wx.ALL) + panel.SetSizer(sizer) + sizer.Fit(panel) + width, height = self.grid_table.GetSize() + self.SetSize(wx.Size(width + 28, height + 44)) + + def update_bms_state_info(self, value: can.message.Message): + """Updates the table cell entries with the current voltage values""" + msg_data: dict = self.dbc.decode_message(value.arbitration_id, value.data) + for i in msg_data.items(): + self.grid_table.SetCellValue(self.msg_to_idx[i[0]], 0, str(i[1])) + + def Destroy(self): # pylint: disable=invalid-name,no-self-use + """Unbind normal destroy""" + return True + + def NewDestroy(self): # pylint: disable=invalid-name + """Destroys the frame""" + return super().Destroy() diff --git a/tools/gui/fgui/lvac/cell_temperatures.py b/tools/gui/fgui/lvac/cell_temperatures.py index 200d8584..dec2746a 100644 --- a/tools/gui/fgui/lvac/cell_temperatures.py +++ b/tools/gui/fgui/lvac/cell_temperatures.py @@ -80,10 +80,12 @@ def __init__( self.temps_per_module = temps_per_module self.grid_table = gridlib.Grid(panel) self.grid_table.CreateGrid(self.temps_per_module, self.modules) + self.grid_table.SetRowLabelSize(100) for i in range(0, self.modules): self.grid_table.SetColLabelValue(i, f"Module {i+1}") for i in range(0, self.temps_per_module): self.grid_table.SetRowLabelValue(i, f"Temperature {i+1}") + self.grid_table.SetRowLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE) for row in range(self.temps_per_module): for col in range(self.modules): self.grid_table.SetCellValue(row, col, "None") diff --git a/tools/gui/fgui/lvac/cell_voltages.py b/tools/gui/fgui/lvac/cell_voltages.py index b29dd8ad..1b0ad4f2 100644 --- a/tools/gui/fgui/lvac/cell_voltages.py +++ b/tools/gui/fgui/lvac/cell_voltages.py @@ -81,10 +81,12 @@ def __init__( self.cells_per_module = cells_per_module self.grid_table = gridlib.Grid(panel) self.grid_table.CreateGrid(self.cells_per_module, self.modules) + self.grid_table.SetRowLabelSize(100) for i in range(0, self.modules): self.grid_table.SetColLabelValue(i, f"Module {i+1}") for i in range(0, self.cells_per_module): self.grid_table.SetRowLabelValue(i, f"Cell {i+1}") + self.grid_table.SetRowLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE) for row in range(self.cells_per_module): for col in range(self.modules): self.grid_table.SetCellValue(row, col, "None") diff --git a/tools/gui/fgui/lvac/debug_response.py b/tools/gui/fgui/lvac/debug_response.py index 7fe336d9..8721be8a 100644 --- a/tools/gui/fgui/lvac/debug_response.py +++ b/tools/gui/fgui/lvac/debug_response.py @@ -102,6 +102,16 @@ def decode_debug_response(value, dbc): nice_msg = f"MCU wafer information: {msg['MCU_waferNumber']} " nice_msg += f"(x={msg['MCU_xWaferCoordinate']}, " nice_msg += f"y={msg['MCU_yWaferCoordinate']}) " + elif mux_value == "foxBMS_CommitHash": + sha = "" + bits = str(bin(msg["shortHash"])[2:].zfill(56)) + sha = "" + for i in range(0, 7): + start = (0 + i) * 8 + end = start + 8 + bitstring = bits[start:end] + sha += chr(int(bitstring, 2)) + nice_msg = f"Short commit hash: {sha}" else: nice_msg = msg print(nice_msg) diff --git a/tools/gui/fgui/lvac/default_messages.py b/tools/gui/fgui/lvac/default_messages.py index 48aa10f0..5eacf60b 100644 --- a/tools/gui/fgui/lvac/default_messages.py +++ b/tools/gui/fgui/lvac/default_messages.py @@ -96,6 +96,16 @@ def _get_cell_temperatures_msg_id(dbc: Database): return cell_temperatures_msg.frame_id +def _get_bms_state_msg_id(dbc: Database): + bms_state_msg = dbc.get_message_by_name("foxBMS_BmsState") + return bms_state_msg.frame_id + + +def _get_bms_state_details_msg_id(dbc: Database): + bms_state_details_msg = dbc.get_message_by_name("foxBMS_BmsStateDetails") + return bms_state_details_msg.frame_id + + def _get_debug_response_msg_id(dbc: Database): debug_response_msg = dbc.get_message_by_name("foxBMS_DebugResponse") return debug_response_msg.frame_id diff --git a/tools/gui/fgui/lvac/lvac_frame.py b/tools/gui/fgui/lvac/lvac_frame.py index a923424e..3709d8ca 100644 --- a/tools/gui/fgui/lvac/lvac_frame.py +++ b/tools/gui/fgui/lvac/lvac_frame.py @@ -69,11 +69,15 @@ from ..workers.can_node_worker import CanAdapterProcess from ..workers.gui_sync_worker import SyncThread from ..workers.send_worker import PeriodicSendThread +from .bms_state import BmsStateFrame from .cell_temperatures import CellTemperatureFrame from .cell_voltages import CellVoltageFrame +from .debug_response import decode_debug_response from .default_messages import ( _get_balancing_threshold_limits, _get_balancing_threshold_signal, + _get_bms_state_details_msg_id, + _get_bms_state_msg_id, _get_bms_state_request_message, _get_cell_temperatures_msg_id, _get_cell_voltages_msg_id, @@ -82,7 +86,6 @@ _get_state_request_signal_mode, _set_bms_state_request_message, ) -from .debug_response import decode_debug_response from .msgs.msg_debug import DebugMessage, DebugMessageState TITLE = f"{__appname__} - Live View and Control - {__version__}" @@ -168,9 +171,24 @@ def __init__(self, parent=None, can_process: Union[None, CanAdapterProcess] = No ) self.f_cell_temperatures.Show() + self.f_bms_state = BmsStateFrame( + title="BMS State and BMS State Details", + parent=self.GetParent(), + dbc=self.dbc, + pos=( + self.f_cell_voltages.GetPosition()[0] + + self.f_cell_voltages.GetSize()[0] + + 30, + self.f_cell_voltages.GetPosition()[1], + ), + ) + self.f_bms_state.Show() + # DBC/CAN stuff self.cell_voltages_msg_id = _get_cell_voltages_msg_id(self.dbc) self.cell_temperatures_msg_id = _get_cell_temperatures_msg_id(self.dbc) + self.bms_state_msg_id = _get_bms_state_msg_id(self.dbc) + self.bms_state_details_msg_id = _get_bms_state_details_msg_id(self.dbc) # construct BMS State Request Message self.state_request_msg: Message = _get_bms_state_request_message(self.dbc) self.state_request_signal_mode = _get_state_request_signal_mode( @@ -456,6 +474,8 @@ def update_process_label(self, value: can.message.Message): self.f_cell_voltages.update_cell_voltages(value) elif _get_message_type(value, self.cell_temperatures_msg_id): self.f_cell_temperatures.update_cell_temperatures(value) + elif _get_message_type(value, self.bms_state_msg_id): + self.f_bms_state.update_bms_state_info(value) elif _get_message_type(value, self.debug_response_msg_id): decode_debug_response(value, self.dbc) @@ -475,6 +495,8 @@ def CloseFrameSafely(self, event: wx.Event): # pylint: disable=invalid-name self.f_cell_temperatures.NewDestroy() if getattr(self, "f_cell_voltages", None): self.f_cell_voltages.NewDestroy() + if getattr(self, "f_bms_state", None): + self.f_bms_state.NewDestroy() if (self.sync_worker and self.sync_worker.is_alive()) or ( self.send_worker and self.send_worker.is_alive() ): @@ -493,6 +515,9 @@ def onLvacFocus( # pylint: disable=invalid-name,unused-argument if getattr(self, "f_cell_voltages", None): self.f_cell_voltages.Raise() self.f_cell_voltages.Iconize(False) + if getattr(self, "f_bms_state", None): + self.f_bms_state.Raise() + self.f_bms_state.Iconize(False) self.Raise() diff --git a/tools/gui/fgui/lvac/msgs/msg_debug.py b/tools/gui/fgui/lvac/msgs/msg_debug.py index c6def523..ded6bab6 100644 --- a/tools/gui/fgui/lvac/msgs/msg_debug.py +++ b/tools/gui/fgui/lvac/msgs/msg_debug.py @@ -105,6 +105,7 @@ def get_version_info_message(self, _type: str = "all") -> can.Message: mcu_lot_number = 0 mcu_unique_die_id = 0 mcu_wafer_information = 0 + mcu_get_commit_hash = 0 if _type == "foxBMS_GetBmsSoftwareVersion": bms_software_version = 1 elif _type == "foxBMS_GetMcuLotNumber": @@ -113,11 +114,14 @@ def get_version_info_message(self, _type: str = "all") -> can.Message: mcu_unique_die_id = 1 elif _type == "foxBMS_GetMcuWaferInformation": mcu_wafer_information = 1 + elif _type == "foxBMS_GetCommitHash": + mcu_get_commit_hash = 1 elif _type == "all": bms_software_version = 1 mcu_lot_number = 1 mcu_unique_die_id = 1 mcu_wafer_information = 1 + mcu_get_commit_hash = 1 else: logging.error(f"Unsupported value {_type}") msg_data = { @@ -126,6 +130,7 @@ def get_version_info_message(self, _type: str = "all") -> can.Message: "foxBMS_GetMcuLotNumber": mcu_lot_number, "foxBMS_GetMcuUniqueDieId": mcu_unique_die_id, "foxBMS_GetMcuWaferInformation": mcu_wafer_information, + "foxBMS_GetCommitHash": mcu_get_commit_hash, } data = self.message.encode(msg_data, padding=True) logging.debug(msg_data) diff --git a/tools/gui/fgui/misc/can/can_helpers.py b/tools/gui/fgui/misc/can/can_helpers.py index 755ac412..f394d730 100644 --- a/tools/gui/fgui/misc/can/can_helpers.py +++ b/tools/gui/fgui/misc/can/can_helpers.py @@ -56,7 +56,7 @@ ) from fgui.misc.can.can_constants import DEFAULT_BAUD_RATE -# we need to pylint's disable=abstract-class-instantiated it is used since the +# we need to set up pylint disable=abstract-class-instantiated it is used since the # 'python-can' documentation tells that this is the way to use it. See # https://python-can.readthedocs.io/en/master/configuration.html diff --git a/tools/ide/vscode/c_cpp_properties.json.jinja2 b/tools/ide/vscode/c_cpp_properties.json.jinja2 index a94f6e4a..70d80392 100644 --- a/tools/ide/vscode/c_cpp_properties.json.jinja2 +++ b/tools/ide/vscode/c_cpp_properties.json.jinja2 @@ -4,7 +4,8 @@ "${workspaceFolder}/build/bin/src/app/main", "${workspaceFolder}/build/bin/src/hal/include", "${workspaceFolder}/build/bin/src/hal/source", - "${workspaceFolder}/build/unit_test/test/mocks", + "${workspaceFolder}/build/unit_test/test/mocks/**", + "${workspaceFolder}/build/unit_test/vendor/**", "${workspaceFolder}/src/app/application/algorithm", "${workspaceFolder}/src/app/application/algorithm/config", "${workspaceFolder}/src/app/application/algorithm/moving_average", @@ -45,9 +46,8 @@ "${workspaceFolder}/src/app/driver/mcu", "${workspaceFolder}/src/app/driver/meas", "${workspaceFolder}/src/app/driver/afe/api", - "${workspaceFolder}/src/app/driver/afe/{{ AFE_MANUFACTURER }}/api/**", - "${workspaceFolder}/src/app/driver/afe/{{ AFE_MANUFACTURER }}/common/**", - "${workspaceFolder}/src/app/driver/afe/{{ AFE_MANUFACTURER }}/{{ AFE_IC }}/**", + {% for afe_include in AFE_INCLUDES %}"${workspaceFolder}/{{ afe_include }}", + {% endfor -%} "${workspaceFolder}/src/app/driver/pex", "${workspaceFolder}/src/app/driver/pwm", "${workspaceFolder}/src/app/driver/rtc", @@ -60,7 +60,7 @@ "${workspaceFolder}/src/app/driver/ts/epcos/b57251v5103j060", "${workspaceFolder}/src/app/driver/ts/epcos/b57861s0103f045", "${workspaceFolder}/src/app/driver/ts/fake/none", - "${workspaceFolder}/src/app/driver/ts/murata/ncu15xh103f6sxx", + "${workspaceFolder}/src/app/driver/ts/murata/ncxxxxh103", "${workspaceFolder}/src/app/driver/ts/vishay/ntcalug01a103g", "${workspaceFolder}/src/app/driver/ts/vishay/ntcle317e4103sba", "${workspaceFolder}/src/app/driver/ts/{{TEMPERATURE_SENSOR_MANUFACTURER}}/{{TEMPERATURE_SENSOR_MODEL}}/{{TEMPERATURE_SENSOR_METHOD}}", @@ -68,7 +68,7 @@ "${workspaceFolder}/src/app/engine/database", "${workspaceFolder}/src/app/engine/diag", "${workspaceFolder}/src/app/engine/diag/cbs", - "${workspaceFolder}/src/app/engine/hwinfo", + "${workspaceFolder}/src/app/engine/hw_info", "${workspaceFolder}/src/app/engine/sys", "${workspaceFolder}/src/app/engine/sys_mon", "${workspaceFolder}/src/app/main/include", @@ -104,6 +104,7 @@ ], "limitSymbolsToIncludedHeaders": true }, + "compilerPath": "", "defines": [ {% for define in DEFINES %}"{{ define[0] }}={{ define[1] }}"{%if not loop.last %},{%endif%} {% endfor %} diff --git a/tools/ide/vscode/cspell.json.jinja2 b/tools/ide/vscode/cspell.json.jinja2 index 7e70db45..84d74b32 100644 --- a/tools/ide/vscode/cspell.json.jinja2 +++ b/tools/ide/vscode/cspell.json.jinja2 @@ -1,8 +1,5 @@ -// cSpell Settings { - // Version of the setting file. Always 0.2 "version": "0.2", - // language - current active spelling language "language": "en", "enabledLanguageIds": [ "bat", @@ -23,14 +20,15 @@ "xml", "yaml" ], - // words - list of words to be always considered correct "words": [ "alphanumericals", "archiver", "cacheable", + "busbar", "contactor", "contactors", "deci", + "derating", "endianness", "favicon", "initialisms", @@ -50,6 +48,7 @@ "phosphane", "pinout", "pinouts", + "powerline", "precharge", "precharged", "precharging", @@ -77,152 +76,138 @@ "typedefed", "undertemperature", "undervoltage", + "unenumerated", "uninitialization", "uninitialize", "uninstallation", "unversioned", "vendored", "warnable", - // Abbreviations - "pdfs", // plural PDF - "pkgs", // plural packages - "Mbit" // megabit + "pdfs", // Abbreviation: plural PDF + "pkgs", // Abbreviation: plural packages + "Mbit" // Abbreviation: megabit ], "enabled": true, "allowCompoundWords": false, "ignoreWords": [ - // project name - "foxbms", - "foxBMS", - "FOXBMS", - // some german words - "angewandten", - "Forschung", - "Foerderung", - "IISB", - "Schottkystrasse", - "Erlangen", + "foxbms", // project name file name friendly + "foxBMS", // project name in correct casing + "FOXBMS", // project name used in code, e.g., in macros + "angewandten", // german word used in the license header + "Forschung", // german word used in the license header + "Foerderung", // german word used in the license header + "IISB", // Short name for Fraunhofer Institute for Integrated Systems and Device Technology + "Schottkystrasse", // german word used in the license header + "Erlangen", // german word used in the license header // Company and product names - "Altium", - "Cppcheck", // a static program analysis tool - "GitHub", - "GitLab", - "Mictor", - "OSHWA", // Open Source Hardware Association - "SAMTEC", // company - "JFLASH", - "Molex", - "orcid", - "wuerth", - "zenodo", - // user name in the documentation - "vulpes", - "fgui", - "lvac", // gui frame name - // Windows related - "USERPROFILE", - "CODEPAGE", - "ERRORLEVEL", - "LOCALAPPDATA", - "APPDATA", - // cmd, batch - "chcp", - "dpfn", - "enabledelayedexpansion", - "enableextensions", - "findstr", - "popd", - "usebackq", - "pushd", - "setlocal", - "xcopy", - // NSIS installer arguments - "noassocfiles", - "nomodpath", - // bash - "substr", - "gsub", - // file extensions - "vsdx", - // file names - "isonum", - "fstartup", - "foxmath", - "portasm", - // prefixes we use in our embedded sources - "AFE", // Analog Front-End - "AFES", // Analog Front-Ends - "BALS", - "CANRX", // CAN receive - "CANTX", // CAN transmit - "HTSEN", - "ILCK", - "SYSM", - "FTSK", - "FTASK", + "Altium", // Name: Company + "Cppcheck", // Name:Software: static program analysis tool + "GitHub", // Name:Company + "GitLab", // Name:Company + "Mictor", // Name:Product: connector from TE Connectivity (Matched Impedance ConnecTOR) + "OSHWA", // Abbrevation:Organization: Open Source Hardware Association + "SAMTEC", // Name:Company + "JFLASH", // Name:Product: MCU flashing tool from Segger + "Molex", // Name:Company + "orcid", // Abbrevation:Organization: Open Researcher Contributor Identification Initiative + "wuerth", // Name:Company + "zenodo", // Name:Product: general-purpose open repository + "vulpes", // user name in the documentation, latin for fox + "fgui", // Name: name of the Python package that implements the foxBMS 2 GUI + "lvac", // name: name of a frame in the foxBMS 2 GUI + "USERPROFILE", // Windows environment variable name + "CODEPAGE", // Windows environment variable name + "ERRORLEVEL", // Windows environment variable name + "LOCALAPPDATA", // Windows environment variable name + "APPDATA", // Windows environment variable name + "chcp", // cmd.exe: command + "dpfn", // cmd.exe: command + "enabledelayedexpansion", // cmd.exe: Batch command + "enableextensions", // cmd.exe: Batch command + "findstr", // cmd.exe: command + "popd", // cmd.exe: command + "usebackq", // cmd.exe: command + "pushd", // cmd.exe: command + "setlocal", // cmd.exe: command + "xcopy", // cmd.exe: command + "noassocfiles", // NSIS installer argument + "nomodpath", // NSIS installer argument + "substr", // bash: command + "gsub", // bash: command + "vsdx", // file extension + "isonum", // Name: name of file(s) in the repository + "fstartup", // Name: name of file(s) in the repository + "foxmath", // Name: name of file(s) in the repository + "portasm", // Name: name of file(s) in the repository + "AFE", // Code:foxBMS:Prefix: Analog Front-End + "AFES", // see AFE + "BALS", // Code:foxBMS:Prefix: Balancing strategy + "CANRX", // Code:foxBMS:Prefix: CAN receive + "CANTX", // Code:foxBMS:Prefix: CAN transmit + "HTSEN", // Code:foxBMS:Prefix: + "ILCK", // Code:foxBMS:Prefix: + "SYSM", // Code:foxBMS:Prefix: + "FTSK", // Code:foxBMS:Prefix: + "FTASK", // Code:foxBMS:Prefix: "EMIF", // Extended Memory Interface - "NOIMD", - "MRC", - "fstd", + "NOIMD", // Code:foxBMS:Prefix: + "MRC", // Code:foxBMS:Prefix: + "fstd", // Name: name of file(s) in the repository "SHAREDRAM", - //unit componds - "ddeg", - "perc", - // C standard header - "assert", - "complex", - "ctype", - "errno", - "fenv", - "float", - "inttypes", - "iso646", - "limits", - "locale", - "math", - "setjmp", - "signal", - "stdalign", - "stdarg", - "stdatomic", - "stdbool", - "stddef", - "stdint", - "stdio", - "stdlib", - "stdnoreturn", - "string", - "tgmath", - "threads", - "time", - "uchar", - "wchar", - "wctype", - // C functions - "realloc", - // general software terms - "MOSFET", - "memcpy", - "realloc", - "calloc", - "mcalloc", - "NTFS", - "JTAG", + "ddeg", // code:unit componds: deci degree + "perc", // code:unit componds: percentage + "assert", // C standard header file + "complex", // C standard header file + "ctype", // C standard header file + "errno", // C standard header file + "fenv", // C standard header file + "float", // C standard header file + "inttypes", // C standard header file + "iso646", // C standard header file + "limits", // C standard header file + "locale", // C standard header file + "math", // C standard header file + "setjmp", // C standard header file + "signal", // C standard header file + "stdalign", // C standard header file + "stdarg", // C standard header file + "stdatomic", // C standard header file + "stdbool", // C standard header file + "stddef", // C standard header file + "stdint", // C standard header file + "stdio", // C standard header file + "stdlib", // C standard header file + "stdnoreturn", // C standard header file + "string", // C standard header file + "tgmath", // C standard header file + "threads", // C standard header file + "time", // C standard header file + "uchar", // C standard header file + "wchar", // C standard header file + "wctype", // C standard header file + "realloc", // C standard function + "MOSFET", // metal-oxide-semiconductor field-effect transistor + "memcpy", // C standard function + "realloc", // C standard function + "calloc", // C standard function + "mcalloc", // C standard function + "NTFS", // Abbrevation: New Technology File System + "JTAG", // Abbrevation:Standard: Joint Test Action Group "unstaged", "Traceback", "GCCRLE", - "LGPL", - "SPDX", - "TSPA", + "LGPL", // License: GNU Lesser General Public License + "SPDX", // Abbrevation:Standard: Software Package Data Exchange + "TSPA", // Abbrevation:License: TECHNOLOGY AND SOFTWARE PUBLICLY AVAILABLE "automodule", "autoclass", - "LLVM", + "LLVM", // Name:Software: set of compiler and toolchain technologies "untracked", - "mingw", - "mutex", - "posix", - "envs", - "devel", + "mingw", // Abbrevation:Software: Minimalist GNU for Windows + "mutex", // Abbrevation:Software: + "posix", // Abbrevation:Standard: Portable Operating System Interface + "envs", // Abbrevation:Generic: environments + "devel", // Abbrevation:Generic: development "libc", "Ooff", "cflags", @@ -232,8 +217,8 @@ "printf", "memset", "memwidth", - "threadsafe", - "threadsafety", + "threadsafe", // Abbrevation:Software: + "threadsafety", // Abbrevation:Software: "vlog", "tskdef", "forcolon", @@ -253,14 +238,11 @@ "SIMO", "SOMI", "docref", - // bender - "VIFC", // Vehicle Interface Controller - // ARM - "curpc", - "SPSR", - // ARM Assembler - "orreq", - "msreq", + "VIFC", // Abbrevation:Bender: Vehicle Interface Controller + "curpc", // ARM + "SPSR", // ARM + "orreq", // ARM Assembler + "msreq", // ARM Assembler // Compound words in defines, abbreveations from HAL, etc. "SPIDATAFMT_t", // TI: driver code "ecap", // TI: abbrevation for "Enhanced Capture" driver @@ -272,6 +254,7 @@ "RAMREG", // TI: driver code "SIGREGL", // TI: driver code "SIGREGH", // TI: driver code + "DIEDL", // TI: register name "ADDMODERD", "ADDMODEWR", "CSHOLD", @@ -453,79 +436,145 @@ "I2CRDATA2", "CRDATA", "GNDL", - // Maxim driver related words - "fmea", - "uphost", - "downhost", - "KBPS", - // NXP related words and abbrevations - "NXPFS", - "RSTB", - "OVUV", - "OVUVREG", - "FSSM", - "INTB", - "AMUX", - "VMON", - "REGX", - "DEVICEID", - "LBIST", - "BIST", - "ABIST", - "PGOOD", - "VCOREMON", - "VDDIO", - "FTTI", - "FCCU", - "INITFS", - "VBOSUVH", - "VBOOSTUVH", - "VSUPUV", - "VPREUVL", - "VPREUVH", - "VSUPUVL", - "VSUPUVH", - "BTFB", - "BTSC", - // protocols - "UART", - // standards - "misra", - // hardware abbreveations or hardware components - "fram", // Ferroelectric Random Access Memory - "isabellenhuette", - "tektronix", - "pcan", // Prodcut of the company PEAK Systems GmBH + // ADI driver related words + "ades", // ADI ADESxxxx + // ADES1830 + "AUXREGS", // ADI ADES1830: Auxiliary registers + "AUXADC", // ADI ADES1830: Auxiliary ADC + "DTMEN", // ADI ADES1830: Discharge Timer Monitor enable + "DTRNG", // ADI ADES1830: Discharge Timer Range setting + "SOAKON", // ADI ADES1830: soak enable + "OWRNG", // ADI ADES1830: soak time range + "RDSID", // ADI ADES1830: Read serial ID + "CFGRB", // ADI ADES1830: Configuration Register B + "RSTCC", // ADI ADES1830: Clear command counter + "RSTF", // ADI ADES1830: reset filter + "TREFUP", // ADI ADES1830: IC pause time to allow the reference to power up + "VGPIO", // ADI ADES1830: safety + "OSCCHK", // ADI ADES1830: safety + "RDSTATA", // ADI ADES1830: safety + "RDSTATB", // ADI ADES1830: safety + "RDSTATC", // ADI ADES1830: safety + "RDSTATD", // ADI ADES1830: safety + "RDSTATE", // ADI ADES1830: safety + "STCR", // ADI ADES1830: register + "CMED", // ADI ADES1830: flag + "SMED", // ADI ADES1830: flag + "THSD", // ADI ADES1830: flag + "SPIFLT", // ADI ADES1830: SPI fault flag + "VDEL", // ADI ADES1830: supply rail delta latent + "CLRFLAG", // ADI ADES1830: command + "STDR", // ADI ADES1830: register + "CNTR", // ADI ADES1830: counter + "CFGRA", // ADI ADES1830: register + "TMODCHK", // ADI ADES1830: flag + "RDAC", // ADI ADES1830 command + "RDACA", // ADI ADES1830: Averaged Cell Voltage Register Group A + "RDACB", // ADI ADES1830: Averaged Cell Voltage Register Group B + "RDACC", // ADI ADES1830: Averaged Cell Voltage Register Group C + "RDACD", // ADI ADES1830: Averaged Cell Voltage Register Group D + "RDACE", // ADI ADES1830: Averaged Cell Voltage Register Group E + "RDACF", // ADI ADES1830: Averaged Cell Voltage Register Group F + "RDFCA", // ADI ADES1830: Filter Cell Voltage Register Group A + "RDFCB", // ADI ADES1830: Filter Cell Voltage Register Group B + "RDFCC", // ADI ADES1830: Filter Cell Voltage Register Group C + "RDFCD", // ADI ADES1830: Filter Cell Voltage Register Group D + "RDFCE", // ADI ADES1830: Filter Cell Voltage Register Group E + "RDFCF", // ADI ADES1830: Filter Cell Voltage Register Group F + "RDFC", // ADI ADES1830 command + "VCELL", // ADI generic for 'cell Voltage' + "RDCV", // ADI ADES1830: read cell voltage RDCVn + "RDCVALL", // ADI ADES1830: read all cell voltages + "RDSV", // ADI ADES1830: read s voltage register RDSVn + "RDSVA", // ADI ADES1830: read s voltage register RDSVA + "RDSVB", // ADI ADES1830: read s voltage register RDSVB + "RDSVC", // ADI ADES1830: read s voltage register RDSVC + "RDSVD", // ADI ADES1830: read s voltage register RDSVD + "RDSVE", // ADI ADES1830: read s voltage register RDSVE + "RDSVF", // ADI ADES1830: read s voltage register RDSVF + "RDRAXA", // ADI ADES1830: redundant auxiliary register A + "RDRAXB", // ADI ADES1830: redundant auxiliary register B + "RDRAXC", // ADI ADES1830: redundant auxiliary register C + "RDRAXD", // ADI ADES1830: redundant auxiliary register D + "ADSV", // ADI ADES1830 safety: command + "RDPWMA", // ADI ADES1830 safety: command: Read PWM register Group A + "WRPWMA", // ADI ADES1830 safety: command: Write PWM register Group A + "RDPWMB", // ADI ADES1830 safety: command: Read PWM register Group B + "WRPWMB", // ADI ADES1830 safety: command: Write PWM register Group B + "ITMP", // ADI ADES1830 status Register Group A (RDSTATA) - STBR2 & STBR3 + "VRES", // ADI ADES1830 status Register Group B (RDSTATA) - STBR4 + "DIETEMP", // ADI ADES1830 safety: generic abbrevation die temperature + "TMOD", // ADI ADES1830 safety: test mode + "RDAUXE", // ADI ADES1830: Read Auxiliary Register Group E + "unsnapshot", // ADI ADES1830: new word + "fmea", // MAXIM: driver related words + "uphost", // MAXIM: driver related words + "downhost", // MAXIM: driver related words + "KBPS", // MAXIM: driver related words + "NXPFS", // NXP: + "RSTB", // NXP: + "OVUV", // NXP: + "OVUVREG", // NXP: + "FSSM", // NXP: + "INTB", // NXP: + "AMUX", // NXP: + "VMON", // NXP: + "REGX", // NXP: + "DEVICEID", // NXP: + "LBIST", // NXP: + "BIST", // NXP: + "ABIST", // NXP: + "PGOOD", // NXP: + "VCOREMON", // NXP: + "VDDIO", // NXP: + "FTTI", // NXP: + "FCCU", // NXP: + "INITFS", // NXP: + "VBOSUVH", // NXP: + "VBOOSTUVH", // NXP: + "VSUPUV", // NXP: + "VPREUVL", // NXP: + "VPREUVH", // NXP: + "VSUPUVL", // NXP: + "VSUPUVH", // NXP: + "BTFB", // NXP: + "BTSC", // NXP: + "UART", // Abbrevation: Universal Asynchronous Receiver Transmitter + "misra", // Abbrevation: Motor Industry Software Reliability Association + "fram", // Abbrevation: Ferroelectric Random Access Memory + "isabellenhuette", // Name:Company + "tektronix", // Name:Company + "pcan", // PEAK: Prodcut of the company PEAK Systems GmBH "USBBUS", // name of the PCAN USB buses in the "python-can" library - "lauterbach", - "epcos", - "murata", - "vishay", - "mram", // Magnetoresistive Random Access Memory + "SENDRECEIVE", // PEAK: reserved name in 'sym' files from PEAK Systems GmBH + "lauterbach", // Name:Company + "epcos", // Name:Company + "murata", // Name:Company + "vishay", // Name:Company + "mram", // Abbrevation:Magnetoresistive Random Access Memory "ntcalug", // temperature sensor form vishay "ntcle", // temperature sensor form vishay "OHKS", // digital status pin from Bender IR155 - // Axivion - "axivion", - "cafecc", - "Codeline", - "gravis", - "larg", - "preinc", - "dashserver", - "localbuild", - "noauth", - "workitem", - "TESTCASE", - // asm keywords - "endasmfunc", + "axivion", // Name:Company + "cafecc", // Axivion: compiler name + "Codeline", // Axivion + "gravis", // Axivion: tool name + "larg", // Axivion: linker argument name + "preinc", // Axivion + "dashserver", // Axivion: tool name + "localbuild", // Axivion: tool name + "noauth", // Axivion + "workitem", // Axivion + "irdump", // Axivion: tool name + "TESTCASE", // Axivion + "endasmfunc", // TI ARM CGT asm keyword // third party software, tools, configuration files etc. - "doxygen", + "doxygen", // Name:Software: Documentation softare "rcfile", "filecvt", "marm", "dilfile", - "Segger", + "Segger", // Name:Company "Jupyter", "rubyinstaller", "rubygems", @@ -568,29 +617,27 @@ "mklib", "gmake", "ruby", - "ceedling", - "ceedlingproject", "Mockbeta", "Mockdatabase", "Mockepcos", "Mockmath", - "freertos", - "safertos", - "rtos", + "freertos", // Name:Software + "safertos", // Name:Software + "rtos", // Abbrevation:Generic "jdebug", "gcov", - "gcovr", - "msys", + "gcovr", // Name:Python: package + "msys", // Abbrevation:Software: Minimal SYStem "lcov", "devkit", "conda", "condarc", "miniconda", "halcogen", - // ceedling - "cmock", - // html - "endverbatim", + "ceedling", // Name:Software: ceedling project + "cmock", // Name:Software: Cmock project + "cexception", // Name:Software: CException project + "endverbatim", // Keyword:Doxygen // waf "APPNAME", "autoconfig", @@ -631,27 +678,23 @@ "tooldir", "uselib", "waflib", - "waf's", "wscript", - // variables in wscript - "confpy", - // rst - "linkcheck", - "stringliteral", - "toctree", - "titlesonly", - "maxdepth", - "numref", - "linenos", - "literalinclude", - "subsubsection", - "subsubsections", - "doxygenfunction", - "genindex", - "modindex", + "linkcheck", // sphinx + "stringliteral", // reStructuredText + "toctree", // reStructuredText + "titlesonly", // reStructuredText + "maxdepth", // reStructuredText + "numref", // reStructuredText + "linenos", // reStructuredText + "literalinclude", // reStructuredText + "subsubsection", // reStructuredText + "subsubsections", // reStructuredText + "doxygenfunction", // reStructuredText + "genindex", // reStructuredText + "modindex", // reStructuredText // python "maxsplit", - "arcname", // 'tar' package + "arcname", // Python:package: tar "pycache", "getenv", "pypi", @@ -660,9 +703,9 @@ "pylintrc", "pyproject", "groupby", - "linesep", // 'os' package - "pathsep", // 'os' package - "platformdirs", + "linesep", // Python:package:os + "pathsep", // Python:package:os + "platformdirs", // Name:Python: package "popen", "tzname", "rglob", @@ -670,81 +713,70 @@ "finditer", "hexlify", "startswith", - // python packages - "cantools", - "jsonschema", - "cffconvert", - "clib", - "gprof2dot", - "iterrows", - "pstats", - "numpy", - "matplotlib", - "mypy", - "statsmodels", - "scikit", - "filterpy", - "dask", - "scipy", - "seaborn", - "pykwalify", - "qtconsole", - "qtpy", - "ruamel", - //wxpython - "vscroll", // style - "Colour", // BackgroundColour etc. - "gridlib", // subpackge of wx.grid - "RADIOBOX", // wxpython control window name - "NUMPAD", // wxpython Event name - "CHECKLISTBOX", // wxpython control window name - "CHOICEDLG", // wxpython choice dialog - // python-can - "bustype", - // matplotlib - "xlabel", - "ylabel", - "pyplot", - // graphviz - "fillcolor", - "graphviz", - "lhead", - "invis", - "fontcolor", - "darkgreen", - "nodesep", - "ranksep", - "ltail", - "rankdir", - "doublecircle", - // sphinx - "autofunction", - "numfig", - "delim", - //latex - "mathrm", - // compiler flags - "DASSERT", - "flto", - // compiler derived words - "hexgen", - "preproc", - // cc-options.yaml - "LINKFLAGS", - "HEXGENFLAGS", - "NMFLAGS", - // misc - "Zener", - "pprs" + "cantools", // Name:Python: package + "jsonschema", // Name:Python: package + "cffconvert", // Name:Python: package + "clib", // Name:Python: package + "gprof2dot", // Name:Python: package + "iterrows", // Name:Python: package + "pstats", // Name:Python: package + "numpy", // Name:Python: package + "matplotlib", // Name:Python: package + "mypy", // Name:Python: package + "statsmodels", // Name:Python: package + "scikit", // Name:Python: package + "filterpy", // Name:Python: package + "dask", // Name:Python: package + "scipy", // Name:Python: package + "seaborn", // Name:Python: package + "pykwalify", // Name:Python: package + "qtconsole", // Name:Python: package + "qtpy", // Name:Python: package + "ruamel", // Name:Python: package + "vscroll", // Python:package: wxpython + "Colour", // Python:package: wxpython + "gridlib", // Python:package: wxpython + "RADIOBOX", // Python:package: wxpython + "NUMPAD", // Python:package: wxpython + "CHECKLISTBOX", // Python:package: wxpython + "CHOICEDLG", // Python:package: wxpython + "bustype", // Python:package:python-can + "xlabel", // Python:package: matplotlib + "ylabel", // Python:package: matplotlib + "pyplot", // Python:package: matplotlib + "fillcolor", // graphviz + "graphviz", // graphviz + "lhead", // graphviz + "invis", // graphviz + "fontcolor", // graphviz + "darkgreen", // graphviz + "nodesep", // graphviz + "ranksep", // graphviz + "ltail", // graphviz + "rankdir", // graphviz + "doublecircle", // graphviz + "autofunction", // sphinx + "numfig", // sphinx + "delim", // sphinx + "mathrm", // LaTeX + "flto", // Linker flag + "hexgen", // // compiler derived words + "preproc", // // compiler derived words + "LINKFLAGS", // option name in cc-options.yaml + "HEXGENFLAGS", // option name in cc-options.yaml + "NMFLAGS", // option name in cc-options.yaml + "Zener", // Zener diode + "TIDUM", // prefix + "pprs" // file extension ], "dictionaries": [ + "companies", "cpp", + "misc", "python", - "wordsEn", - "wordsEnGb", - "companies", "softwareTerms", - "misc" + "wordsEn", + "wordsEnGb" ], "flagWords": [ "endianess", @@ -759,7 +791,7 @@ "**/vscode-extension/**", ".clang-format", ".git*", - ".lock-waf_*", // waf's lock file in the top level + ".lock-waf_*", ".mailmap", ".vscode", "BSD-3-Clause.txt", @@ -771,7 +803,7 @@ "conf/guidelines/rules.json", "conf/hcg/**", "conf/spa/.pylintrc", - "conf/unit/ceedling.cmd", + "conf/spell/**", "conf/unit/project.yml", "conf/unit/vsc-settings.yml", "docs/_ext/**", @@ -819,15 +851,20 @@ "tests/axivion/predefined_macros.txt", "tests/axivion/qualification-test/qualification-kit/**", "tests/axivion/rule_config_c.json", + "tests/env/conda_env_linux.json", + "tests/env/conda_env_win32.json", "tests/re-names/*.json", + "tests/unit/build.mocks.json", + "tests/unit/build.tests.json", "tools/dbc/*.dbc", "tools/dbc/*.sym", "tools/debugger/lauterbach/*.in", "tools/debugger/ozone/*.jdebug.*", - "tools/debugger/ozone\foxbms.jflash", - "tools/gui/fgui/misc/logo.py", // just binary code - "tools/waf", // waf binary - "tools/waf3-*/**", // unpacked waf sources + "tools/debugger/ozone/foxbms.jflash", + "tools/gui/fgui/misc/logo.py", + "tools/vendor/**", + "tools/waf", + "tools/waf3-*/**", "tools/waf-verify-sig.py" ] } diff --git a/tools/ide/vscode/settings.json.jinja2 b/tools/ide/vscode/settings.json.jinja2 index 35bb05da..00def626 100644 --- a/tools/ide/vscode/settings.json.jinja2 +++ b/tools/ide/vscode/settings.json.jinja2 @@ -3,62 +3,63 @@ "files.encoding": "utf8", "files.autoGuessEncoding": true, "files.exclude": { + "**/*.gcov": true, + "**/*.stats": true, + "**/*.zip": true, + "**/.DS_Store": true, "**/.git": true, - "**/.svn": true, "**/.hg": true, - "**/CVS": true, - "**/.DS_Store": true, - "**/LLVM/**": true, + "**/.lock-waf_*_build": true, + "**/.svn": true, + "**/.wafpickle-*": true, "**/__pycache__/**": true, - "**/build/**/*.swi.json": true, "**/build/**/*.a": true, + "**/build/**/*.aux": true, "**/build/**/*.crl": true, - "**/build/**/*.rl": true, - "**/build/**/*.obj": true, "**/build/**/*.log": true, - "**/build/**/*.aux": true, + "**/build/**/*.obj": true, "**/build/**/*.pp": true, "**/build/**/*.ppd": true, "**/build/**/*.ppi": true, "**/build/**/*.ppm": true, "**/build/**/*.ppr": true, "**/build/**/*.pprs": true, + "**/build/**/*.rl": true, + "**/build/**/*.swi.json": true, "**/conf/hcg/include/**": true, + "**/CVS": true, + "**/LLVM/**": true, ".github/**": true, ".gitlab/**": true, ".vscode/**": true, - "build/tmp**": true, - "build/c4che/**": true, "build/axivion/**": true, + "build/c4che/**": true, "build/conf_check_*/**": true, "build/predefined_defines/**": true, - "**/.lock-waf_*_build": true, - "**/.wafpickle-*": true, - "**/*.gcov": true, - "**/*.zip": true + "build/tmp**": true }, "files.watcherExclude": { "**/.git/objects/**": true, "**/.git/subtree-cache/**": true, - "**/waf-3-*/**": true, - "**/LLVM/**": true, "**/__pycache__/**": true, "**/build/**/*.pp": true, "**/build/**/*.ppr": true, "**/build/**/*.pprs": true, "**/conf/hcg/include/**": true, + "**/LLVM/**": true, + "**/waf-3-*/**": true, "tests/axivion/qualification-kit/**": true }, "search.exclude": { - "**/node_modules": true, - "**/bower_components": true, "**/*.code-search": true, + "**/bower_components": true, + "**/conf/hcg/include/**": true, "**/LLVM/**": true, + "**/node_modules": true, "**build/**/*.obj": true, "**build/**/*.pp": true, "**build/**/*.ppr": true, "**build/**/*.pprs": true, - "**/conf/hcg/include/**": true, "tests/axivion/qualification-kit/**": true }, "css.validate": false, @@ -117,7 +118,7 @@ 79 ], "[shellscript]": { - "files.eol": "\n", + "files.eol": "\n" }, "editor.formatOnSave": true, "editor.bracketPairColorization.enabled": true, @@ -126,14 +127,14 @@ "editor.formatOnSave": true, "editor.rulers": [ 79 - ], + ] }, "[python]": { "files.encoding": "utf8", "editor.formatOnSave": true, "editor.rulers": [ 79 - ], + ] }, "[c]": { "editor.formatOnSave": true, @@ -145,8 +146,8 @@ { "column": 119, "color": "#ff0000" - }, - ], + } + ] }, "[html]": { "editor.formatOnSave": false diff --git a/tools/precharge/precharge_dimensioning.ipynb b/tools/precharge/precharge_dimensioning.ipynb new file mode 100644 index 00000000..0b6f7b46 --- /dev/null +++ b/tools/precharge/precharge_dimensioning.ipynb @@ -0,0 +1,523 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "unsigned-bridges", + "metadata": {}, + "source": [ + "Precharge dimensioning\n", + "----------------------\n", + "\n", + "The capacitor charging starts with an inrush current and ends with an exponential decay down to the steady state condition. When the magnitude of the inrush peak is very large compared to the maximum rating of the components, then component stress is to be expected. The current into a capacitor is known to be $I = C ( d V / d T )$: the peak inrush current will depend upon the capacitance C and the rate of change of the voltage (dV/dT). The inrush current will increase as the capacitance value increases, and the inrush current will increase as the voltage of the power source increases. This second parameter is of primary concern in high voltage power distribution systems. By their nature, high voltage power sources will deliver high voltage into the distribution system. Capacitive loads will then be subject to high inrush currents upon power-up. The stress to the components must be understood and minimized. \n", + "\n", + "This script helps selecting the correct precharge resistor depending on the battery system parameters. This script assumes that a circuit is precharged if we have reached 95% of the system voltage. This equals a time constant of $3\\tau$\n", + "\n", + "Three cases are calculated within this script. One case assumes the maximum current as limiting factor, a second takes the maximum precharge duration as input factor and the last one uses the precharge resistance as input. In the following variables related to the respective cases are indicated with `curReq`, `timReq` and `resReq`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "future-missile", + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from scipy import integrate\n", + "\n", + "# battery system specifications\n", + "outputCapacitance_F = 0.000385 # capacitance that needs to be precharged in F\n", + "maximumBatteryVoltage_V = 823.2 # maximum battery voltage in V\n", + "\n", + "# Case requirements\n", + "timReqPrechargeDuration_s = 0.3 # precharge duration in s\n", + "curReqCurrent_A = 5.0 # maximum allowed current in A\n", + "resReqPrechargeResistance_ohm = 180.0 # precharge resistance in ohm\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "planned-pipeline", + "metadata": {}, + "source": [ + "With the required current limit and the given maximum battery voltage the minimum precharge resistance can be calculated to\n", + "\n", + "$R_{Precharge}$ = $\\frac{V_{Battery}}{I_{max}}$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "russian-offer", + "metadata": {}, + "outputs": [], + "source": [ + "curReqPrechargeResistance_ohm = maximumBatteryVoltage_V / curReqCurrent_A" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "concrete-mercury", + "metadata": {}, + "source": [ + "With the previously calculated precharge resistance we can calculate the precharge duration (to 95%) for this case to\n", + "\n", + "$D$ = $3*\\tau = 3 * R_{precharge} * outputCapacitance_F$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "centered-result", + "metadata": {}, + "outputs": [], + "source": [ + "curReqPrechargeDuration_s = 3.0 * curReqPrechargeResistance_ohm * outputCapacitance_F\n", + "resReqPrechargeDuration_s = 3.0 * resReqPrechargeResistance_ohm * outputCapacitance_F" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "inner-pottery", + "metadata": {}, + "source": [ + "The precharge resistance to fulfill the timing requirement is calculated to:\n", + "\n", + "$\\tau$ = $\\frac{prechargeDuration}{3}$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ceramic-coalition", + "metadata": {}, + "outputs": [], + "source": [ + "curReqTau_s = curReqPrechargeDuration_s/3.0\n", + "timReqTau_s = timReqPrechargeDuration_s/3.0\n", + "resReqTau_s = resReqPrechargeDuration_s/3.0" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "powerful-alabama", + "metadata": {}, + "source": [ + "Starting from the output capacitance and the requirement for the precharge duration, the precharge resistance can be calculated to\n", + "\n", + "$R_{Precharge}$ = $\\frac{\\tau}{outputCapacitance_F}$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "hourly-wesley", + "metadata": {}, + "outputs": [], + "source": [ + "timReqPrechargeResistance_ohm = timReqTau_s / outputCapacitance_F\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "hawaiian-charter", + "metadata": {}, + "source": [ + "This leads to the following results:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "derived-navigator", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Precharge resistance to fullfil the current requirement:\n", + "R_min (ohm):\t164.64000000000001\n", + "D_precharge (s):\t0.19015920000000003\n", + "\\Precharge resistance to fullfil the timing requirement:\n", + "R_max (ohm):\t259.7402597402597\n", + "D_precharge (s):\t0.3\n", + "\\Precharge resistance to fullfil the precharge resistance requirement:\n", + "R_max (ohm):\t180.0\n", + "D_precharge (s):\t0.2079\n" + ] + } + ], + "source": [ + "print(\"Precharge resistance to fullfil the current requirement:\")\n", + "print(\"R_min (ohm):\\t\" + str(curReqPrechargeResistance_ohm))\n", + "print(\"D_precharge (s):\\t\" + str(curReqPrechargeDuration_s))\n", + "\n", + "print(\"\\Precharge resistance to fullfil the timing requirement:\")\n", + "print(\"R_max (ohm):\\t\" + str(timReqPrechargeResistance_ohm))\n", + "print(\"D_precharge (s):\\t\" + str(timReqPrechargeDuration_s))\n", + "\n", + "print(\"\\Precharge resistance to fullfil the precharge resistance requirement:\")\n", + "print(\"R_max (ohm):\\t\" + str(resReqPrechargeResistance_ohm))\n", + "print(\"D_precharge (s):\\t\" + str(resReqPrechargeDuration_s))\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "communist-above", + "metadata": {}, + "source": [ + "Precharge course\n", + "----------------\n", + "\n", + "With a calculated precharge resistance, we can determine the following precharge course for current and voltage during the precharge process:\n", + "\n", + "$I(t) = \\dot{Q} = \\frac{U_{Battery}}{R_{Precharge}}e^{-\\frac{1}{R_{Precharge} C_{out}}t} = \\frac{U_{Battery}}{R_{Precharge}}e^{-\\frac{1}{\\tau}t}$\n", + "\n", + "$U_{System}(t) = U_{Battery}(1 - e^{-\\frac{1}{R_{Precharge}C_{out}}t}) = U_{Battery}(1 - e^{-\\frac{1}{\\tau}t})$\n", + "\n", + "We now calculate the voltage and current values for both the current cases:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "stuffed-jaguar", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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om59kQ07wrNnjGFDUzvvb9jOe+ub+GBjM8s32SXecVFXWcKk+iom1VcyaXgVk4dXeftV1FaWFC4TSdgR9BvMqH7uotq5jernNi7ppy01kmCMWSMiPwRWAq3AAmPMAhEZZYxZ68VZKyIjvVOiTpAoq71jPRCR+cB8sK0e5s+fz4wZMzjkkEP45S9/SW1tLd/+9rf53ve+B8DNN9/MpZdeSkdHBxdeeCGPPPIIy5cv5wtf+AJr167l2Wef5cADD2TixIn84Q9/YKedduKkk07ipptuIhgMcvPNN3PBBRcAcNVVV/GTn/yEzZs3c/bZZ7No0SJef/11jjvOjo3x17/+lVmzZrH//vvz61//mmHDhvGNb3yDK664AoAf//jHHHHEEXzpkCM48YCDufH663l/+XK++MUv8uGHH/LCCy9wyCGHMGbMGB544AEmT57MvHnzuOWWWygtLeX666/noosuAuCaa67hpptuYuvWrZxzzjk8++yzLFmyhBNOOIH29nYWLFjA7NmzmT17Nr/5zW8YMWIE5557LldffTUAP/3pTzn//PMBuOSSS7j33ntZs2YNJ598Mu+99x6LFi1i7ty51NfX89BDDzF16lSOP/54br31VioqKrjqqqu4+OKLAbj++uu59tpr2b59O+eddx4LFy5k6dKlzJs3j6amJhYuXMicOXOYMWMGd999N6NHj+bMM8/k2muv7WXLZZddxp133sm6des49dRTWbJkCS+//DJHHnkkNTU1PPLII0yfPp0jjzyS2267jerqai677DIuvfRSAG688UauuOIKWltb+frXv84TTzzB+++/z2c/+1kaGhp4+umn2X///Zk2bRr33Xcf48aN45RTTuGGG27oZcvll1/OL37xCzZu3MgZZ5zB4sWL+fnPf84VV1xBWVkZjz32mFNl76KLLiIcDvPtb3+bP/7xj6xcuXKHKnvnnHMOJ554Yr+XvfN++EPW7L47o046ib+1tNDs9Z2sbG1lxNKlzK+oYMKKFax49FE+NmdOd9lbkrbs/RyalnHGCVPpXLOQYeG3GFmxDYCIETZ1jUVGHMXj/97ExsgUTjv/Or73v5cDm7n55uMHXdl78cUXWbhwoZNlL77eM8DFV/2Ai6/5EduDNew8+yBefnc1jeEyugIxh0R50DC6UghvWsW+Qys4aM9deP5vjzCywnDVt7/DpZde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P9s8P9s8P7s8O9s8P9s8v7JEJElEThCR4dVd4iIl5H29gR+patQ8AlUtFJG/A6/E8M6/AHcQjPIo0lZVN0Xa3CQiRUvCdgTmlbhvfeRcFBGZAEwASElJYcKECfTs2ZNhw4bx2GOPkZmZye23385vfvMbAB566CHuvPNODh48yC233MLkyZNZs2YNF110EZs2bWLWrFkMHjyYzp078+KLL3LkkUcybtw4HnzwQZKTk3nooYe4+eabAbj33nt5+OGH2blzJ+PHj2f+/Pl89tlnnH322QBMnTqVXr16MXDgQJ588klatGjBTTfdxN133x38j/GXv7Bu3TomTJjA7bffzssvv8y3337LJZdcQlZWFnPmzGHYsGG0b9+eV155ha5duzJmzBj+/Oc/k5qayv333394v+Pf//73PPjgg+zZs4ef/exnzJo1i+XLl/ODH/yAvLw83n33Xfr27Uvfvn156qmnaN26Nddddx333XcfAH/961+54YYbAPjlL3/JiytXcnNqKjkTJzLlm2+YP38+I0aMoGXLlkyaNIn37rqLHi1acNPNN9OoUSOG9GrFX5+BXz38PrfedzETJ07kulNG0jEJHpv8CitXrmTMmDFkZ2czffp0+vfvT8+ePXnmmWdo164d1157LRMnTizTl1//+tfc88wMUgqb0nDn1zzxxBQWLlzIqFGjyMjIYPLkyRx33HGMGjWKv/3tbzRp0oRf//rX3HnnnQD84Q9/4O6772b//v3ceOONvP3226xevZqxY8eyY8cOZsyYwcCBAznmmGN4/vnn6dixI5dffnmwk0upvtx11108+uijbNu2jWuuuYbFixeTlZXFa6+9RlpaGlOmTDH13bv11lspKCiod9+95557jg0bNnDZZZexatWqMt+9o48+mnPOOYdHHnmERo0ace+993LHHXcAcP/99zNx4kT27dvH9ddfz/Tp0yv87mVlZXHXXXdV+t375z//yebNm7nyyitZvnx5vfruLV68mDPPPPN7+93Lyspi69atJr97Yf67913/7h1xxBE899xzJr97lv+7F6/v3gknnMCECRNMfvcs/3cvHt+90aNHM2HCBLPfPcv/3YvHd09EmDBhgsnvnvX/7sXju5eVlcW9995r4rtXG0TkeuBuoGXk1ABgkYhMBj5Q1UdCNaSqVR7ALuCSCq5dAuwK2c55wN8jfx4B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WVkZzz77LCUlJaxcuZIbbriBbt26Rc+gmDVrFgsXLuTRRx9l0KBBzJ07l6effppTTz012v+dd97Jc889x5w5czjhhBNYsWIF119/PcXFxVx44YUJn+fy5cs5/vjj6dKlS7Rtz549nHPOOZSWlrJkyRLKysr4+OOPk3zlDqioqODpp5/mP/7jPwgEAuTm5jbZ5rPPPuPVV18lOzs72vbII4/wy1/+kocffpjTTjuNdevWcf3115Odnc2kSZMIBoNceumlFBcXs2LFCvbu3cvkyZOpqalp0v/QoUN56623mDhxYqvjFxERERERaY6KGhlg8eLF3HnnnekOI2Ndd9113HfffbzxxhuMHj0aCF16Mnr0aI455hh+8YtfcNRRRzF37lx8Ph8nnXQSv/71r7nxxhuZMWMG+fn5cf0VFRURCATIz8+nZ8+e0fasrCzuvvvu6HLv3r358MMPeeaZZ6JFjYceeojbbruN73//+0BoPJRly5ZF99mzZw8PPvggr732GiNGjACgT58+rFy5kjlz5jRb1KiqquKoo46Ka3v66af58ssvWbFiBd27dwegb9++rX79amtrWbRoET169Ihrf/XVVyksLKShoYH9+/cD8OCDD0bXz5gxg5kzZzJu3Ljo87j99tuZO3cukyZN4o033mDDhg1UVFRw7LHHRl+PyPOOdfTRR/PBBx+0OnYREREREZGWqKiRATZv3py2Y3thiNJ+/fpx9tlns2DBAkaPHs3WrVtZtmwZixcvBkIDhn7729+OnsUBcNZZZ1FbW0t5eTmDBw9O+ljz5s3j0Ucfpaqqin379lFXV8dxxx0HwO7du/nyyy8ZOnRodHsz44wzzmDLli0AbNiwgf379zNmzBjMLLpdXV0dvXv3bva4+/bta3IGxUcffcTgwYOjBY1D1atXryYFDYCzzz6b+fPns2/fPh555BE2bdrEP//zPwOwfft2tmzZwo033shNN90U3Sd2TI5PPvmEsrKyaEEDYNiwYXF5iMjLy2Pfvn2H9TxEREREREQaU1EjA1x++eXpDiHjTZw4keuvv56dO3eycOFCunbtysUXXwyExrCILSDEaq49kcWLFzNlyhRmzZrF8OHD6dy5M3PmzGHJkiVJ9xkZb+KVV16J+7EPxF3a0Vj37t356KOP4toixYPm+Hy+JtvU1dU12a6goCDh/vn5+Rx//PEA/Pa3v2XUqFHMmDGD6dOnR5/HvHnzGD58eML9DxZfrJ07d1JSUpL09iIiIiIiIsnQQKEZoKqqKt0hZLxx48aRm5vLk08+yYIFCxg/fny0SDBgwABWrFgRN4DlO++8QyAQaPZyjUAg0GSA1nfeeYdhw4YxadIkhgwZwvHHH8+mTZui64uKiujZsycrV66Mtjnn4i6rGDBgADk5OVRVVXH88cfHTZEzPhI59dRT2bhxY9xzGDJkCGvXrmXHjh0J9ykpKeGrr76KKy6sWXPoI6Tcdddd3HfffWzdupUePXpQVlbGpk2bmjyPSCFkwIAB/PWvf42epQKwcuXKuOcQsW7dOoYMGXLIsYmIiIiIiCSiokYGeO+999IdQsbLy8vjiiuuYPr06WzatCnu1qc333wzW7du5eabb+aTTz7hD3/4A7fffjuTJk1qMp5GRO/evVm5ciWVlZXs2LGDYDBI//79+fDDD1m6dCl/+ctfmDFjBm+99VbcfpMnT2bmzJksWbKEjRs3csstt/DFF19Ez97o1KkTt956K7feeisLFiygvLycNWvWMG/ePObPn9/s8xs1ahT79+9n7dq10bYrrriC0tJSLrnkEpYvX05FRQUvv/xy9O4nI0eOZOfOnfzqV79i06ZNPPbYYzz33HOH/BqPHDmSgQMHcs899wChO6fMnDmT2bNns3HjRtatW8cTTzzBvffeC4RuCXviiScyfvx41qxZw4oVK5g6dSp+f/wJYHv37mX16tWMGTPmkGMTERERERFJREWNDJBoYEVpauLEiezatYvhw4dz0kknRdvLyspYunQpH330EaeccgrXXnstl19+efTOJonceuutBAIBBgwYQElJCZs3b+bGG2/khz/8IVdccQVnnHEGlZWV3HLLLU32u+qqq7jmmmv41re+BcCll14aNx5G5BKOWbNmMXDgQL773e/y/PPP06dPn2bj6datG//4j//IU089FW0rKCjgrbfeoqysjLFjxzJw4EDuuuuuaAHlpJNO4t///d+ZP38+gwcP5vXXX+fnP/95617URn7605/y2GOPUVVVxcSJE1mwYAGLFi3i5JNPZsSIEcyfPz/6PHw+H0uWLCEYDDJs2DDGjx/PnXfeSU5OTlyfL730Escee6ze5yIiIiIi0uasNdfFe0FBQYHbs2dPusNolTfeeIPzzjuv3Y+zevVqTjvttHY/zpFmyJAhnHnmmTz88MOH1c/69esZNWoU5eXldO7cuY2iS73CwkJ+97vfMWHCBCB0O9cpU6ZwxRVXpDcwERERERGJWr16NevWraOmpoYbbrghbp2Z7XXOJR6cL8PoTI0M8Oyzz6Y7BElSVVUV8+fPZ+PGjaxfv57Jkyfz8ccfc/XVVx923wMHDmTWrFlUVFS0QaSZYdu2bYwbN06D4YqIiIiISLvQ3U8yQEuXJUhm8fl8PPHEE0ybNo1gMMiAAQNYunQpp59+epv0P378+DbpJ1OUlpbys5/9LN1hiIiIiIhIB6WiRga45JJL0h2CJOmYY47hnXfeSXcYGa26ujrdIYiIiIiIyBFCl59kgNmzZ6c7BBERERERERHPUVEjAwQCgZQdKxgMpuxYIiIiIiIiknk60g1DVNTIAPfee29KjhMIBNi7d29KjiUiIiIiIiKZqba2tsMUNlTUyAC33HJLSo5TVlZGeXk51dXVOmNDRERERETkCBQMBqmsrGTXrl00NDSQl5eX7pAOiwYKPYJ07dqV/fv3s2HDBnw+H2aW7pBEREREREQkxfbv38+2bdv429/+xvDhw9MdzmGxjnLKSURBQYHbs2dPusNolW3btlFaWpqy423fvp0XXniBmpqalB2zI9u/fz+5ubnpDkMOgXLnbcqftyl/3qb8eZdy523Kn7dlWv6CwSCDBw9m5MiR+HzxF3GY2V7nXEGaQmsVFTUywLRp07j//vtTesyamhp27dpFfX19So/bEd1///1MmzYt3WHIIVDuvE358zblz9uUP+9S7rxN+fO2TMqfmZGfn0+XLl0SnsHvpaKGLj/JALt37075MXNycujZs2fKj9sR7du3j169eqU7DDkEyp23KX/epvx5m/LnXcqdtyl/3qb8tQ+dqZEBPvzwQ4YMGZLuMOQQKX/epdx5m/Lnbcqftyl/3qXceZvy521eyp+XztTQ3U8ywPLly9MdghwG5c+7lDtvU/68TfnzNuXPu5Q7b1P+vE35ax8qamSA9evXpzsEOQzKn3cpd96m/Hmb8udtyp93KXfepvx5m/LXPjrc5SdmFgT2pTuOVvIDGrHTu5Q/71LuvE358zblz9uUP+9S7rxN+fM2L+UvzznniZMgOlxRw4vMbJVz7vR0xyGHRvnzLuXO25Q/b1P+vE358y7lztuUP29T/tqHJyovIiIiIiIiIiKNqaghIiIiIiIiIp6kokZmmJ/uAOSwKH/epdx5m/Lnbcqftyl/3qXceZvy523KXzvQmBoiIiIiIiIi4kk6U0NEREREREREPElFDRERERERERHxJBU1UsjMxpjZRjMrN7PbE6w3M/tteP1aMxuSjjilqSRyd6KZrTCzGjO7NR0xSvOSyN+V4c/cWjN7z8xOTkecklgS+fteOHdrzGyVmZ2VjjglsYPlL2a7M8yswczGpTI+aV4Sn72RZrY7/NlbY2a/TEecklgyn71wDteY2XozeyvVMUrzkvj8TYv57K0L//3smo5Ypakk8ldkZq+Y2cfhz9816Yizo9CYGiliZlnAp8B3gc+BD4DLnXMbYrb5B+AnwD8Aw4CHnHPD0hCuxEgyd6XAccAlwC7n3Kx0xCpNJZm/4cAnzrldZnYBMF2fvcyQZP4KgT3OOWdmg4FnnXMnpiVgiZNM/mK2ex3YDyxwzj2X6lglXpKfvZHArc65i9ISpDQryfx1Ad4DxjjnNptZqXNuW1oCljjJ/u2M2X4sMNU5953URSnNSfLz93OgyDl3m5mVABuBns652nTE7HU6UyN1hgLlzrnPwm/W3wPfa7TN94AnXMj7QBczOyrVgUoTB82dc26bc+4DoC4dAUqLksnfe865XeHF94FeKY5RmpdM/qrdgQp9AaBqfeZI5t8+CBX0nwf0gypzJJs7yUzJ5O8K4AXn3GYIfZdJcYzSvNZ+/i4HnklJZJKMZPLngE5mZkAhsBOoT22YHYeKGqlTBmyJWf483NbabST1lBdva23+rgOWtmtE0hpJ5c/MLjWz/wH+AFybotjk4A6aPzMrAy4F5qUwLjm4ZP92fjt8+vRSMxuYmtAkCcnkrz9QbGb/ZWarzWx8yqKTg0n6u4uZ5QNjCBWGJTMkk7/fAScBW4H/BiY754KpCa/j8ac7gCOIJWhr/L+JyWwjqae8eFvS+TOzUYSKGhqTIXMklT/n3BJgiZmdDcwAzmvvwCQpyeTvN8BtzrmG0H9YSYZIJncfAsc556rDl9C+CPRr98gkGcnkzw+cBpwL5AErzOx959yn7R2cHFRrvnuOBd51zu1sx3ikdZLJ3/nAGuA7QF/gdTNb7pz7pr2D64h0pkbqfA4cE7Pci1BlrrXbSOopL96WVP7CYzE8CnzPOfd1imKTg2vV58859zbQ18y6t3dgkpRk8nc68HszqwTGAXPN7JLUhCctOGjunHPfOOeqw4//CGTrs5cxkv3e+apzbo9zbgfwNqCBsjNDa/7t+xG69CTTJJO/awhd/uWcc+VABaDxwA6Rihqp8wHQz8z6mFmA0B+glxtt8zIwPnwXlG8Bu51zX6Q6UGkimdxJ5jpo/szsWOAF4Cr9D1XGSSZ/x4evScVCd40KACpMZYaD5s8518c519s51xt4DrjZOfdi6kOVRpL57PWM+ewNJfS9Up+9zJDMd5eXgBFm5g9fwjAM+CTFcUpiSX33NLMi4BxCuZTMkUz+NhM6Swoz6wGcAHyW0ig7EF1+kiLOuXozmwQsA7IIje6+3sx+HF4/D/gjoTuflAN7CVXwJM2SyZ2Z9QRWAZ2BoJlNAQboFLL0S/Kz90ugG6H/IQaod86dnq6Y5YAk8/d9QgXhOmAfcFnMwKGSRknmTzJQkrkbB9xkZvWEPns/0mcvMySTP+fcJ2b2KrAWCAKPOufWpS9qiWjF385Lgdecc3vSFKokkGT+ZgALzey/CV2uclv4jCk5BLqlq4iIiIiIiIh4ki4/ERERERERERFPUlFDRERERERERDxJRQ0RERERERER8SQVNURERERERETEk1TUEBERERERERFPUlE6OcrPAAAD6UlEQVRDRETkCGNmLomp0sx6hx9PSHfMEWZWZmZ7zCzp2y6b2VQzW2tm+t4jIiLSweiWriIiIkcYM/tWo6YlwMfA9Ji2GmADcCqwyTm3PTXRtczMFgClzrmLWrFPHlAB3OGce7zdghMREZGUU1FDRETkCGdmlcA7zrl/SncsLTGzHsAW4FLn3B9aue9M4ELn3MB2CU5ERETSQqdhioiISEKJLj8xs4Vm9rmZnW5m75nZPjPbaGYXhtf/NHzpyjdm9pKZlTTq029md5jZ/5hZjZltNbMHzCw3iZAmAP8LLGvU5/lm9q6Z7Taz6nA8v2y07++BAWY2/BBeChEREclQKmqIiIhIa3UGngAeBS4FtgHPm9kDwCjg/wBTwo/nNNr3SeBO4GngQuBe4DrgqSSOOwZY4ZyrjzSY2d8BLwOVwGXAxcCDQEGjfdcA34T7EBERkQ7Cn+4ARERExHM6AT92zr0NYGZbCY3JcREwwDnXEG4fBPzEzLKccw1mNoJQ4eFq59wT4b7eMLOdwJNmdopzbk2iA5qZAcOA2Y1WDQECwE3OuW/CbX9qvL9zLmhma4HG44mIiIiIh+lMDREREWmtPZGCRtj/hOdvRAoaMe1+4Kjw8higltBZHf7IBLwWXn92C8fsAuQBjQcsXQPUAb83s3FmVtpCH9uBo1tYLyIiIh6jooaIiIi01t9iF5xzteGHuxptF2mPjJdRSuisimpChYjItC28vlsLx4z0UdPo2OXA+YS+0ywCvjSzP5vZOQn62EeoMCIiIiIdhC4/ERERkVT5GtgPjGhm/daD7AtQ3HiFc+5N4E0zywHOBO4G/mBmvZ1zO2I27QrsaLy/iIiIeJeKGiIiIpIqrwK3AUXOuf/Xmh2dc7VmVgH8XQvb1AB/MrNC4CWgD/FFjD7AylZHLSIiIhlLRQ0RERFJCefcf5nZM8BzZvYgoQJDEOgN/ANwm3Pu0xa6eBsYGttgZj8mNBbHH4EtQHfgDkJnfayL2a4L0B+Y1VbPR0RERNJPRQ0RERFJpX8CfgJcC/yC0BgZlcAy4KuD7LsYGB++rKQy3PYxcAGhW8OWAjuBd4ArnXP7Yva9kNAYH0va5FmIiIhIRjDnXLpjEBERETkoM/MBfwEed87d08p9lwI7nHNXtUtwIiIikhYqaoiIiIhnmNmVwINAH+fc3iT3OQV4HxgUvluKiIiIdBC6/ERERES85GmgjNA4HBuS3KcncI0KGiIiIh2PztQQEREREREREU/ypTsAEREREREREZFDoaKGiIiIiIiIiHiSihoiIiIiIiIi4kkqaoiIiIiIiIiIJ6moISIiIiIiIiKe9P8BB+u5SDTloV0AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "timReqArrayPrechargeTime_s = np.arange(0.0, timReqPrechargeDuration_s + 0.5, 0.001)\n", + "curReqArrayPrechargeTime_s = np.arange(0.0, curReqPrechargeDuration_s + 0.5, 0.001)\n", + "resReqArrayPrechargeTime_s = np.arange(0.0, resReqPrechargeDuration_s + 0.5, 0.001)\n", + "\n", + "# Arrays for precharging with timing requirement\n", + "timReqArrayCurrent_A = [(maximumBatteryVoltage_V/timReqPrechargeResistance_ohm) * math.exp(-(1/timReqTau_s) * time_step_s) for time_step_s in timReqArrayPrechargeTime_s]\n", + "timReqArrayVoltage_V = [maximumBatteryVoltage_V * (1 - math.exp(-(1/timReqTau_s)*time_step_s)) for time_step_s in timReqArrayPrechargeTime_s]\n", + "\n", + "# Arrays for precharging with current requirement\n", + "curReqArrayCurrent_A = [(maximumBatteryVoltage_V/resReqPrechargeResistance_ohm) * math.exp(-(1/curReqTau_s) * time_step_s) for time_step_s in curReqArrayPrechargeTime_s]\n", + "curReqArrayVoltage_V = [maximumBatteryVoltage_V * (1 - math.exp(-(1/curReqTau_s)*time_step_s)) for time_step_s in curReqArrayPrechargeTime_s]\n", + "\n", + "# Arrays for precharging with resistance requirement\n", + "resReqArrayCurrent_A = [(maximumBatteryVoltage_V/resReqPrechargeResistance_ohm) * math.exp(-(1/resReqTau_s) * time_step_s) for time_step_s in resReqArrayPrechargeTime_s]\n", + "resReqArrayVoltage_V = [maximumBatteryVoltage_V * (1 - math.exp(-(1/resReqTau_s)*time_step_s)) for time_step_s in resReqArrayPrechargeTime_s]\n", + "\n", + "# plot data\n", + "p = []\n", + "fig, ax1 = plt.subplots(figsize=(17.6, 12.0))\n", + "p.extend(\n", + " ax1.plot(\n", + " timReqArrayPrechargeTime_s,\n", + " timReqArrayVoltage_V,\n", + " label=\"Voltage (timReq)\",\n", + " linewidth=1.5,\n", + " )\n", + ")\n", + "p.extend(\n", + " ax1.plot(\n", + " curReqArrayPrechargeTime_s,\n", + " curReqArrayVoltage_V,\n", + " label=\"Voltage (curReq)\",\n", + " linewidth=1.5,\n", + " color=\"cyan\"\n", + " )\n", + ")\n", + "p.extend(\n", + " ax1.plot(\n", + " resReqArrayPrechargeTime_s,\n", + " resReqArrayVoltage_V,\n", + " label=\"Voltage (resReq)\",\n", + " linewidth=1.5,\n", + " color=\"orange\"\n", + " )\n", + ")\n", + "\n", + "\n", + "# add horizontal line at 95% system voltage -> at this voltage level we would close second main contactor\n", + "ax1.axhline(y=0.95*maximumBatteryVoltage_V, ls='--', lw=1)\n", + "\n", + "ax2=ax1.twinx()\n", + "\n", + "p.extend(\n", + " ax2.plot(\n", + " timReqArrayPrechargeTime_s,\n", + " timReqArrayCurrent_A,\n", + " label=\"Current (timReq)\",\n", + " linewidth=1.5,\n", + " color=\"red\",\n", + " )\n", + ")\n", + "p.extend(\n", + " ax2.plot(\n", + " curReqArrayPrechargeTime_s,\n", + " curReqArrayCurrent_A,\n", + " label=\"Current (curReq)\",\n", + " linewidth=1.5,\n", + " color=\"black\",\n", + " )\n", + ")\n", + "p.extend(\n", + " ax2.plot(\n", + " resReqArrayPrechargeTime_s,\n", + " resReqArrayCurrent_A,\n", + " label=\"Current (resReq)\",\n", + " linewidth=1.5,\n", + " color=\"pink\",\n", + " )\n", + ")\n", + "\n", + "\n", + "ax1.set_ylabel(\"System voltage in (V)\", fontsize=16)\n", + "ax2.set_ylabel(\"Precharge current (A)\", fontsize=16)\n", + "ax1.set_xlabel(\"Time (s)\", fontsize=16)\n", + "\n", + "ax1.grid(axis=\"x\", color=\"black\", linestyle=\"dashed\", linewidth=0.6, which=\"major\")\n", + "ax1.grid(axis=\"y\", color=\"black\", linestyle=\"dashed\", linewidth=0.6, which=\"major\")\n", + "\n", + "labs = [l.get_label() for l in p]\n", + "ax1.legend(\n", + " p,\n", + " labs,\n", + " loc=\"lower right\",\n", + " fancybox=True,\n", + " shadow=True,\n", + " ncol=5,\n", + " prop={\"size\": 14},\n", + ")\n", + "\n", + "ax1.set_title(\"Voltage and current during precharging\", fontsize=28)\n", + "plt.tick_params(axis=\"both\", which=\"major\", labelsize=\"16\")\n", + "plt.show()\n", + " \n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "sunrise-davis", + "metadata": {}, + "source": [ + "Now we can calculate the losses in the precharge resistor as follows:\n", + "\n", + "$P_{Precharge}(t) = \\frac{U_{Precharge}^2}{R_{Precharge}} = \\frac{(U_{Battery} - U_{System}(t))^2}{R_{Precharge}}$\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "rural-offering", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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L2xmfwcsJC7n+HG5MXtbyrH+l99h0M8nwaVLYMhBaQ9HuqitrY2mpqa0hyHdpH6+qZ9faueb+vmmfr6pn1/e2pVaytEvhYH0B74L/GsI4ZkSmzUCLxW5fFXyuQFYn2y3usx2jXmf14TdZ2EKtysc67nAuQDNzc2ce+65jBo1irFjx3L77bczZMgQLr/8cq666ioAbrzxRiZNmsSWLVu49NJLmT17Ni+++CInn3wyy5YtY8GCBRx99NEccsgh3HvvvRx88MGccsopTJs2jb59+3LjjTdyySWXAHD11Vdz8803s2rVKs455xwWLlzIk/WaCNQAACAASURBVE8+yfHHHw/AI488wpFHHsmYMWO48847aWxs5OKLL2bKlCkAjBn8OmcPhqsnXcZpl07l/vvv5+WXX+bUU09l6dKlPP7444wdO5YDDjiABx54gBEjRjB+/HimT5/OgAEDuO6665g4cSIA1157LdOmTWPt2rWcf/75LFiwgCVLlnDiiSfS3t7O3LlzGT16NKNHj+buu++mubmZCy64gGuuiatpvvWtbzFhwgQArrzySmbOnMlrr73G6aefznPPPcfChQsZN24cTU1NPPjgg4wcOZITTjiBW265hbq6Oq6++uqduyhdd911TJ06lfXr13PhhRcyb948nn76acaPH8+6deuYN28eLS0tjBo1ihkzZjB8+HDOPvtspk6duttYJk+ezF133cXrr7/OmWeeyZIlS2htbeXYY49l8ODBzJ49myOOOIJjjz2WW2+9lUGDBjF58mQmTZoEwA033MCUKVPYtGkTF110EQ8//DDPP/88J510Em1tbcyfP58xY8Zw+OGHM2vWLA488EDOOOMMrr/++t3G8tWvfpXbbruNFStWcNZZZzF58mQOO+wwjjvuOGpqapgzZ46b595NN93ExIkT2b59O5dffvk++dw7//zz+dSnPuXyubd48WIWL168Tz/3nnjiCebNm+fyuef5373eeO798Ic/ZPr06W6fe57/3euN594zzzzDLbfc4vK55/3fvd547tXW1rJ582aXzz3P/+711nPvK1/5CiNHjnT53PP8715vPPd++tOfUl9f7+a5V8pe32PCzK4CzgJGhRA2JZcV7jHxHNAaQji14LbnAHcAB4cQXjGzR4FBIYT3FWz3D8Bc4JgQwgIzu5O4V8QBBdsdDjwLfD6EMLPc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gE/m3e4TyW3uz9tuG3Af8BEzy+3P8hFgADCr4OfOAt5lZiN66feoKldeeWXZ6xtrG5ODXyanl9mgU4ZWk876SXVTP9/Uzy+18039fFM/39TPr6y0S2Viwsz6mtkAMzsc+C7wOnFCAeLSjqeK3GwJcLCZDcrb7sUQwsYi2w0ARuZt1w48X2Q7iMe7yJyZM2eWvb6prqljKQfozBxVprN+Ut3Uzzf180vtfFM/39TPN/XzKyvt9upSjjwLgaOSr58nLttYnnzfCLxU5Darks8NwPpku9VltmvM+7wm7H6Uz8LtdmNm5wLnAjQ3N3PuuecyatQoxo4dy+23386QIUO4/PLLueqqqwC48cYbmTRpElu2bOHSSy9l9uzZvPjii5x88sksW7aMBQsWcPTRR3PIIYdw7733cvDBB3PKKacwbdo0+vbty4033sgll1wCwNVXX83NN9/MhEnx3AAAIABJREFUqlWrOOecc1i4cCFPPvkkxx9/PACPPPIIRx55JGPGjOHOO++ksbGRiy++mClTpgCwbds2LrjgArZv387ll1/O/fffz8svv8ypp57K0qVLaX2tlRUHreBXi//EB4D/fuAeDjvpYKZPn86AAQO47rrrmDhxIgDXXnst06ZNY+3atZx//vksWLCAJUuWcOKJJ9Le3s7cuXMZPXo0o0eP5u6776a5uZkLLrhg56lrvvWtb+1c+3TllVcyc+ZMXnvtNU4//XSee+45Fi5cyLhx42hqauLBBx9k5MiRnHDCCdxyyy3U1dVx9dVXc8UVVwBw3XXXMXXqVNavX8+FF17IvHnzePrppxk/fjzr1q1j3rx5tLS0MGrUKGbMmMHw4cM5++yzmTp16m5jmTx5MnfddRevv/46Z555JkuWLKG1tZVjjz2WwYMHM3v2bI444giOPfZYbr31VgYNGsTkyZOZNGkSADfccANTpkxh06ZNXHTRRTz88MM8//zznHTSSbS1tTF//nzGjBnD4YcfzqxZszjwwAM544wzuP7663cby1e/+lVuu+02VqxYwVlnncWjjz7Ka6+9xnHHHUdNTQ1z5sxx89y76aabmDhxYsnn3uOPP87YsWM54IADeOCBBxgxYgTjx4/P1HPvvvvuY/v27S6fe4sXL2bx4sX79HNvwYIFXHDBBS6fe57/3euN5959993H+9//frfPPc//7vXGc+/JJ59k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mkSPHj2YNm0a+/fvJy8vj127djFy5Ehyc3O5+OKLWbBgAWeeeSapqakUFhZy9913M3/+fLp37w5Au3btWLp0KdOmTStzkvirX/2KCy+8sNpxb9q0iRdffJGFCxdy9tlnA/Doo49y7LHH8vjjjzNs2DDy8/M5/fTToyespa90fvDBB6Snp/OTn/yEpk2b0rZtW0499dQDbu/zzz9n165dtG7dOjovIyODxo0bR68GHswNN9zAD3/4QyDosvXjH/+YZ599lp49ewJw7bXXVhhorbCwkIyMjOjJJwRXm0488UQApkyZwqBBg8p0AfvjH//I6aefzo4dO2jSpAkzZsxg5syZ9OvXD4BZs2ZFr7KVdvTRR7Nt2zb2799PSopO8Q5GZafmZQfg9ttv57rrruOGG26Izvve975X7f0oMWjQIIYNGxZ9/P777wNw9tln06BBA/bu3UtxcTHt2rXjoosuAuCJJ57A3Zk1a1a0MuNPf/oTWVlZzJ07l4suuoh7772XIUOG8Mtf/hKAcePGkZuby+bNm8ts/+ijj45utzYrJsJK5Sa2cgOQlpbGzJkzo90FZ86cedDPc35+PhdccEF0m+3atauw3sGDBzN06FCKior45ptvOPLII6NlKzc3l1WrVrFz504aN24MBGX4pZde4tFHH+Wmm27i97//Pb169WLcuHEAHH/88SxbtowZM2aU2U6TJk1o3rx5tKzGi7616qgPPvgg2SFIDJS/cFP+wivWlgu1Zd68eWRkZLB//36+/vprBgwYwP3338+WLVv4+uuvOeuss6KvPeyww+jWrRvr1gV3xu7evTv79u1j2bJlrFmzhu7du9O7d2+GDx8OwIIFC6I/vtetW0dRURE5OTllrmR+/fXXFZpDd+nS5ZD2Yf369TRo0IBu3bpF5zVv3pxTTjklGuuIESO48MILWblyJX369OHHP/5xtK9unz59aNu2Le3ataNfv3707duX888/n6ZNm1a6vb179wLBCWFNffe7343+36pVKwBOOeWUMvMKCwvZs2cPTZo0AYITuFWrVrF//34WLVrE1KlTyzQ7XrFiBZs3b+bJJ5+Mziu5vdqWLVto0qQJX331VZn3KSMjo8x2SzRu3Bh3p6ioiIyMjBrvZ43E2HKhtqjsxNz5BkEAABjISURBVKfs7Nixg23btsXlaumB9n/OnDmcdNJJbNy4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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Minimum and maximum precharge losses\n", + "timReqArrayPower_W = [((maximumBatteryVoltage_V - systemVoltage_V)**2)/timReqPrechargeResistance_ohm for systemVoltage_V in timReqArrayVoltage_V]\n", + "curReqArrayPower_W = [((maximumBatteryVoltage_V - systemVoltage_V)**2)/curReqPrechargeResistance_ohm for systemVoltage_V in curReqArrayVoltage_V]\n", + "resReqArrayPower_W = [((maximumBatteryVoltage_V - systemVoltage_V)**2)/resReqPrechargeResistance_ohm for systemVoltage_V in resReqArrayVoltage_V]\n", + "\n", + "\n", + "# plot data\n", + "p = []\n", + "fig, ax1 = plt.subplots(figsize=(17.6, 12.0))\n", + "p.extend(\n", + " ax1.plot(\n", + " timReqArrayPrechargeTime_s,\n", + " timReqArrayPower_W,\n", + " label=\"Power loss (timReq)\",\n", + " linewidth=1.5,\n", + " )\n", + ")\n", + "p.extend(\n", + " ax1.plot(\n", + " curReqArrayPrechargeTime_s,\n", + " curReqArrayPower_W,\n", + " label=\"Power loss (curReq)\",\n", + " linewidth=1.5,\n", + " )\n", + ")\n", + "p.extend(\n", + " ax1.plot(\n", + " resReqArrayPrechargeTime_s,\n", + " resReqArrayPower_W,\n", + " label=\"Power loss (resReq)\",\n", + " linewidth=1.5,\n", + " )\n", + ")\n", + "\n", + "ax1.set_ylabel(\"Precharge losses (W)\", fontsize=16)\n", + "ax1.set_xlabel(\"Time (s)\", fontsize=16)\n", + "\n", + "ax1.grid(axis=\"x\", color=\"black\", linestyle=\"dashed\", linewidth=0.6, which=\"major\")\n", + "ax1.grid(axis=\"y\", color=\"black\", linestyle=\"dashed\", linewidth=0.6, which=\"major\")\n", + "\n", + "labs = [l.get_label() for l in p]\n", + "ax1.legend(\n", + " p,\n", + " labs,\n", + " loc=\"lower right\",\n", + " fancybox=True,\n", + " shadow=True,\n", + " ncol=5,\n", + " prop={\"size\": 14},\n", + ")\n", + "\n", + "ax1.set_title(\"Power loss during precharging\", fontsize=28)\n", + "plt.tick_params(axis=\"both\", which=\"major\", labelsize=\"16\")\n", + "plt.show()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "careful-effects", + "metadata": {}, + "source": [ + "Integrating these losses over the course of precharging gives us the amount of energy that the precharge resistor needs to sustain.\n", + "\n", + "$E_{Precharge}(t) = P_{Precharge}(t) t$\n", + "\n", + "The total energy loss is calculated as\n", + "\n", + "$E_{Total} = \\int_0^\\infty P_{Precharge}(t)\\mathrm{d}t$\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "detailed-university", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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V1wBwK233srf//53tm7dygUXXMDMmTOZP38+xx7rXUpxypQp7L///owcOZInn3ySDh06cPnll3Pzzd4VEv7f//t/XHzxxZSXl3Pttdfy+uuvs2rVKs444wxWrlzJV199xejRo+nWrRtvvPEGffv25aSTTuKBBx4gJSWFO++8k6uvvhqAO+64g3vvvZfc3FwuuugiPv/8cxYuXMjxxx9PcXExH3/8McOHD2f48OE888wzZGVlcfHFF3PbbbcB8I9//INLL70UgOuuu44XX3yRNWvWcOaZZ7JkyRJmzpzJmDFj6NixI2+//Tb9+/fnuOOO46GHHiItLY1bb72VP/3pTwDceeedTJo0ifz8fC655BKmTp3KokWLOOmkk8jLy2Pq1KlkZ2czePBgnn/+ebp27cp5553HpEmTatRyww038PTTT7N+/Xp+//vfs3DhQnJychg7diyZmZlMnjyZQYMGMXbsWB555BEyMjK44YYbuO0vV3Nj1sd0bN+Fv3ydydb/XMhll13Ghx9+yNKlSznllFN4cuOTLAst49TQqaycu5JJL02iR48enHXWWdx11101arnpppt47LHH2LRpExMmTKBbt25MnDiRcePGkZqaynvvvdckn71J9/2deZkj2ZbUgf4F/yP3k/9jy2GN++w9+OCDXH311Xv0Z2/z5s3cdNNNMf/sXX/99QDcc8893HzzzRQWFlb57J166qls2bKFadOmMXLkSAYMGMBLL720W5+9OXPmMGfOnCb/7DXFcS8Wn73NmzczceJEtZ+9pjruafnsbd68mU8//VTlZ0/7cS8Wn71evXoxb948lZ89zce9WH32brnlFiZOnKjys6f5uBeLz97pp5/Oww8/rPazp/m4F4vP3s9//nMmTpyo5rNXK+dcYDfgfLwGgz61TE8AXgaKgLERpr8O/BDh+fH+egfXVcOIESOcJhdccEHQJcSnUMi5N85x7pb2zq2cEXGWZ7971g15boh7bsFzDd5Mc+S3cvNOd/g9/3EDb/jQvT9vbZNvb09i+59elp1ulp9ulp9ulp9elp1u2vIDclyE79st/QyHx4FfA6c556ZGmL4QOFlEWruq4zjsB5QAS5uhRhMP5r0KC9+BX9wIex1SY3LO+hwenP0gR/U+irP3OzuAAutn0fodnPX0N5SWh3jlgkMY0bt90CUZY4wxxhhj9lDiNUYE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72ucc38AJnvvv3DQ+y4ntghxgvd+1ZFmyM3N9Xl5eQn590mG6upq0tPTwx4jMX53CdTsgH9eCECzb+a858/jnJxz+MnUnwRyyuZmz7Sfv8eAvj158aazAjnHkUSqXxekfnapnW3qZ5v62aZ+dqmdbdb6OeeWeO9zD369sz6lYgCxPR4OVtbys3+c7xuQ4LlCN2vWrLBHSIzGeij4EEbvu51iTdkayuvLOXPomYGd9oMNpWzauYurzhhx9DcHIDL9uij1s0vtbFM/29TPNvWzS+1si0q/5N7AHj8HHOrSi4MfJxDv+w78pXMzgZkA2dnZzJw5k4kTJzJ16lR+9atfkZGRwezZs/nhD38IwIMPPshdd91FQ0MDt99+O/PmzWPTpk1cfvnlFBcXs2DBAs466yxGjhzJc889x4gRI7jiiiuYO3cuKSkpPPjgg9x2220A3HPPPTzyyCOUlZVxww03sGjRIlasWMFFF10EwKuvvsqkSZOYMmUKTz75JAMGDOD73/8+c+bMAaCxsZGbbrqJpqYmZs+ezfPPP09BQQFXXnkl+fn5fPDBB0ydOpUhQ4bwwgsvMHr0aGbMmMFDDz1Ez549uf/++1u/vD/+8Y+ZO3culZWV3HjjjSxYsIBVq1Yxffp06uvrmT9/PpMnT2by5Mn85je/ITs7m5tuuol7741tj/GLX/yCW265BYA777yTZ555hqKiIq666irWrVvHokWLOO+888jKyuLFF19k3LhxXHzxxTz66KOckF7Jrem7eeyVT1j+0kzuv/9+7n7ybhgC/cr78fOf/5w1a9YwY8YMqqureeutt8jNzWXixIk8/fTTDB48mOuvv5777rvvc7PcfffdPPXUU2zbto1rrrmGVatWkZeXx7Rp03huSxo9mutZ9/YfWd7tfB577DHS0tK4++67ueuuuwB44IEHmDNnDnV1ddx666288sorrF+/nssuu4zS0lLeffddpkyZwvjx43n22WfJycnh6quv5qc//ennZvnRj37EE088QUlJCddddx2rV69m5syZXHDBBaSmpvLyyy+b+e49/PDDzJo1y/x3r3fv3txzzz3ccUdsO5j777+f++67j5qaGm6++Wbeeuutw373FixYwI9+9KN2fffS09OZN28eEyZMYNq0aUn/7i1dupSlS5d22e/eggULmDlzptnvXkf+3ovCd2/BggW8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l2Jm/Pzzz0VUVWD27t1L5cqV+e9//xvuUiQMCtKmvaZFixa88cYb4S5DwqS4temuXbvy1FOhucCj1zscpgE7gLfMrLOZdcJ31YpdwAvhLCxUnn766XCXIAFQft6m/LxL2RU/iYmJmFmO6Yorrgh3aQH59ttveeutt/xOwlWzZk0mTpzod78rr7yS5ORkzjvvvIAe7+TtGBERwUUXXcSAAQP49dfgHplapUoVevXqpdFGeShJbTpUZs2a5bftqlatSseOHUlKSgr6Y/3jH/9g2LBhpKenB33dxYXadGAyO5Yzp/POO4+rr76aFStWBP2xRo0axdixY0lJSQn6uj3d4eCcOwxcDWwB5gLzge3A1c65Q+GsLVQyz/Iv3qT8vE35eZeyK56uueYakpOT/aZFixaF9DFPnDhBKE+4PWXKFLp06cJZZ52V5/0iIyOpVq1aUC5jmrkdd+zYwUsvvcQ777zD3/72t4DXm92dd97J/Pnz2b9/f9DXXVyU5DYdqOPHjwMQHR1NcnIye/bs4b333uPw4cN06NCBY8eOBfXxbrjhBg4ePMj7778f1PUWNyW1TQezvSUlJZGcnMzSpUupXLkyHTp0YO/evUFbP8Bll11G7dq1mTdvXlDXCx7vcABwzv3onOvinDvLOVfBOXejc25HuOsKld9//z3cJUgAlJ+3KT/vUnbFU1RUFNWqVfObzj33j3NJmxkvvvgi3bp1o3z58rl+mNq9eze33norFStWpGLFinTo0IHvv/8+6/bRo0fToEEDZs2axcUXX0xUVBSHDx9my5YttGnThrJly3LppZeyaNEiYmJimDVrFgBXX30199xzj99jHThwgOjo6FMOw/7999957bXX6NSpU9a8tm3bsnPnTh588MGsvVyQ85CKWbNmERMTw/vvv098fDzR0dF06tSJlJQUXn/9derUqcPZZ59Nz549SUtLy3U7XnDBBbRv357u3buzePFiv/vMnDmTevXqUbZsWS655BImT57st2d369attG3bNmt7vPvuu37bA6BBgwZUr15dw9DzUBLaNPi+jP3P//wPNWrUICoqitq1a/Pss88CuR8utGPHDsyMzCvLZd5n0aJFtGjRgsjISD788MOsbVStWjXOP/98mjdvzn333cfOnTvZvHlz1vpWrlxJmzZtiI6OJjY2lgEDBnDgwIGs21NTU0lMTCQmJoaqVavy+OOP85e//IXExMSs+5QuXZobbriBV155JfcwBSg5bbpmzZqMHj2aPn36cM4553D77bcD+be1ZcuWccUVVxATE8PZZ59Ny5Yt2bBhg9+6q1SpQrVq1bjssst46KGHSElJ4csvv8y6fePGjXTo0IEKFSpQpUoVbrvtNn766Se/mh944IGs7Td48GAGDBhA27Zt/R6nU6dOIWnP+V42Us4sDz74YLhLkAAoP29Tft6l7ArnkXeS2LjnQP53DKJ61c9iVMfczgMdmDFjxvDEE08wbtw4pk+fTp8+fWjdujU1atQgNTWVhIQErrzySj777DMiIyOZOHEi11xzDd999x3R0dEAbN++nZdffpl///vfREZGEhkZyU033US1atVYtWoVaWlpDB48mKNHj2Y9bv/+/Rk4cCCTJk0iKioKgFdeeYWYmBg6duyYa63ffPMNKSkpNG/+x1XF3njjDRo1akSfPn0YMGBAns/16NGjTJo0ifnz53Ps2DG6dOlC165dKVu2LAsXLuSXX37h5ptv5rnnnjvlqJ8ffviBDz74gDJlymTNmzZtGg8//DBTpkyhWbNmbNiwgf79+1OmTBnuuece0tPTuemmm6hYsSJffPEFqampDBo0yG97ZGrRogWfffYZ/fr1y/O5BN37w+Gnb4v2MatdBn8O/uV4vd6mAXr37s3y5ct55plnaNKkCTt37mTXrl2F3hbDhg1j0qRJxMXFUaFCBd577z2/23/77TdefvllgKw2/e2339K+fXseeeQRXnrpJfbv38/gwYPp06cPr7/+OgAPPPAAH330EQsXLiQ2NpZHHnmEZcuWcfPNN/utv0WLFjz22GOFrjtQT65+kk37NxXpY8afG8+wFsNCsu7i0KYBnnrqKR566CHWrFmDcy7ftnbixAk6d+5M3759mT9/PsePH+err76idOnSuT52amoqM2fOBP5oz8nJyVx11VX07duXiRMncvz4cUaOHEmnTp1YtWoVpUqVYtKkSUybNo1p06bRsGFDpk6dyvz582natKnf+lu0aMHYsWNJS0ujXLlyhUzx1Dw/wqGkefXVV8NdggRA+Xmb8vMuZVc8ffDBB8TExPhNw4b5fyDu2bMnd9xxB3FxcTz66KNERESwfPlyABYsWIBzjpkzZ9KwYUPi4+N54YUXOHToEO+++27WOo4dO8bcuXNp2rQpDRo0YMmSJWzevJk5c+bQuHFjWrVqxeTJkzlx4kTWMjfffDOlSpXizTffzJo3Y8YMevXq5fdl/mQ7d+7M2jub6dxzz6V06dJUqFAha+/gqZw4cYKpU6fSrFkzWrVqRY8ePfj000+znl9CQgKdO3dmyZIluW7HcuXKcfHFF7Nx40a/7fjoo48yfvx4unbtSq1atejYsSPDhw/nueeeA+Djjz9m48aNzJs3jyZNmvCnP/2Jp59+2m97ZKpevTo7duw45XMo6UpCm/7+++9ZsGABL730El26dKF27dokJCTQq1evQm+v0aNH0759e2rXrk3lypUBOHz4MDExMZQvX56KFSuyYMECOnXqRHx8PAATJkyge/fuDBkyhDp16tCyZUuef/55Fi5cyN69ezl06BDTp09n/PjxXHfddTRo0ICZM2dSqlTOr03Vq1dn9+7dubZ18SkJbTpTmzZtGDp0KHFxcdSpUyfftnbgwAF+++03OnbsyMUXX0x8fDw9evSgbt26fuutWbNm1rabPHkyzZs3p127dgA8//zzNGrUiCeffJK6devSsGFD5syZw//+7/9mjQh6+umnGTp0KLfccgvx8fE888wzudZfvXp1jh8/zp49e/LMtLA0wsFjfvzxx3CXIAFQft6m/LxL2RVOKEYahMJVV13Fiy++6DfvnHPO8fu7YcOGWb9HRERQuXLlrGNf165dy/bt26lQoYLfMqmpqWzbti3r7wsuuICqVatm/b1p0yaqV69ObGxs1rzLL7/c7wtJVFQUPXv2ZMaMGdx6661s3LiR1atXZ+2dyk1aWhplypTJ9YtNQURFRXHppZdm/V21alWqVatGpUqV/OZt3Oh/5fDM7ZiWlsa0adPYtm0b9957LwD79u1j165d/PWvf/UbYXHyMdLfffcdsbGxXHTRRVm3t2zZMtfnUa5cuRyHdBSJEIw0CIWS0KbXrVtHqVKlSEhIyHNbFERue5mjo6NZv349J06cYNmyZUycOJEXXvjjXPJr165l69atfh3RmW1527ZtREdHc+zYMVq1apV1e0xMDJdddlmOxypXrhzOOY4cOUJMTEzAz6egQjXSIBRKQpvOlL095tfWWrVqRWJiItdddx3t2rWjXbt2dOvWjQsvvNBvPUuWLOHss89m3bp1jBgxgtmzZ2d1iKxdu5Zly5bl2v62bdvGpZdeSnJysl97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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "timReqArrayEnergy_Ws = integrate.cumtrapz(timReqArrayPower_W, timReqArrayPrechargeTime_s, initial=0)\n", + "curReqArrayEnergy_Ws = integrate.cumtrapz(curReqArrayPower_W, curReqArrayPrechargeTime_s, initial=0)\n", + "resReqArrayEnergy_Ws = integrate.cumtrapz(resReqArrayPower_W, resReqArrayPrechargeTime_s, initial=0)\n", + "\n", + "# plot data\n", + "p = []\n", + "fig, ax1 = plt.subplots(figsize=(17.6, 12.0))\n", + "p.extend(\n", + " ax1.plot(\n", + " timReqArrayPrechargeTime_s,\n", + " timReqArrayEnergy_Ws,\n", + " label=\"Energy (timReq)\",\n", + " linewidth=1.5,\n", + " )\n", + ")\n", + "p.extend(\n", + " ax1.plot(\n", + " curReqArrayPrechargeTime_s,\n", + " curReqArrayEnergy_Ws,\n", + " label=\"Energy (curReq)\",\n", + " linewidth=1.5,\n", + " )\n", + ")\n", + "p.extend(\n", + " ax1.plot(\n", + " resReqArrayPrechargeTime_s,\n", + " resReqArrayEnergy_Ws,\n", + " label=\"Energy (resReq)\",\n", + " linewidth=1.5,\n", + " )\n", + ")\n", + "\n", + "ax1.set_ylabel(\"Loss energy (Ws)\", fontsize=16)\n", + "ax1.set_xlabel(\"Time (s)\", fontsize=16)\n", + "\n", + "ax1.grid(axis=\"x\", color=\"black\", linestyle=\"dashed\", linewidth=0.6, which=\"major\")\n", + "ax1.grid(axis=\"y\", color=\"black\", linestyle=\"dashed\", linewidth=0.6, which=\"major\")\n", + "\n", + "labs = [l.get_label() for l in p]\n", + "ax1.legend(\n", + " p,\n", + " labs,\n", + " loc=\"lower right\",\n", + " fancybox=True,\n", + " shadow=True,\n", + " ncol=5,\n", + " prop={\"size\": 14},\n", + ")\n", + "\n", + "ax1.set_title(\"Energy loss during precharging\", fontsize=28)\n", + "plt.tick_params(axis=\"both\", which=\"major\", labelsize=\"16\")\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "narrow-delaware", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tools/utils/README.md b/tools/utils/README.md index d382619c..cf18d4da 100644 --- a/tools/utils/README.md +++ b/tools/utils/README.md @@ -1,6 +1,6 @@ # Utils -This directory and its subdirectories contain batch and shellscript helper +This directory and its subdirectories contain batch and shell script helper scripts. The ``bash`` directory contains bash scripts while ``cmd`` scripts contains batch scripts. diff --git a/tools/utils/bash/dir_shall_not_exist.sh b/tools/utils/bash/dir_shall_not_exist.sh new file mode 100644 index 00000000..f3ea16b4 --- /dev/null +++ b/tools/utils/bash/dir_shall_not_exist.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +set -e + +if [ -d "$1" ]; then + # directory exists + exit 1 +else + # directory does not exist + exit 0 +fi diff --git a/tools/utils/bash/find_base_conda.sh b/tools/utils/bash/find_base_conda.sh index fb40329e..8ac4f8d4 100755 --- a/tools/utils/bash/find_base_conda.sh +++ b/tools/utils/bash/find_base_conda.sh @@ -48,7 +48,7 @@ function _win32_get_vars() { if [[ $USERPROFILE = *" "* ]]; then MINICONDA_DIRECTORIES=($SYSTEMDRIVE/miniconda3/ $ProgramData/miniconda3/) else - MINICONDA_DIRECTORIES=($USERPROFILE/miniconda3/ $LOCALAPPDATA/Continuum/miniconda3/ $SYSTEMDRIVE/miniconda3/ $ProgramData/miniconda3/) + MINICONDA_DIRECTORIES=($USERPROFILE/miniconda3/ $LOCALAPPDATA/miniconda3/ $LOCALAPPDATA/Continuum/miniconda3/ $SYSTEMDRIVE/miniconda3/ $ProgramData/miniconda3/) fi # Activate script path (relative to the environment directory) diff --git a/tools/utils/cmd/find_base_conda.bat b/tools/utils/cmd/find_base_conda.bat index b1292e10..9cff7edc 100644 --- a/tools/utils/cmd/find_base_conda.bat +++ b/tools/utils/cmd/find_base_conda.bat @@ -55,7 +55,7 @@ @IF NOT "%USERPROFILE%"=="%USERPROFILE: =%" @( @SET MINICONDA_DIRECTORIES=%SystemDrive%\miniconda3\ %ProgramData%\miniconda3\ ) ELSE @( - @SET MINICONDA_DIRECTORIES=%USERPROFILE%\miniconda3\ %LOCALAPPDATA%\Continuum\miniconda3\ %SystemDrive%\miniconda3\ %ProgramData%\miniconda3\ + @SET MINICONDA_DIRECTORIES=%USERPROFILE%\miniconda3\ %LOCALAPPDATA%\miniconda3\ %LOCALAPPDATA%\Continuum\miniconda3\ %SystemDrive%\miniconda3\ %ProgramData%\miniconda3\ ) @REM Activate script path (relative to the environment directory) diff --git a/tools/utils/generate_license_list.py b/tools/utils/generate_license_list.py index 0888a1d9..96f8e9f6 100644 --- a/tools/utils/generate_license_list.py +++ b/tools/utils/generate_license_list.py @@ -106,7 +106,7 @@ def __repr__(self): @staticmethod def date_get_today() -> str: - """returns the datestring for the output""" + """returns the date-string for the output""" today = date.today() return today.strftime("%Y-%m-%d") diff --git a/tools/utils/generate_missing_test_files.py b/tools/utils/generate_missing_test_files.py index 9979e55c..97597b33 100644 --- a/tools/utils/generate_missing_test_files.py +++ b/tools/utils/generate_missing_test_files.py @@ -128,7 +128,7 @@ def main(): out_txt[42] = f" * @file {missing_file.name}" out_txt[44] = f" * @date {today_iso} (date of creation)" out_txt[45] = f" * @updated {today_iso} (date of last update)" - out_txt[57] = f'TEST_FILE("{source_file}")' + out_txt[57] = f'TEST_SOURCE_FILE("{source_file}")' if not missing_file.parent.exists(): missing_file.parent.mkdir() missing_file.write_text("\n".join(out_txt) + "\n", encoding="utf-8") diff --git a/tools/utils/list_prefixes.py b/tools/utils/list_prefixes.py new file mode 100644 index 00000000..ae12e220 --- /dev/null +++ b/tools/utils/list_prefixes.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Template for Python scripts""" + +import argparse +import os +import re +import logging +from pathlib import Path + + +from git import Repo + + +def get_git_root(path: str = os.path.realpath(__file__)) -> Path: + """helper function to find the repository root + + Args: + path (string): path of test_f_guidelines + + Returns: + root (string): root path of the git repository + """ + repo = Repo(path, search_parent_directories=True) + root = Path(repo.git.rev_parse("--show-toplevel")) + return root + + +def main(): # pylint: disable=too-many-statements + """Update the version information in all relevant files.""" + parser = argparse.ArgumentParser() + parser.add_argument( + "-v", + "--verbosity", + dest="verbosity", + action="count", + default=0, + help="set verbosity level", + ) + args = parser.parse_args() + + if args.verbosity == 1: + logging.basicConfig(level=logging.INFO) + elif args.verbosity > 1: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.ERROR) + root = get_git_root() + prefix_re = re.compile(r"@prefix\s+(\S+)") + prefixes = [] + for i in root.rglob("**/*.[c|h]"): + i_posix = i.as_posix() + if any( + [ + ".git/" in i_posix, + "/axivion/" in i_posix, + "build/" in i_posix, + "/freertos/" in i_posix, + "/vendor/" in i_posix, + ] + ): + continue + for line in i.read_text(encoding="utf-8").splitlines(): + m = prefix_re.search(line) + if m: + prefix = m.group(1) + if prefix not in prefixes: + prefixes.extend([prefix, prefix.lower()]) + break + print("\n".join(sorted(prefixes, key=str.casefold))) + + +if __name__ == "__main__": + main() diff --git a/tools/utils/ruby-install.bat b/tools/utils/ruby-install.bat index 6e41528b..4e24412d 100644 --- a/tools/utils/ruby-install.bat +++ b/tools/utils/ruby-install.bat @@ -40,11 +40,11 @@ @TITLE Installing Ruby @ECHO Downloading Ruby -@SET RUBYINSTALLER="%USERPROFILE%\Downloads\rubyinstaller-devkit-2.7.2-1-x64.exe" -@SET RUBY_INSTALL_DIRECTORY=C:\Ruby\Ruby272-x64 -@curl.exe -fsSL https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-2.7.2-1/rubyinstaller-devkit-2.7.2-1-x64.exe -o "%USERPROFILE%\Downloads\rubyinstaller-devkit-2.7.2-1-x64.exe" +@SET RUBYINSTALLER="%USERPROFILE%\Downloads\rubyinstaller-3.1.3-1-x64.exe" +@SET RUBY_INSTALL_DIRECTORY=C:\Ruby\Ruby3.1.3-x64 +@curl.exe -fsSL https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-3.1.3-1/rubyinstaller-3.1.3-1-x64.exe -o "%USERPROFILE%\Downloads\rubyinstaller-3.1.3-1-x64.exe" @ECHO Done -@ECHO Installing Ruby 2.7.2-x64 +@ECHO Installing Ruby 3.1.3-x64 @%RUBYINSTALLER% /verysilent /dir="%RUBY_INSTALL_DIRECTORY%" /tasks="noassocfiles,nomodpath,noridkinstall" @ECHO Done @ECHO Installing dependencies diff --git a/tools/utils/verify_doc_source_links.py b/tools/utils/verify_doc_source_links.py new file mode 100644 index 00000000..d8e85a20 --- /dev/null +++ b/tools/utils/verify_doc_source_links.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# We kindly request you to use one or more of the following phrases to refer to +# foxBMS in your hardware, software, documentation or advertising materials: +# +# - "This product uses parts of foxBMS®" +# - "This product includes parts of foxBMS®" +# - "This product is derived from foxBMS®" + +"""Checks files references that are used in some documentation files.""" + +import argparse +import logging +import sys +import re +from pathlib import Path + +import git +from git.exc import InvalidGitRepositoryError + +SCRIPT_DIR = Path(__file__).parent.resolve() + + +def main(): + """This script does this and that""" + parser = argparse.ArgumentParser() + parser.add_argument( + "-v", + "--verbosity", + dest="verbosity", + action="count", + default=0, + help="set verbosity level", + ) + args = parser.parse_args() + + if args.verbosity == 1: + logging.basicConfig(level=logging.INFO) + elif args.verbosity > 1: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.ERROR) + + try: + repo = git.Repo(SCRIPT_DIR, search_parent_directories=True) + root = Path(repo.git.rev_parse("--show-toplevel")) + except InvalidGitRepositoryError: + sys.exit("Test can only be run in a git repository.") + + ls_files = repo.git.ls_files("docs/software/modules/*.rst").splitlines() + rst_files: list[Path] = [root / i for i in ls_files] + reg = re.compile( + # r"``((tests|src)\/.*)``\s+ \(`API\s+\<(.*)\>`__,\s+\`source\s\<(.*)`__\)" + r"``((tests|src)\/.*)``\s+ \(`API\s+\<(.*)\>`__,\s+\`source\s\<(.*)\>`__\)" + ) + err = 0 + for i in rst_files: + if not i.is_file(): + logging.warning(f"File '{i}' does not exists.") + continue + txt = i.read_text(encoding="utf-8") + found_references = [] + for line in txt.splitlines(): + m = reg.search(line) + if not m: + continue + found_references.append( + (Path(m.group(1)).name, Path(m.group(3)).name, Path(m.group(4)).name) + ) + for ref in found_references: + if ref[0].endswith(".c"): + api_end = "_8c.html" + tests_end = "_8c_source.html" + elif ref[0].endswith(".h"): + api_end = "_8h.html" + tests_end = "_8h_source.html" + expected_api_ref = ref[0].replace("_", "__")[:-2] + api_end + expected_tests_ref = ref[0].replace("_", "__")[:-2] + tests_end + logging.debug(ref) + if not ref[1] == expected_api_ref: + logging.error( + f"In file '{i}' for \n\t'{ref[0]}'\nexpected\n\t'" + f"{expected_api_ref}'\nbut found\n\t'{ref[1]}'.\n" + ) + err += 1 + if not ref[2] == expected_tests_ref: + logging.error( + f"In file '{i}' for \n\t'{ref[0]}'\nexpected\n\t'" + f"{expected_tests_ref}'\nbut found\n\t'{ref[2]}'.\n" + ) + err += 1 + sys.exit(err) + + +if __name__ == "__main__": + main() diff --git a/tools/vendor/ceedling/Gemfile.lock b/tools/vendor/ceedling/Gemfile.lock index 8c738df3..0a2715d0 100644 --- a/tools/vendor/ceedling/Gemfile.lock +++ b/tools/vendor/ceedling/Gemfile.lock @@ -2,30 +2,31 @@ GEM remote: http://rubygems.org/ specs: constructor (2.0.0) - deep_merge (1.2.1) - diff-lcs (1.3) + deep_merge (1.2.2) + diff-lcs (1.5.0) diy (1.1.2) constructor (>= 1.0.0) - rake (12.3.3) - require_all (1.3.3) - rr (1.1.2) - rspec (3.8.0) - rspec-core (~> 3.8.0) - rspec-expectations (~> 3.8.0) - rspec-mocks (~> 3.8.0) - rspec-core (3.8.0) - rspec-support (~> 3.8.0) - rspec-expectations (3.8.2) + rake (13.0.6) + require_all (3.0.0) + rr (3.1.0) + rspec (3.12.0) + rspec-core (~> 3.12.0) + rspec-expectations (~> 3.12.0) + rspec-mocks (~> 3.12.0) + rspec-core (3.12.0) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-mocks (3.8.0) + rspec-support (~> 3.12.0) + rspec-mocks (3.12.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-support (3.8.0) - thor (0.19.1) + rspec-support (~> 3.12.0) + rspec-support (3.12.0) + thor (1.2.1) PLATFORMS ruby + x64-mingw-ucrt x64-mingw32 DEPENDENCIES @@ -40,4 +41,4 @@ DEPENDENCIES thor BUNDLED WITH - 2.0.2 + 2.3.26 diff --git a/tools/vendor/ceedling/README.md b/tools/vendor/ceedling/README.md index 7f63c572..a9875871 100644 --- a/tools/vendor/ceedling/README.md +++ b/tools/vendor/ceedling/README.md @@ -1,5 +1,4 @@ -Ceedling --------- +# Ceedling This directory contains the vendored files of Ceedling, the unit-test-runner used by this project. It is released, if not otherwise specified under the diff --git a/tools/vendor/ceedling/bin/ceedling b/tools/vendor/ceedling/bin/ceedling index d110f3d4..5a1d4958 100644 --- a/tools/vendor/ceedling/bin/ceedling +++ b/tools/vendor/ceedling/bin/ceedling @@ -6,10 +6,10 @@ require 'fileutils' # Check for the main project file (either the one defined in the ENV or the default) main_filepath = ENV['CEEDLING_MAIN_PROJECT_FILE'] -project_found = (!main_filepath.nil? && File.exists?(main_filepath)) +project_found = (!main_filepath.nil? && File.exist?(main_filepath)) if (!project_found) main_filepath = "project.yml" - project_found = File.exists?(main_filepath) + project_found = File.exist?(main_filepath) end def is_windows? @@ -17,16 +17,16 @@ def is_windows? return ((Config::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false) end +def here + File.join(File.expand_path(File.dirname(__FILE__)),"/..") +end + unless (project_found) #===================================== We Do Not Have A Project ================================================ puts "Welcome to Ceedling!" require 'thor' - def here - File.dirname(__FILE__) + "/.." - end - class CeedlingTasks < Thor include Thor::Actions @@ -51,13 +51,14 @@ unless (project_found) desc "upgrade PROJECT_NAME", "upgrade ceedling for a project (not req'd if gem used)" def upgrade(name, silent = false) as_local = true + yaml_path = File.join(name, "project.yml") begin - require "yaml" - as_local = (YAML.load_file(File.join(name, "project.yml"))[:project][:which_ceedling] != 'gem') + require File.join(here,"lib","ceedling","yaml_wrapper.rb") + as_local = (YamlWrapper.new.load(yaml_path)[:project][:which_ceedling] != 'gem') rescue raise "ERROR: Could not find valid project file '#{yaml_path}'" end - found_docs = File.exists?( File.join(name, "docs", "CeedlingPacket.md") ) + found_docs = File.exist?( File.join(name, "docs", "CeedlingPacket.md") ) copy_assets_and_create_structure(name, silent, true, {:upgrade => true, :no_configs => true, :local => as_local, :docs => found_docs}) end @@ -66,7 +67,7 @@ unless (project_found) puts "WARNING: --no_docs deprecated. It is now the default. Specify -docs if you want docs installed." if (options[:no_docs] || options[:nodocs]) puts "WARNING: --as_gem deprecated. It is now the default. Specify -local if you want ceedling installed to this project." if (options[:as_gem] || options[:asgem]) - puts "WARNING: --with_ignore deprecated. It is now called -gitignore" if (options[:with_ignore] || options[:with_ignore]) + puts "WARNING: --with_ignore deprecated. It is now called -gitignore" if (options[:with_ignore] || options[:withignore]) use_docs = options[:docs] || false use_configs = !(options[:no_configs] || options[:noconfigs] || false) @@ -84,13 +85,22 @@ unless (project_found) [source_path, test_path, test_support_path].each do |d| FileUtils.mkdir_p d end + else + prj_yaml = YamlWrapper.new.load(File.join(name, 'project.yml')) + test_support_path = if prj_yaml.key?(:path) && \ + prj_yaml[:path].key?(:support) + prj_yaml.key?[:path][:support] + else + '' + end end # Genarate gitkeep in test support path - FileUtils.touch(File.join(test_support_path, '.gitkeep')) + FileUtils.touch(File.join(test_support_path, '.gitkeep')) unless \ + test_support_path.empty? # If documentation requested, create a place to dump them and do so - doc_path = "" + doc_path = '' if use_docs doc_path = use_gem ? File.join(name, 'docs') : File.join(ceedling_path, 'docs') FileUtils.mkdir_p doc_path @@ -238,7 +248,7 @@ unless (project_found) #===================================== We Have A Project Already ================================================ else - require 'yaml' + require File.join(here,"lib","ceedling","yaml_wrapper.rb") require 'rbconfig' #determine platform @@ -262,20 +272,20 @@ else :add_path => [], :path_connector => (platform == :mswin) ? ";" : ":", :graceful_fail => false, - :which_ceedling => (Dir.exists?("vendor/ceedling") ? "vendor/ceedling" : 'gem'), + :which_ceedling => (Dir.exist?("vendor/ceedling") ? "vendor/ceedling" : 'gem'), :default_tasks => [ 'test:all' ], :list_tasks => false } #guess that we need a special script file first if it exists if (platform == :mswin) - options[:pretest] = File.exists?("#{ platform.to_s }_setup.bat") ? "#{ platform.to_s }_setup.bat" : nil + options[:pretest] = File.exist?("#{ platform }_setup.bat") ? "#{ platform }_setup.bat" : nil else - options[:pretest] = File.exists?("#{ platform.to_s }_setup.sh") ? "source #{ platform.to_s }_setup.sh" : nil + options[:pretest] = File.exist?("#{ platform }_setup.sh") ? "source #{ platform }_setup.sh" : nil end #merge in project settings if they can be found here - yaml_options = YAML.load_file(main_filepath) + yaml_options = YamlWrapper.new.load(main_filepath) if (yaml_options[:paths]) options[:add_path] = yaml_options[:paths][:tools] || [] else @@ -302,6 +312,10 @@ else options[:list_tasks] = true when /^project:(\w+)/ ENV['CEEDLING_USER_PROJECT_FILE'] = "#{$1}.yml" + when /^--test_case=(\w+)/ + ENV['CEEDLING_INCLUDE_TEST_CASE_NAME'] = $1 + when /^--exclude_test_case=(\w+)/ + ENV['CEEDLING_EXCLUDE_TEST_CASE_NAME'] = $1 else options[:args].push(v) end @@ -318,7 +332,7 @@ else end # Load Ceedling (either through the rakefile OR directly) - if (File.exists?("rakefile.rb")) + if (File.exist?("rakefile.rb")) load 'rakefile.rb' else if (options[:which_ceedling] == 'gem') diff --git a/tools/vendor/ceedling/lib/ceedling/build_batchinator.rb b/tools/vendor/ceedling/lib/ceedling/build_batchinator.rb new file mode 100644 index 00000000..f48aee77 --- /dev/null +++ b/tools/vendor/ceedling/lib/ceedling/build_batchinator.rb @@ -0,0 +1,102 @@ + +class BuildBatchinator + + constructor :configurator, :streaminator, :reportinator + + def setup + @queue = Queue.new + end + + # Neaten up a build step with progress message and some scope encapsulation + def build_step(msg, heading: true, &block) + if heading + msg = @reportinator.generate_heading(msg) + else # Progress message + msg = "\n" + @reportinator.generate_progress(msg) + end + + @streaminator.stdout_puts(msg, Verbosity::NORMAL) + + yield # Execute build step block + end + + # Parallelize work to be done: + # - Enqueue things (thread-safe) + # - Spin up a number of worker threads within constraints of project file config and amount of work + # - Each worker thread consumes one item from queue and runs the block against its details + # - When the queue is empty, the worker threads wind down + def exec(workload:, things:, &block) + workers = 0 + + case workload + when :compile + workers = @configurator.project_compile_threads + when :test + workers = @configurator.project_test_threads + else + raise NameError("Unrecognized batch workload type: #{workload}") + end + + # Enqueue all the items the block will execute against + things.each { |thing| @queue << thing } + + # Choose lesser of max workers or number of things to process & redefine workers + # (It's neater and more efficient to avoid workers we won't use) + workers = [workers, things.size].min + + threads = (1..workers).collect do + thread = Thread.new do + begin + # Run tasks until there are no more enqueued + loop do + # pop(true) is non-blocking and raises ThreadError when queue is empty + yield @queue.pop(true) + end + + # First, handle thread exceptions (should always be due to empty queue) + rescue ThreadError => e + # Typical case: do nothing and allow thread to wind down + + # ThreadError outside scope of expected empty queue condition + unless e.message.strip.casecmp("queue empty") + # Shutdown all worker threads + shutdown_threads(threads) + + raise(e) # Raise exception again + end + + # Second, catch every other kind of exception so we can intervene with thread cleanup. + # Generally speaking, catching Exception is a no-no, but we must in this case. + # Raise the exception again so that: + # 1. Calling code knows something bad happened and handles appropriately + # 2. Ruby runtime can handle most serious problems + rescue Exception => e + # Shutdown all worker threads + shutdown_threads(threads) + + raise(e) # Raise exception again after intervening + end + end + + # Hand thread to Enumerable collect() routine + thread + end + + # Hand worker threads to scheduler / wait for them to finish + threads.each { |thread| thread.join } + end + + ### Private ### + + private + + # Terminate worker threads other than ourselves (we're already winding down) + def shutdown_threads(workers) + workers.each do |thread| + next if thread == Thread.current + thread.terminate + end + end + +end + diff --git a/tools/vendor/ceedling/lib/ceedling/build_invoker_utils.rb b/tools/vendor/ceedling/lib/ceedling/build_invoker_utils.rb index 5727bcab..7f57dc4f 100644 --- a/tools/vendor/ceedling/lib/ceedling/build_invoker_utils.rb +++ b/tools/vendor/ceedling/lib/ceedling/build_invoker_utils.rb @@ -12,10 +12,8 @@ class BuildInvokerUtils # ==== Attributes # # * _exception_: The exception given by a rescue statement. - # * _context_: A symbol representing where in the build the exception - # occurs. - # * _test_build_: A bool to signify if the exception occurred while building - # from test or source. + # * _context_: A symbol representing where in the build the exception occurs. + # * _test_build_: A bool to signify if the exception occurred while building from test or source. # def process_exception(exception, context, test_build=true) if (exception.message =~ /Don't know how to build task '(.+)'/i) @@ -26,7 +24,7 @@ def process_exception(exception, context, test_build=true) @streaminator.stderr_puts( error_header ) if (@configurator.project_use_deep_dependencies) - help_message = "Try fixing #include statements or adding missing file. Then run '#{REFRESH_TASK_ROOT}#{context.to_s}' task and try again." + help_message = "Try fixing #include statements or adding missing file. Then run '#{REFRESH_TASK_ROOT}#{context}' task and try again." @streaminator.stderr_puts( help_message ) end diff --git a/tools/vendor/ceedling/lib/ceedling/cmock_builder.rb b/tools/vendor/ceedling/lib/ceedling/cmock_builder.rb deleted file mode 100644 index 4a74aa84..00000000 --- a/tools/vendor/ceedling/lib/ceedling/cmock_builder.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'cmock' - -class CmockBuilder - - attr_accessor :cmock - - def setup - @cmock = nil - end - - def manufacture(cmock_config) - @cmock = CMock.new(cmock_config) - end - -end diff --git a/tools/vendor/ceedling/lib/ceedling/config_matchinator.rb b/tools/vendor/ceedling/lib/ceedling/config_matchinator.rb new file mode 100644 index 00000000..9bff4cb9 --- /dev/null +++ b/tools/vendor/ceedling/lib/ceedling/config_matchinator.rb @@ -0,0 +1,156 @@ + + +# :
: +# :: +# :: +# :: +# - +# - +# - ... + +class ConfigMatchinator + + constructor :configurator, :streaminator + + def config_include?(section:, context:, operation:nil) + # Create configurator accessor method + accessor = (section.to_s + '_' + context.to_s).to_sym + + # If no entry in configuration for context in this section, bail out + return false if not @configurator.respond_to?( accessor ) + + # If operation undefined, we've progressed as far as we need and already know the config is present + return true if operation.nil? + + # Get element associated with this context + elem = @configurator.send( accessor ) + + # If [section][context] is a simple array + if elem.is_a?(Array) + # A list instead of a hash, means [operation] is not present + return false + + # If [section][context] is a hash + elsif elem.is_a?(Hash) + return elem.include?( operation ) + end + + # Otherwise, [section][context] is something that cannot contain an [operation] sub-hash + return false + end + + def get_config(section:, context:, operation:nil) + # Create configurator accessor method + accessor = (section.to_s + '_' + context.to_s).to_sym + + # If no entry in configuration for context in this section, bail out + return nil if not @configurator.respond_to?( accessor ) + + # Get config element associated with this context + elem = @configurator.send( accessor ) + + # If [section][context] is a simple array + if elem.class == Array + # If no operation specified, then a simple array makes sense + return elem if operation.nil? + + # Otherwise, if an operation is specified but we have an array, go boom + error = "ERROR: [#{section}][#{context}] present in project configuration but does not contain [#{operation}]." + @streaminator.stderr_puts(error, Verbosity::ERRORS) + raise + + # If [section][context] is a hash + elsif elem.class == Hash + if not operation.nil? + # Bail out if we're looking for an [operation] sub-hash, but it's not present + return nil if not elem.include?( operation ) + + # Return array or hash at operation + return elem[operation] + + # If operation is not being queried, but we have a hash, return the hash + else + return elem + end + + # If [section][context] is nothing we expect--something other than an array or hash + else + error = "ERROR: [#{section}][#{context}] in project configuration is neither a list nor hash." + @streaminator.stderr_puts(error, Verbosity::ERRORS) + raise + end + + return nil + end + + def validate_matchers(hash:, section:, context:, operation:nil) + # Look for matcher keys with missing values + hash.each do |k, v| + if v == nil + operation = operation.nil? ? '' : "[#{operation}]" + error = "ERROR: Missing list of values for [#{section}][#{context}]#{operation}[#{k}] matcher in project configuration." + @streaminator.stderr_puts(error, Verbosity::ERRORS) + raise + end + end + end + + # Note: This method only relevant if hash includes test filepath matching keys + def matches?(hash:, filepath:, section:, context:, operation:nil) + _values = [] + + # Sanity check + if filepath.nil? + @streaminator.stderr_puts("NOTICE: [#{section}][#{context}]#{operation} > '#{matcher}' matching provided nil #{filepath}", Verbosity::ERROR) + raise + end + + # Iterate through every hash touple [matcher key, values array] + # In prioritized order match test filepath against each matcher key... + # 1. Wildcard + # 2. Any filepath matching + # 3. Regex + # + # Wildcard and filepath matching can look like valid regexes, so they must be evaluated first. + # + # Each element of the collected _values array will be an array of values. + + hash.each do |matcher, values| + # 1. Try wildcard matching -- return values for every test filepath if '*' is found in values matching key + if ('*' == matcher.to_s.strip) + _values += values + + # 2. Try filepath literal matching (including substring matching) with each values matching key + elsif (filepath.include?(matcher.to_s.strip)) + _values += values + + # 3. Try regular expression matching against all values matching keys that are regexes (ignore if not a valid regex) + # Note: We use logical AND here so that we get a meaningful fall-through to the else reporting condition. + # Nesting the actual regex matching beneath validity checking improperly catches unmatched regexes + elsif (regex?(matcher.to_s.strip)) and (!(filepath =~ /#{matcher.to_s.strip}/).nil?) + _values += values + + else + operation = operation.nil? ? '' : "[#{operation}]" + @streaminator.stderr_puts("NOTICE: [#{section}][#{context}]#{operation} > '#{matcher}' did not match #{filepath}", Verbosity::DEBUG) + end + end + + return _values.flatten # Flatten to handle YAML aliases + end + + private + + def regex?(expr) + valid = true + + begin + Regexp.new(expr) + rescue RegexpError + valid = false + end + + return valid + end + +end diff --git a/tools/vendor/ceedling/lib/ceedling/configurator.rb b/tools/vendor/ceedling/lib/ceedling/configurator.rb index 0ae4d04a..86940710 100644 --- a/tools/vendor/ceedling/lib/ceedling/configurator.rb +++ b/tools/vendor/ceedling/lib/ceedling/configurator.rb @@ -10,7 +10,7 @@ class Configurator attr_reader :project_config_hash, :script_plugins, :rake_plugins attr_accessor :project_logging, :project_debug, :project_verbosity, :sanity_checks - constructor(:configurator_setup, :configurator_builder, :configurator_plugins, :cmock_builder, :yaml_wrapper, :system_wrapper) do + constructor(:configurator_setup, :configurator_builder, :configurator_plugins, :yaml_wrapper, :system_wrapper) do @project_logging = false @project_debug = false @project_verbosity = Verbosity::NORMAL @@ -18,8 +18,11 @@ class Configurator end def setup - # special copy of cmock config to provide to cmock for construction - @cmock_config_hash = {} + # Cmock config reference to provide to CMock for mock generation + @cmock_config = {} # Default empty hash, replaced by reference below + + # Runner config reference to provide to runner generation + @runner_config = {} # Default empty hash, replaced by reference below # note: project_config_hash is an instance variable so constants and accessors created # in eval() statements in build() have something of proper scope and persistence to reference @@ -84,7 +87,7 @@ def populate_defaults(config) def populate_unity_defaults(config) unity = config[:unity] || {} - @runner_config = unity.merge(@runner_config || config[:test_runner] || {}) + @runner_config = unity.merge(config[:test_runner] || {}) end def populate_cmock_defaults(config) @@ -100,11 +103,11 @@ def populate_cmock_defaults(config) cmock[:enforce_strict_ordering] = true if (cmock[:enforce_strict_ordering].nil?) cmock[:mock_path] = File.join(config[:project][:build_root], TESTS_BASE_PATH, 'mocks') if (cmock[:mock_path].nil?) + cmock[:verbosity] = @project_verbosity if (cmock[:verbosity].nil?) cmock[:plugins] = [] if (cmock[:plugins].nil?) cmock[:plugins].map! { |plugin| plugin.to_sym } - cmock[:plugins] << (:cexception) if (!cmock[:plugins].include?(:cexception) and (config[:project][:use_exceptions])) cmock[:plugins].uniq! cmock[:unity_helper] = false if (cmock[:unity_helper].nil?) @@ -117,12 +120,26 @@ def populate_cmock_defaults(config) @runner_config = cmock.merge(@runner_config || config[:test_runner] || {}) - @cmock_builder.manufacture(cmock) + @cmock_config = cmock + end + + + def copy_vendor_defines(config) + # NOTE: To maintain any backwards compatibility following a refactoring of :defines: handling, + # copy top-level vendor defines into the respective tool areas. + config[UNITY_SYM].store(:defines, config[:defines][UNITY_SYM]) + config[CMOCK_SYM].store(:defines, config[:defines][CMOCK_SYM]) + config[CEXCEPTION_SYM].store(:defines, config[:defines][CEXCEPTION_SYM]) end def get_runner_config - @runner_config + return @runner_config.clone + end + + + def get_cmock_config + return @cmock_config.clone end @@ -143,9 +160,6 @@ def tools_setup(config) # populate stderr redirect option tool[:stderr_redirect] = StdErrRedirect::NONE if (tool[:stderr_redirect].nil?) - # populate background execution option - tool[:background_exec] = BackgroundExec::NONE if (tool[:background_exec].nil?) - # populate optional option to control verification of executable in search paths tool[:optional] = false if (tool[:optional].nil?) end @@ -328,6 +342,27 @@ def build(config, *keys) end + def redefine_element(elem, value) + # Ensure elem is a symbol + elem = elem.to_sym if elem.class != Symbol + + # Ensure element already exists + if not @project_config_hash.include?(elem) + @streaminator.stderr_puts("Could not rederine #{elem} in configurator--element does not exist", Verbosity::ERROR) + raise + end + + # Update internal hash + @project_config_hash[elem] = value + + # Update global constant + @configurator_builder.build_global_constant(elem, value) + + # Update backup config + store_config + end + + # add to constants and accessors as post build step def build_supplement(config_base, config_more) # merge in our post-build additions to base configuration hash @@ -357,7 +392,7 @@ def insert_rake_plugins(plugins) end end - ### private ### + ### Private ### private diff --git a/tools/vendor/ceedling/lib/ceedling/configurator_builder.rb b/tools/vendor/ceedling/lib/ceedling/configurator_builder.rb index f202d8a6..d3bddda8 100644 --- a/tools/vendor/ceedling/lib/ceedling/configurator_builder.rb +++ b/tools/vendor/ceedling/lib/ceedling/configurator_builder.rb @@ -11,21 +11,39 @@ class ConfiguratorBuilder constructor :file_system_utils, :file_wrapper, :system_wrapper + def build_global_constant(elem, value) + # Convert key names to Ruby constant names + # Some key names can be C file names that can include dashes + # Upcase the key names to create consitency and Ruby constants by convention + # Replace dashes with underscores to match handling of Ruby accessor method names + formatted_key = elem.to_s.gsub('-','_').upcase + + # Undefine global constant if it already exists + Object.send(:remove_const, formatted_key.to_sym) if @system_wrapper.constants_include?(formatted_key) + + # Create global constant + Object.module_eval("#{formatted_key} = value") + end + def build_global_constants(config) config.each_pair do |key, value| - formatted_key = key.to_s.upcase - # undefine global constant if it already exists - Object.send(:remove_const, formatted_key.to_sym) if @system_wrapper.constants_include?(formatted_key) - # create global constant - Object.module_eval("#{formatted_key} = value") + build_global_constant(key, value) end + + # TODO: This wants to go somewhere better + Object.module_eval("TOOLS_TEST_ASSEMBLER = {}") if (not config[:test_build_use_assembly]) && !defined?(TOOLS_TEST_ASSEMBLER) + Object.module_eval("TOOLS_RELEASE_ASSEMBLER = {}") if (not config[:release_build_use_assembly]) && !defined?(TOOLS_RELEASE_ASSEMBLER) end def build_accessor_methods(config, context) + # Fill configurator object with accessor methods config.each_pair do |key, value| - # fill configurator object with accessor methods - eval("def #{key.to_s.downcase}() return @project_config_hash[:#{key.to_s}] end", context) + # Convert key names to Ruby method names + # Some key names can be C file names that can include dashes; dashes are not allowed in Ruby method names + # Downcase the key names and replace any illegal dashes with legal underscores + # Downcased key names create consistency and ensure no method names become Ruby constants by accident + eval("def #{key.to_s.gsub('-','_').downcase}() return @project_config_hash[:#{key}] end", context) end end @@ -71,33 +89,52 @@ def populate_defaults(config, defaults) end - def clean(in_hash) + def cleanup(in_hash) # ensure that include files inserted into test runners have file extensions & proper ones at that in_hash[:test_runner_includes].map!{|include| include.ext(in_hash[:extension_header])} end + def set_exception_handling(in_hash) + # If project defines exception handling, do not change the setting. + # But, if the project omits exception handling setting... + if not in_hash[:project_use_exceptions] + # Automagically set it if cmock is configured for it + if in_hash[:cmock_plugins] && in_hash[:cmock_plugins].include?(:cexception) + in_hash[:project_use_exceptions] = true + # Otherwise, disable exceptions for the project + else + in_hash[:project_use_exceptions] = false + end + end + end + + def set_build_paths(in_hash) out_hash = {} project_build_artifacts_root = File.join(in_hash[:project_build_root], 'artifacts') project_build_tests_root = File.join(in_hash[:project_build_root], TESTS_BASE_PATH) + project_build_vendor_root = File.join(in_hash[:project_build_root], 'vendor') project_build_release_root = File.join(in_hash[:project_build_root], RELEASE_BASE_PATH) paths = [ [:project_build_artifacts_root, project_build_artifacts_root, true ], [:project_build_tests_root, project_build_tests_root, true ], + [:project_build_vendor_root, project_build_vendor_root, true ], [:project_build_release_root, project_build_release_root, in_hash[:project_release_build] ], [:project_test_artifacts_path, File.join(project_build_artifacts_root, TESTS_BASE_PATH), true ], [:project_test_runners_path, File.join(project_build_tests_root, 'runners'), true ], [:project_test_results_path, File.join(project_build_tests_root, 'results'), true ], [:project_test_build_output_path, File.join(project_build_tests_root, 'out'), true ], - [:project_test_build_output_asm_path, File.join(project_build_tests_root, 'out', 'asm'), true ], - [:project_test_build_output_c_path, File.join(project_build_tests_root, 'out', 'c'), true ], [:project_test_build_cache_path, File.join(project_build_tests_root, 'cache'), true ], [:project_test_dependencies_path, File.join(project_build_tests_root, 'dependencies'), true ], + [:project_build_vendor_unity_path, File.join(project_build_vendor_root, 'unity', 'src'), true ], + [:project_build_vendor_cmock_path, File.join(project_build_vendor_root, 'cmock', 'src'), in_hash[:project_use_mocks] ], + [:project_build_vendor_cexception_path, File.join(project_build_vendor_root, 'c_exception', 'lib'), in_hash[:project_use_exceptions] ], + [:project_release_artifacts_path, File.join(project_build_artifacts_root, RELEASE_BASE_PATH), in_hash[:project_release_build] ], [:project_release_build_cache_path, File.join(project_build_release_root, 'cache'), in_hash[:project_release_build] ], [:project_release_build_output_path, File.join(project_build_release_root, 'out'), in_hash[:project_release_build] ], @@ -106,7 +143,6 @@ def set_build_paths(in_hash) [:project_release_dependencies_path, File.join(project_build_release_root, 'dependencies'), in_hash[:project_release_build] ], [:project_log_path, File.join(in_hash[:project_build_root], 'logs'), true ], - [:project_temp_path, File.join(in_hash[:project_build_root], 'temp'), true ], [:project_test_preprocess_includes_path, File.join(project_build_tests_root, 'preprocess/includes'), in_hash[:project_use_test_preprocessor] ], [:project_test_preprocess_files_path, File.join(project_build_tests_root, 'preprocess/files'), in_hash[:project_use_test_preprocessor] ], @@ -132,33 +168,15 @@ def set_build_paths(in_hash) end - def set_force_build_filepaths(in_hash) - out_hash = {} - - out_hash[:project_test_force_rebuild_filepath] = File.join( in_hash[:project_test_dependencies_path], 'force_build' ) - out_hash[:project_release_force_rebuild_filepath] = File.join( in_hash[:project_release_dependencies_path], 'force_build' ) if (in_hash[:project_release_build]) - - return out_hash - end - - def set_rakefile_components(in_hash) out_hash = { :project_rakefile_component_files => [File.join(CEEDLING_LIB, 'ceedling', 'tasks_base.rake'), File.join(CEEDLING_LIB, 'ceedling', 'tasks_filesystem.rake'), File.join(CEEDLING_LIB, 'ceedling', 'tasks_tests.rake'), - File.join(CEEDLING_LIB, 'ceedling', 'tasks_vendor.rake'), File.join(CEEDLING_LIB, 'ceedling', 'rules_tests.rake')]} - out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_cmock.rake') if (in_hash[:project_use_mocks]) - out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_preprocess.rake') if (in_hash[:project_use_test_preprocessor]) - out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_tests_deep_dependencies.rake') if (in_hash[:project_use_deep_dependencies]) - out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'tasks_tests_deep_dependencies.rake') if (in_hash[:project_use_deep_dependencies]) - - out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_release_deep_dependencies.rake') if (in_hash[:project_release_build] and in_hash[:project_use_deep_dependencies]) out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_release.rake') if (in_hash[:project_release_build]) - out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'tasks_release_deep_dependencies.rake') if (in_hash[:project_release_build] and in_hash[:project_use_deep_dependencies]) out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'tasks_release.rake') if (in_hash[:project_release_build]) return out_hash @@ -203,7 +221,7 @@ def expand_all_path_globs(in_hash) # sorted to provide assured order of traversal in test calls on mocks path_keys.sort.each do |key| - out_hash["collection_#{key.to_s}".to_sym] = @file_system_utils.collect_paths( in_hash[key] ) + out_hash["collection_#{key}".to_sym] = @file_system_utils.collect_paths( in_hash[key] ) end return out_hash @@ -221,7 +239,7 @@ def collect_source_and_include_paths(in_hash) def collect_source_include_vendor_paths(in_hash) extra_paths = [] - extra_paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions]) + extra_paths << in_hash[:project_build_vendor_cexception_path] if (in_hash[:project_use_exceptions]) return { :collection_paths_source_include_vendor => @@ -294,7 +312,7 @@ def collect_assembly(in_hash) def collect_source(in_hash) all_source = @file_wrapper.instantiate_file_list in_hash[:collection_paths_source].each do |path| - if File.exists?(path) and not File.directory?(path) + if File.exist?(path) and not File.directory?(path) all_source.include( path ) else all_source.include( File.join(path, "*#{in_hash[:extension_source]}") ) @@ -312,7 +330,6 @@ def collect_headers(in_hash) paths = in_hash[:collection_paths_test] + in_hash[:collection_paths_support] + - in_hash[:collection_paths_source] + in_hash[:collection_paths_include] paths.each do |path| @@ -336,7 +353,7 @@ def collect_release_existing_compilation_input(in_hash) paths.each do |path| release_input.include( File.join(path, "*#{in_hash[:extension_header]}") ) - if File.exists?(path) and not File.directory?(path) + if File.exist?(path) and not File.directory?(path) release_input.include( path ) else release_input.include( File.join(path, "*#{in_hash[:extension_source]}") ) @@ -358,15 +375,16 @@ def collect_all_existing_compilation_input(in_hash) in_hash[:collection_paths_test] + in_hash[:collection_paths_support] + in_hash[:collection_paths_source] + - in_hash[:collection_paths_include] + - [File.join(in_hash[:unity_vendor_path], UNITY_LIB_PATH)] + in_hash[:collection_paths_include] - paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions]) - paths << File.join(in_hash[:cmock_vendor_path], CMOCK_LIB_PATH) if (in_hash[:project_use_mocks]) + # Vendor paths for frameworks + paths << in_hash[:project_build_vendor_unity_path] + paths << in_hash[:project_build_vendor_cexception_path] if (in_hash[:project_use_exceptions]) + paths << in_hash[:project_build_vendor_cmock_path] if (in_hash[:project_use_mocks]) paths.each do |path| all_input.include( File.join(path, "*#{in_hash[:extension_header]}") ) - if File.exists?(path) and not File.directory?(path) + if File.exist?(path) and not File.directory?(path) all_input.include( path ) else all_input.include( File.join(path, "*#{in_hash[:extension_source]}") ) @@ -384,38 +402,6 @@ def collect_all_existing_compilation_input(in_hash) end - def get_vendor_defines(in_hash) - defines = in_hash[:unity_defines].clone - defines.concat(in_hash[:cmock_defines]) if (in_hash[:project_use_mocks]) - defines.concat(in_hash[:cexception_defines]) if (in_hash[:project_use_exceptions]) - - return defines - end - - - def collect_vendor_defines(in_hash) - return {:collection_defines_vendor => get_vendor_defines(in_hash)} - end - - - def collect_test_and_vendor_defines(in_hash) - defines = in_hash[:defines_test].clone - vendor_defines = get_vendor_defines(in_hash) - defines.concat(vendor_defines) if vendor_defines - - return {:collection_defines_test_and_vendor => defines} - end - - - def collect_release_and_vendor_defines(in_hash) - release_defines = in_hash[:defines_release].clone - - release_defines.concat(in_hash[:cexception_defines]) if (in_hash[:project_use_exceptions]) - - return {:collection_defines_release_and_vendor => release_defines} - end - - def collect_release_artifact_extra_link_objects(in_hash) objects = [] @@ -427,26 +413,12 @@ def collect_release_artifact_extra_link_objects(in_hash) def collect_test_fixture_extra_link_objects(in_hash) - # Note: Symbols passed to compiler at command line can change Unity and CException behavior / configuration; - # we also handle those dependencies elsewhere in compilation dependencies - - sources = [UNITY_C_FILE] + sources = [] + support = @file_wrapper.instantiate_file_list() - in_hash[:files_support].each { |file| sources << file } + @file_system_utils.revise_file_list( support, in_hash[:files_support] ) - # we don't include paths here because use of plugins or mixing different compilers may require different build paths - sources << CEXCEPTION_C_FILE if (in_hash[:project_use_exceptions]) - sources << CMOCK_C_FILE if (in_hash[:project_use_mocks]) - - # if we're using mocks & a unity helper is defined & that unity helper includes a source file component (not only a header of macros), - # then link in the unity_helper object file too - if ( in_hash[:project_use_mocks] and in_hash[:cmock_unity_helper] ) - in_hash[:cmock_unity_helper].each do |helper| - if @file_wrapper.exist?(helper.ext(in_hash[:extension_source])) - sources << helper - end - end - end + support.each { |file| sources << file } # create object files from all the sources objects = sources.map { |file| File.basename(file) } @@ -459,15 +431,13 @@ def collect_test_fixture_extra_link_objects(in_hash) } end - private def get_vendor_paths(in_hash) vendor_paths = [] - vendor_paths << File.join(in_hash[:unity_vendor_path], UNITY_LIB_PATH) - vendor_paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions]) - vendor_paths << File.join(in_hash[:cmock_vendor_path], CMOCK_LIB_PATH) if (in_hash[:project_use_mocks]) - vendor_paths << in_hash[:cmock_mock_path] if (in_hash[:project_use_mocks]) + vendor_paths << in_hash[:project_build_vendor_unity_path] + vendor_paths << in_hash[:project_build_vendor_cmock_path] if (in_hash[:project_use_mocks]) + vendor_paths << in_hash[:project_build_vendor_cexception_path] if (in_hash[:project_use_exceptions]) return vendor_paths end diff --git a/tools/vendor/ceedling/lib/ceedling/configurator_setup.rb b/tools/vendor/ceedling/lib/ceedling/configurator_setup.rb index c43bb5c1..6580336a 100644 --- a/tools/vendor/ceedling/lib/ceedling/configurator_setup.rb +++ b/tools/vendor/ceedling/lib/ceedling/configurator_setup.rb @@ -16,11 +16,11 @@ class ConfiguratorSetup def build_project_config(config, flattened_config) ### flesh out config - @configurator_builder.clean(flattened_config) + @configurator_builder.cleanup(flattened_config) + @configurator_builder.set_exception_handling(flattened_config) ### add to hash values we build up from configuration & file system contents flattened_config.merge!(@configurator_builder.set_build_paths(flattened_config)) - flattened_config.merge!(@configurator_builder.set_force_build_filepaths(flattened_config)) flattened_config.merge!(@configurator_builder.set_rakefile_components(flattened_config)) flattened_config.merge!(@configurator_builder.set_release_target(flattened_config)) flattened_config.merge!(@configurator_builder.collect_project_options(flattened_config)) @@ -39,9 +39,6 @@ def build_project_config(config, flattened_config) flattened_config.merge!(@configurator_builder.collect_headers(flattened_config)) flattened_config.merge!(@configurator_builder.collect_release_existing_compilation_input(flattened_config)) flattened_config.merge!(@configurator_builder.collect_all_existing_compilation_input(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_vendor_defines(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_test_and_vendor_defines(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_release_and_vendor_defines(flattened_config)) flattened_config.merge!(@configurator_builder.collect_release_artifact_extra_link_objects(flattened_config)) flattened_config.merge!(@configurator_builder.collect_test_fixture_extra_link_objects(flattened_config)) diff --git a/tools/vendor/ceedling/lib/ceedling/configurator_validator.rb b/tools/vendor/ceedling/lib/ceedling/configurator_validator.rb index fc021012..f362f6ba 100644 --- a/tools/vendor/ceedling/lib/ceedling/configurator_validator.rb +++ b/tools/vendor/ceedling/lib/ceedling/configurator_validator.rb @@ -185,7 +185,7 @@ def retrieve_value(config, keys) def format_key_sequence(keys, depth) walked_keys = keys.slice(0, depth) - formatted_keys = walked_keys.map{|key| "[:#{key.to_s}]"} + formatted_keys = walked_keys.map{|key| "[:#{key}]"} return formatted_keys.join end diff --git a/tools/vendor/ceedling/lib/ceedling/constants.rb b/tools/vendor/ceedling/lib/ceedling/constants.rb index 19484f06..8d5fadfd 100644 --- a/tools/vendor/ceedling/lib/ceedling/constants.rb +++ b/tools/vendor/ceedling/lib/ceedling/constants.rb @@ -25,13 +25,6 @@ class StdErrRedirect end -class BackgroundExec - NONE = :none - AUTO = :auto - WIN = :win - UNIX = :unix -end - unless defined?(PROJECT_ROOT) PROJECT_ROOT = Dir.pwd() end @@ -42,17 +35,26 @@ class BackgroundExec EXTENSION_NONWIN_EXE = '.out' +PREPROCESS_SYM = :preprocess + +CEXCEPTION_SYM = :cexception CEXCEPTION_ROOT_PATH = 'c_exception' CEXCEPTION_LIB_PATH = "#{CEXCEPTION_ROOT_PATH}/lib" CEXCEPTION_C_FILE = 'CException.c' CEXCEPTION_H_FILE = 'CException.h' +UNITY_SYM = :unity UNITY_ROOT_PATH = 'unity' UNITY_LIB_PATH = "#{UNITY_ROOT_PATH}/src" UNITY_C_FILE = 'unity.c' UNITY_H_FILE = 'unity.h' UNITY_INTERNALS_H_FILE = 'unity_internals.h' +# Do-nothing macros defined in unity.h for extra build context to be used by build tools like Ceedling +UNITY_TEST_SOURCE_FILE = 'TEST_SOURCE_FILE' +UNITY_TEST_INCLUDE_PATH = 'TEST_INCLUDE_PATH' + +CMOCK_SYM = :cmock CMOCK_ROOT_PATH = 'cmock' CMOCK_LIB_PATH = "#{CMOCK_ROOT_PATH}/src" CMOCK_C_FILE = 'cmock.c' @@ -67,7 +69,7 @@ class BackgroundExec TEST_ROOT_NAME = 'test' unless defined?(TEST_ROOT_NAME) TEST_TASK_ROOT = TEST_ROOT_NAME + ':' unless defined?(TEST_TASK_ROOT) -TEST_SYM = TEST_ROOT_NAME.to_sym unless defined?(TEST_SYM) +TEST_SYM = :test RELEASE_ROOT_NAME = 'release' unless defined?(RELEASE_ROOT_NAME) RELEASE_TASK_ROOT = RELEASE_ROOT_NAME + ':' unless defined?(RELEASE_TASK_ROOT) diff --git a/tools/vendor/ceedling/lib/ceedling/debugger_utils.rb b/tools/vendor/ceedling/lib/ceedling/debugger_utils.rb new file mode 100644 index 00000000..6975b31f --- /dev/null +++ b/tools/vendor/ceedling/lib/ceedling/debugger_utils.rb @@ -0,0 +1,218 @@ +# The debugger utils class, +# Store functions and variables helping to parse debugger output and +# prepare output understandable by report generators +class DebuggerUtils + constructor :configurator, + :tool_executor, + :unity_utils + + def setup + @new_line_tag = '$$$' + @colon_tag = '!!!' + @command_line = nil + @test_result_collector_struct = Struct.new(:passed, :failed, :ignored, + :output, keyword_init: true) + end + + # Copy original command line generated from @tool_executor.build_command_line + # to use command line without command line extra args not needed by debugger + # + # @param [hash, #command] - Command line generated from @tool_executor.build_command_line + def configure_debugger(command) + # Make a clone of clean command hash + # for further calls done for collecting segmentation fault + if @configurator.project_config_hash[:project_use_backtrace_gdb_reporter] && + @configurator.project_config_hash[:test_runner_cmdline_args] + @command_line = command.clone + elsif @configurator.project_config_hash[:project_use_backtrace_gdb_reporter] + # If command_lines are not enabled, do not clone but create reference to command + # line + @command_line = command + end + end + + # Execute test_runner file under gdb and return: + # - output -> stderr and stdout + # - time -> execution of single test + # + # @param [hash, #command] - Command line generated from @tool_executor.build_command_line + # @return [String, #output] - output from binary execution + # @return [Float, #time] - time execution of the binary file + def collect_cmd_output_with_gdb(command, cmd, test_case=nil) + gdb_file_name = @configurator.project_config_hash[:tools_backtrace_settings][:executable] + gdb_extra_args = @configurator.project_config_hash[:tools_backtrace_settings][:arguments] + gdb_extra_args = gdb_extra_args.join(' ') + + gdb_exec_cmd = "#{gdb_file_name} #{gdb_extra_args} #{cmd}" + crash_result = @tool_executor.exec(gdb_exec_cmd, command[:options]) + if (crash_result[:exit_code] == 0) and (crash_result[:output] =~ /(?:PASS|FAIL|IGNORE)/) + [crash_result[:output], crash_result[:time].to_f] + else + ["#{gdb_file_name.split(/\w+/)[0]}:1:#{test_case || 'test_Unknown'}:FAIL:#{crash_result[:output]}", 0.0] + end + end + + # Collect list of test cases from test_runner + # and apply filters basing at passed : + # --test_case + # --exclude_test_case + # input arguments + # + # @param [hash, #command] - Command line generated from @tool_executor.build_command_line + # @return Array - list of the test_cases defined in test_file_runner + def collect_list_of_test_cases(command) + all_test_names = command[:line] + @unity_utils.additional_test_run_args('', 'list_test_cases') + test_list = @tool_executor.exec(all_test_names, command[:options]) + test_runner_tc = test_list[:output].split("\n").drop(1) + + # Clean collected test case names + # Filter tests which contain test_case_name passed by `--test_case` argument + if ENV['CEEDLING_INCLUDE_TEST_CASE_NAME'] + test_runner_tc.delete_if { |i| !(i =~ /#{ENV['CEEDLING_INCLUDE_TEST_CASE_NAME']}/) } + end + + # Filter tests which contain test_case_name passed by `--exclude_test_case` argument + if ENV['CEEDLING_EXCLUDE_TEST_CASE_NAME'] + test_runner_tc.delete_if { |i| i =~ /#{ENV['CEEDLING_EXCLUDE_TEST_CASE_NAME']}/ } + end + + test_runner_tc + end + + # Update stderr output stream to auto, to collect segmentation fault for + # test execution with gcov tool + # + # @param [hash, #command] - Command line generated from @tool_executor.build_command_line + def enable_gcov_with_gdb_and_cmdargs(command) + if @configurator.project_config_hash[:project_use_backtrace_gdb_reporter] && + @configurator.project_config_hash[:test_runner_cmdline_args] + command[:options][:stderr_redirect] = if [:none, StdErrRedirect::NONE].include? @configurator.project_config_hash[:tools_backtrace_settings][:stderr_redirect] + DEFAULT_BACKTRACE_TOOL[:stderr_redirect] + else + @configurator.project_config_hash[:tools_backtrace_settings][:stderr_redirect] + end + end + end + + # Support function to collect backtrace from gdb. + # If test_runner_cmdline_args is set, function it will try to run each of test separately + # and create output String similar to non segmentation fault execution but with notification + # test with segmentation fault as failure + # + # @param [hash, #shell_result] - output shell created by calling @tool_executor.exec + # @return hash - updated shell_result passed as argument + def gdb_output_collector(shell_result) + test_case_result_collector = @test_result_collector_struct.new( + passed: 0, + failed: 0, + ignored: 0, + output: [] + ) + + # Reset time + shell_result[:time] = 0 + + test_case_list_to_execute = collect_list_of_test_cases(@command_line) + test_case_list_to_execute.each do |test_case_name| + test_run_cmd = @command_line.clone + test_run_cmd_with_args = test_run_cmd[:line] + @unity_utils.additional_test_run_args(test_case_name, 'test_case') + test_output, exec_time = collect_cmd_output_with_gdb(test_run_cmd, test_run_cmd_with_args, test_case_name) + + # Concatenate execution time between tests + # running tests serpatatelly might increase total execution time + shell_result[:time] += exec_time + + # Concatenate test results from single test runs, which not crash + # to create proper output for further parser + if test_output =~ /([\S]+):(\d+):([\S]+):(IGNORE|PASS|FAIL:)(.*)/ + test_output = "#{Regexp.last_match(1)}:#{Regexp.last_match(2)}:#{Regexp.last_match(3)}:#{Regexp.last_match(4)}#{Regexp.last_match(5)}" + if test_output =~ /:PASS/ + test_case_result_collector[:passed] += 1 + elsif test_output =~ /:IGNORE/ + test_case_result_collector[:ignored] += 1 + elsif test_output =~ /:FAIL:/ + test_case_result_collector[:failed] += 1 + end + else + # <-- Parse Segmentatation Fault output section --> + + # Withdraw test_name from gdb output + test_name = if test_output =~ /<(.*)>/ + Regexp.last_match(1) + else + '' + end + + # Collect file_name and line in which Segmentation fault have his beginning + if test_output =~ /#{test_name}\s\(\)\sat\s(.*):(\d+)\n/ + # Remove path from file_name + file_name = Regexp.last_match(1).to_s.split('/').last.split('\\').last + # Save line number + line = Regexp.last_match(2) + + # Replace: + # - '\n' by @new_line_tag to make gdb output flat + # - ':' by @colon_tag to avoid test results problems + # to enable parsing output for default generator_test_results regex + test_output = test_output.gsub("\n", @new_line_tag).gsub(':', @colon_tag) + test_output = "#{file_name}:#{line}:#{test_name}:FAIL: #{test_output}" + end + + # Mark test as failure + test_case_result_collector[:failed] += 1 + end + test_case_result_collector[:output].append("#{test_output}\r\n") + end + + template = "\n-----------------------\n" \ + "\n#{(test_case_result_collector[:passed] + \ + test_case_result_collector[:failed] + \ + test_case_result_collector[:ignored])} " \ + "Tests #{test_case_result_collector[:failed]} " \ + "Failures #{test_case_result_collector[:ignored]} Ignored\n\n" + + template += if test_case_result_collector[:failed] > 0 + "FAIL\n" + else + "OK\n" + end + shell_result[:output] = test_case_result_collector[:output].join('') + template + + shell_result + end + + # Restore new line under flatten log + # + # @param(String, #text) - string containing flatten output log + # @return [String, #output] - output with restored new line character + def restore_new_line_character_in_flatten_log(text) + if @configurator.project_config_hash[:project_use_backtrace_gdb_reporter] && + @configurator.project_config_hash[:test_runner_cmdline_args] + text = text.gsub(@new_line_tag, "\n") + end + text + end + + # Restore colon character under flatten log + # + # @param(String, #text) - string containing flatten output log + # @return [String, #output] - output with restored colon character + def restore_colon_character_in_flatten_log(text) + if @configurator.project_config_hash[:project_use_backtrace_gdb_reporter] && + @configurator.project_config_hash[:test_runner_cmdline_args] + text = text.gsub(@colon_tag, ':') + end + text + end + + # Unflat segmentation fault log + # + # @param(String, #text) - string containing flatten output log + # @return [String, #output] - output with restored colon and new line character + def unflat_debugger_log(text) + text = restore_new_line_character_in_flatten_log(text) + text = restore_colon_character_in_flatten_log(text) + text = text.gsub('"',"'") # Replace " character by ' for junit_xml reporter + text + end +end diff --git a/tools/vendor/ceedling/lib/ceedling/defaults.rb b/tools/vendor/ceedling/lib/ceedling/defaults.rb index 1300a1aa..ad7b2777 100644 --- a/tools/vendor/ceedling/lib/ceedling/defaults.rb +++ b/tools/vendor/ceedling/lib/ceedling/defaults.rb @@ -10,15 +10,13 @@ :executable => ENV['CC'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CC'].split[0], :name => 'default_test_compiler'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ ENV['CC'].nil? ? "" : ENV['CC'].split[1..-1], ENV['CPPFLAGS'].nil? ? "" : ENV['CPPFLAGS'].split, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, - {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, - "-DGNU_COMPILER".freeze, + "-I\"${5}\"".freeze, # Per-test executable search paths + "-D\"${6}\"".freeze, # Per-test executable defines + "-DGNU_COMPILER".freeze, # OSX clang "-g".freeze, ENV['CFLAGS'].nil? ? "" : ENV['CFLAGS'].split, "-c \"${1}\"".freeze, @@ -33,13 +31,12 @@ :executable => ENV['CCLD'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CCLD'].split[0], :name => 'default_test_linker'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ ENV['CCLD'].nil? ? "" : ENV['CCLD'].split[1..-1], ENV['CFLAGS'].nil? ? "" : ENV['CFLAGS'].split, ENV['LDFLAGS'].nil? ? "" : ENV['LDFLAGS'].split, - "\"${1}\"".freeze, + "${1}".freeze, "${5}".freeze, "-o \"${2}\"".freeze, "".freeze, @@ -52,32 +49,45 @@ :executable => '${1}'.freeze, :name => 'default_test_fixture'.freeze, :stderr_redirect => StdErrRedirect::AUTO.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [].freeze } -DEFAULT_TEST_INCLUDES_PREPROCESSOR_TOOL = { +DEFAULT_TEST_SHALLOW_INCLUDES_PREPROCESSOR_TOOL = { :executable => ENV['CC'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CC'].split[0], :name => 'default_test_includes_preprocessor'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ ENV['CC'].nil? ? "" : ENV['CC'].split[1..-1], ENV['CPPFLAGS'].nil? ? "" : ENV['CPPFLAGS'].split, - '-E'.freeze, # OSX clang - '-MM'.freeze, - '-MG'.freeze, - # avoid some possibility of deep system lib header file complications by omitting vendor paths - # if cpp is run on *nix system, escape spaces in paths; if cpp on windows just use the paths collection as is - # {"-I\"$\"" => "{SystemWrapper.windows? ? COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE : COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE.map{|path| path.gsub(\/ \/, \'\\\\ \') }}"}.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, - {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, - {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze, + '-E'.freeze, # Run only through preprocessor stage with its output + '-MM'.freeze, # Output make rule + suppress header files found in system header directories + '-MG'.freeze, # Assume missing header files are generated files (do not discard) + '-MP'.freeze, # Create make "phony" rules for each include dependency + "-D\"${2}\"".freeze, # Per-test executable defines "-DGNU_COMPILER".freeze, # OSX clang - # '-nostdinc'.freeze, # disabled temporarily due to stdio access violations on OSX + '-nostdinc'.freeze, # Ignore standard include paths + "\"${1}\"".freeze + ].freeze + } + +DEFAULT_TEST_NESTED_INCLUDES_PREPROCESSOR_TOOL = { + :executable => ENV['CC'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CC'].split[0], + :name => 'default_test_includes_preprocessor'.freeze, + :stderr_redirect => StdErrRedirect::NONE.freeze, + :optional => false.freeze, + :arguments => [ + ENV['CC'].nil? ? "" : ENV['CC'].split[1..-1], + ENV['CPPFLAGS'].nil? ? "" : ENV['CPPFLAGS'].split, + '-E'.freeze, # Run only through preprocessor stage with its output + '-MM'.freeze, # Output make rule + suppress header files found in system header directories + '-MG'.freeze, # Assume missing header files are generated files (do not discard) + '-H'.freeze, # Also output #include list with depth + "-I\"${2}\"".freeze, # Per-test executable search paths + "-D\"${3}\"".freeze, # Per-test executable defines + "-DGNU_COMPILER".freeze, # OSX clang + '-nostdinc'.freeze, # Ignore standard include paths "\"${1}\"".freeze ].freeze } @@ -86,17 +96,14 @@ :executable => ENV['CC'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CC'].split[0], :name => 'default_test_file_preprocessor'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ ENV['CC'].nil? ? "" : ENV['CC'].split[1..-1], ENV['CPPFLAGS'].nil? ? "" : ENV['CPPFLAGS'].split, '-E'.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, - {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, - {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze, - "-DGNU_COMPILER".freeze, + "-I\"${4}\"".freeze, # Per-test executable search paths + "-D\"${3}\"".freeze, # Per-test executable defines + "-DGNU_COMPILER".freeze, # OSX clang # '-nostdinc'.freeze, # disabled temporarily due to stdio access violations on OSX "\"${1}\"".freeze, "-o \"${2}\"".freeze @@ -107,14 +114,11 @@ :executable => FilePathUtils.os_executable_ext('gcc').freeze, :name => 'default_test_file_preprocessor_directives'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ '-E'.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, - {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, - {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze, + "-I\"${4}\"".freeze, # Per-test executable search paths + "-D\"${3}\"".freeze, # Per-test executable defines "-DGNU_COMPILER".freeze, '-fdirectives-only'.freeze, # '-nostdinc'.freeze, # disabled temporarily due to stdio access violations on OSX @@ -134,16 +138,13 @@ :executable => ENV['CC'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CC'].split[0], :name => 'default_test_dependencies_generator'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ ENV['CC'].nil? ? "" : ENV['CC'].split[1..-1], ENV['CPPFLAGS'].nil? ? "" : ENV['CPPFLAGS'].split, '-E'.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, - {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, - {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze, + "-I\"${5}\"".freeze, # Per-test executable search paths + "-D\"${4}\"".freeze, # Per-test executable defines "-DGNU_COMPILER".freeze, "-MT \"${3}\"".freeze, '-MM'.freeze, @@ -159,7 +160,6 @@ :executable => ENV['CC'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CC'].split[0], :name => 'default_release_dependencies_generator'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ ENV['CC'].nil? ? "" : ENV['CC'].split[1..-1], @@ -180,19 +180,16 @@ ].freeze } - DEFAULT_RELEASE_COMPILER_TOOL = { :executable => ENV['CC'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CC'].split[0], :name => 'default_release_compiler'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ ENV['CC'].nil? ? "" : ENV['CC'].split[1..-1], ENV['CPPFLAGS'].nil? ? "" : ENV['CPPFLAGS'].split, - {"-I\"$\"" => 'COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR'}.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE'}.freeze, - {"-D$" => 'COLLECTION_DEFINES_RELEASE_AND_VENDOR'}.freeze, + "-I\"${5}\"".freeze, # Search paths + "-D\"${6}\"".freeze, # Defines "-DGNU_COMPILER".freeze, ENV['CFLAGS'].nil? ? "" : ENV['CFLAGS'].split, "-c \"${1}\"".freeze, @@ -207,12 +204,12 @@ :executable => ENV['AS'].nil? ? FilePathUtils.os_executable_ext('as').freeze : ENV['AS'].split[0], :name => 'default_release_assembler'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ ENV['AS'].nil? ? "" : ENV['AS'].split[1..-1], ENV['ASFLAGS'].nil? ? "" : ENV['ASFLAGS'].split, - {"-I\"$\"" => 'COLLECTION_PATHS_SOURCE_AND_INCLUDE'}.freeze, + "-I\"${3}\"".freeze, # Search paths + "-D\"${4}\"".freeze, # Defines (FYI--allowed with GNU assembler but ignored) "\"${1}\"".freeze, "-o \"${2}\"".freeze, ].freeze @@ -222,7 +219,6 @@ :executable => ENV['CCLD'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CCLD'].split[0], :name => 'default_release_linker'.freeze, :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, :optional => false.freeze, :arguments => [ ENV['CCLD'].nil? ? "" : ENV['CCLD'].split[1..-1], @@ -237,18 +233,34 @@ ].freeze } +DEFAULT_BACKTRACE_TOOL = { + :executable => FilePathUtils.os_executable_ext('gdb').freeze, + :name => 'default_backtrace_settings'.freeze, + :stderr_redirect => StdErrRedirect::AUTO.freeze, + :optional => true.freeze, + :arguments => [ + '-q', + '--eval-command run', + '--eval-command backtrace', + '--batch', + '--args' + ].freeze + } + DEFAULT_TOOLS_TEST = { :tools => { :test_compiler => DEFAULT_TEST_COMPILER_TOOL, :test_linker => DEFAULT_TEST_LINKER_TOOL, :test_fixture => DEFAULT_TEST_FIXTURE_TOOL, + :backtrace_settings => DEFAULT_BACKTRACE_TOOL, } } DEFAULT_TOOLS_TEST_PREPROCESSORS = { :tools => { - :test_includes_preprocessor => DEFAULT_TEST_INCLUDES_PREPROCESSOR_TOOL, + :test_shallow_includes_preprocessor => DEFAULT_TEST_SHALLOW_INCLUDES_PREPROCESSOR_TOOL, + :test_nested_includes_preprocessor => DEFAULT_TEST_NESTED_INCLUDES_PREPROCESSOR_TOOL, :test_file_preprocessor => DEFAULT_TEST_FILE_PREPROCESSOR_TOOL, :test_file_preprocessor_directives => DEFAULT_TEST_FILE_PREPROCESSOR_DIRECTIVES_TOOL, } @@ -286,18 +298,14 @@ DEFAULT_CEEDLING_CONFIG = { :project => { # :build_root must be set by user - :use_exceptions => true, :use_mocks => true, :compile_threads => 1, :test_threads => 1, :use_test_preprocessor => false, - :use_preprocessor_directives => false, - :use_deep_dependencies => false, - :generate_deep_dependencies => true, # only applicable if use_deep_dependencies is true - :auto_link_deep_dependencies => false, :test_file_prefix => 'test_', :options_paths => [], :release_build => false, + :use_backtrace_gdb_reporter => false, }, :release_build => { @@ -331,24 +339,27 @@ ], :defines => { - :test => [], - :test_preprocess => [], + :test => [], # A hash/sub-hashes in config file can include operations and test executable matchers as keys + :preprocess => [], # A hash/sub-hashes in config file can include operations and test executable matchers as keys :release => [], - :release_preprocess => [], - :use_test_definition => false, + :unity => [], + :cmock => [], + :cexception => [] + }, + + :flags => { + # Test & release flags are validated for presence--empty flags causes an error + # :test => [], # A hash/sub-hashes in config file can include operations and test executable matchers as keys + # :release => [] # A hash/sub-hashes in config file can include arrays for operations }, :libraries => { :flag => '-l${1}', :path_flag => '-L ${1}', :test => [], - :test_preprocess => [], - :release => [], - :release_preprocess => [], + :release => [] }, - :flags => {}, - :extension => { :header => '.h', :source => '.c', @@ -361,22 +372,20 @@ :testpass => '.pass', :testfail => '.fail', :dependencies => '.d', + :yaml => '.yml' }, :unity => { - :vendor_path => CEEDLING_VENDOR, - :defines => [] + :vendor_path => CEEDLING_VENDOR }, :cmock => { :vendor_path => CEEDLING_VENDOR, - :defines => [], :includes => [] }, :cexception => { - :vendor_path => CEEDLING_VENDOR, - :defines => [] + :vendor_path => CEEDLING_VENDOR }, :test_runner => { @@ -422,7 +431,7 @@ <%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'TEST OUTPUT')%> % hash[:results][:stdout].each do |string| % string[:collection].each do |item| -<%=string[:source][:path]%><%=File::SEPARATOR%><%=string[:source][:file]%>: "<%=item%>" +<%=string[:source][:file]%>: "<%=item%>" % end % end @@ -431,7 +440,7 @@ <%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'IGNORED TEST SUMMARY')%> % hash[:results][:ignores].each do |ignore| % ignore[:collection].each do |item| -<%=ignore[:source][:path]%><%=File::SEPARATOR%><%=ignore[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%> +<%=ignore[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%> % if (item[:message].length > 0) : "<%=item[:message]%>" % else @@ -445,7 +454,7 @@ <%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'FAILED TEST SUMMARY')%> % hash[:results][:failures].each do |failure| % failure[:collection].each do |item| -<%=failure[:source][:path]%><%=File::SEPARATOR%><%=failure[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%> +<%=failure[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%> % if (item[:message].length > 0) : "<%=item[:message]%>" % else diff --git a/tools/vendor/ceedling/lib/ceedling/defineinator.rb b/tools/vendor/ceedling/lib/ceedling/defineinator.rb new file mode 100644 index 00000000..16b40da3 --- /dev/null +++ b/tools/vendor/ceedling/lib/ceedling/defineinator.rb @@ -0,0 +1,53 @@ + + +# :defines: +# :test: +# :*: # Define TEST during compilation of all files for all test executables +# - TEST +# :Model: # Define PLATFORM_B during compilation of any test executable with Model in its filename +# - -PLATFORM_B +# :unity: +# - UNITY_INCLUDE_PRINT_FORMATTED # Define Unity configuration symbols during all test compilation +# - UNITY_FLOAT_PRECISION=0.001f # ... +# :release: +# - COM=Serial # Define COM for compilation of all files during release build + +# :defines: +# :test: # Equivalent to [test]['*'] -- i.e. same defines for all test executables +# - TEST +# - PLATFORM_B + + + +class Defineinator + + constructor :configurator, :streaminator, :config_matchinator + + def setup + @section = :defines + end + + def defines_defined?(context:) + return @config_matchinator.config_include?(section:@section, context:context) + end + + def defines(context:, filepath:nil) + defines = @config_matchinator.get_config(section:@section, context:context) + + if defines == nil then return [] + elsif defines.is_a?(Array) then return defines.flatten # Flatten to handle YAML aliases + elsif defines.is_a?(Hash) + @config_matchinator.validate_matchers(hash:defines, section:@section, context:context) + + return @config_matchinator.matches?( + hash: defines, + filepath: filepath, + section: @section, + context: context) + end + + # Handle unexpected config element type + return [] + end + +end diff --git a/tools/vendor/ceedling/lib/ceedling/dependinator.rb b/tools/vendor/ceedling/lib/ceedling/dependinator.rb index accfe80c..647bc195 100644 --- a/tools/vendor/ceedling/lib/ceedling/dependinator.rb +++ b/tools/vendor/ceedling/lib/ceedling/dependinator.rb @@ -1,36 +1,22 @@ class Dependinator - constructor :configurator, :project_config_manager, :test_includes_extractor, :file_path_utils, :rake_wrapper, :file_wrapper - - def touch_force_rebuild_files - @file_wrapper.touch( @configurator.project_test_force_rebuild_filepath ) - @file_wrapper.touch( @configurator.project_release_force_rebuild_filepath ) if (@configurator.project_release_build) - end - + constructor :configurator, :project_config_manager, :test_context_extractor, :file_path_utils, :rake_wrapper, :file_wrapper def load_release_object_deep_dependencies(dependencies_list) dependencies_list.each do |dependencies_file| - if File.exists?(dependencies_file) + if File.exist?(dependencies_file) @rake_wrapper.load_dependencies( dependencies_file ) end end end - def enhance_release_file_dependencies(files) - files.each do |filepath| - @rake_wrapper[filepath].enhance( [@configurator.project_release_force_rebuild_filepath] ) if (@project_config_manager.release_config_changed) - end - end - - - def load_test_object_deep_dependencies(files_list) dependencies_list = @file_path_utils.form_test_dependencies_filelist(files_list) dependencies_list.each do |dependencies_file| - if File.exists?(dependencies_file) + if File.exist?(dependencies_file) @rake_wrapper.load_dependencies(dependencies_file) end end diff --git a/tools/vendor/ceedling/lib/ceedling/erb_wrapper.rb b/tools/vendor/ceedling/lib/ceedling/erb_wrapper.rb index 8d70b6d2..77c458b5 100644 --- a/tools/vendor/ceedling/lib/ceedling/erb_wrapper.rb +++ b/tools/vendor/ceedling/lib/ceedling/erb_wrapper.rb @@ -3,7 +3,7 @@ class ErbWrapper def generate_file(template, data, output_file) File.open(output_file, "w") do |f| - f << ERB.new(template, 0, "<>").result(binding) + f << ERB.new(template, trim_mode: "<>").result(binding) end end end \ No newline at end of file diff --git a/tools/vendor/ceedling/lib/ceedling/file_finder.rb b/tools/vendor/ceedling/lib/ceedling/file_finder.rb index 53775b7b..34c38778 100644 --- a/tools/vendor/ceedling/lib/ceedling/file_finder.rb +++ b/tools/vendor/ceedling/lib/ceedling/file_finder.rb @@ -1,8 +1,5 @@ require 'rubygems' require 'rake' # for adding ext() method to string -require 'thread' - - class FileFinder SEMAPHORE = Mutex.new @@ -19,21 +16,14 @@ def prepare_search_sources def find_header_file(mock_file) header = File.basename(mock_file).sub(/#{@configurator.cmock_mock_prefix}/, '').ext(@configurator.extension_header) - found_path = @file_finder_helper.find_file_in_collection(header, @configurator.collection_all_headers, :error) + found_path = @file_finder_helper.find_file_in_collection(header, @configurator.collection_all_headers, :error, mock_file) return found_path end def find_header_input_for_mock_file(mock_file) - found_path = find_header_file(mock_file) - mock_input = found_path - - if (@configurator.project_use_test_preprocessor) - mock_input = @cacheinator.diff_cached_test_file( @file_path_utils.form_preprocessed_file_filepath( found_path ) ) - end - - return mock_input + return find_header_file(mock_file) end @@ -44,7 +34,7 @@ def find_source_from_test(test, complain) source = File.basename(test).sub(/#{test_prefix}/, '') # we don't blow up if a test file has no corresponding source file - return @file_finder_helper.find_file_in_collection(source, source_paths, complain) + return @file_finder_helper.find_file_in_collection(source, source_paths, complain, test) end @@ -53,7 +43,7 @@ def find_test_from_runner_path(runner_path) test_file = File.basename(runner_path).sub(/#{@configurator.test_runner_file_suffix}#{'\\'+extension_source}/, extension_source) - found_path = @file_finder_helper.find_file_in_collection(test_file, @configurator.collection_all_tests, :error) + found_path = @file_finder_helper.find_file_in_collection(test_file, @configurator.collection_all_tests, :error, runner_path) return found_path end @@ -74,7 +64,7 @@ def find_test_input_for_runner_file(runner_path) def find_test_from_file_path(file_path) test_file = File.basename(file_path).ext(@configurator.extension_source) - found_path = @file_finder_helper.find_file_in_collection(test_file, @configurator.collection_all_tests, :error) + found_path = @file_finder_helper.find_file_in_collection(test_file, @configurator.collection_all_tests, :error, file_path) return found_path end @@ -82,7 +72,7 @@ def find_test_from_file_path(file_path) def find_test_or_source_or_header_file(file_path) file = File.basename(file_path) - return @file_finder_helper.find_file_in_collection(file, @all_test_source_and_header_file_collection, :error) + return @file_finder_helper.find_file_in_collection(file, @all_test_source_and_header_file_collection, :error, file_path) end @@ -102,28 +92,33 @@ def find_compilation_input_file(file_path, complain=:error, release=false) @file_finder_helper.find_file_in_collection( source_file, @file_wrapper.directory_listing( File.join(@configurator.project_test_runners_path, '*') ), - complain) + complain, + file_path) elsif (@configurator.project_use_mocks and (source_file =~ /#{@configurator.cmock_mock_prefix}/)) found_file = @file_finder_helper.find_file_in_collection( source_file, - @file_wrapper.directory_listing( File.join(@configurator.cmock_mock_path, '*') ), - complain) + @file_wrapper.directory_listing( File.join(@configurator.cmock_mock_path, '**/*.*') ), + complain, + file_path) elsif release found_file = @file_finder_helper.find_file_in_collection( source_file, @configurator.collection_release_existing_compilation_input, - complain) + complain, + file_path) + else temp_complain = (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) ? :ignore : complain found_file = @file_finder_helper.find_file_in_collection( source_file, @configurator.collection_all_existing_compilation_input, - temp_complain) + temp_complain, + file_path) found_file ||= find_assembly_file(file_path, false) if (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) end } @@ -133,17 +128,17 @@ def find_compilation_input_file(file_path, complain=:error, release=false) def find_source_file(file_path, complain) source_file = File.basename(file_path).ext(@configurator.extension_source) - return @file_finder_helper.find_file_in_collection(source_file, @configurator.collection_all_source, complain) + return @file_finder_helper.find_file_in_collection(source_file, @configurator.collection_all_source, complain, file_path) end def find_assembly_file(file_path, complain = :error) assembly_file = File.basename(file_path).ext(@configurator.extension_assembly) - return @file_finder_helper.find_file_in_collection(assembly_file, @configurator.collection_all_assembly, complain) + return @file_finder_helper.find_file_in_collection(assembly_file, @configurator.collection_all_assembly, complain, file_path) end def find_file_from_list(file_path, file_list, complain) - return @file_finder_helper.find_file_in_collection(file_path, file_list, complain) + return @file_finder_helper.find_file_in_collection(file_path, file_list, complain, file_path) end end diff --git a/tools/vendor/ceedling/lib/ceedling/file_finder_helper.rb b/tools/vendor/ceedling/lib/ceedling/file_finder_helper.rb index a168e5cb..b9ad300f 100644 --- a/tools/vendor/ceedling/lib/ceedling/file_finder_helper.rb +++ b/tools/vendor/ceedling/lib/ceedling/file_finder_helper.rb @@ -6,34 +6,42 @@ class FileFinderHelper constructor :streaminator - def find_file_in_collection(file_name, file_list, complain, extra_message="") + def find_file_in_collection(file_name, file_list, complain, original_filepath="") file_to_find = nil - file_list.each do |item| - base_file = File.basename(item) + # search our collection for the specified base filename + matches = file_list.find_all {|v| File.basename(v) == file_name } + case matches.length + when 0 + matches = file_list.find_all {|v| v =~ /(?:\\|\/|^)#{file_name}$/i} + if (matches.length > 0) + blow_up(file_name, "However, a filename having different capitalization was found: '#{matches[0]}'.") + end - # case insensitive comparison - if (base_file.casecmp(file_name) == 0) - # case sensitive check - if (base_file == file_name) - file_to_find = item - break - else - blow_up(file_name, "However, a filename having different capitalization was found: '#{item}'.") + case (complain) + when :error then blow_up(file_name) + when :warn then gripe(file_name) + #when :ignore then end - end - - end - - if file_to_find.nil? - case (complain) - when :error then blow_up(file_name, extra_message) - when :warn then gripe(file_name, extra_message) - #when :ignore then - end + when 1 + return matches[0] + else + # Determine the closest match by giving looking for matching path segments, especially paths ENDING the same + best_match_index = 0 + best_match_value = 0 + reverse_original_pieces = original_filepath.split(/(?:\\|\/)/).reverse + matches.each_with_index do |m,i| + reverse_match_pieces = m.split(/(?:\\|\/)/).reverse + # + num = reverse_original_pieces.zip(reverse_match_pieces).inject(0){|s,v| v[0] == v[1] ? s+3 : s} + num = reverse_original_pieces.inject(num){|s,v| reverse_match_pieces.include?(v) ? s+1 : s} + if num > best_match_value + best_match_index = i + best_match_value = num + end + end + return matches[best_match_index] end - - return file_to_find end private diff --git a/tools/vendor/ceedling/lib/ceedling/file_path_utils.rb b/tools/vendor/ceedling/lib/ceedling/file_path_utils.rb index 89a28ba7..c4d04f75 100644 --- a/tools/vendor/ceedling/lib/ceedling/file_path_utils.rb +++ b/tools/vendor/ceedling/lib/ceedling/file_path_utils.rb @@ -76,10 +76,6 @@ def self.reform_glob(path) ######### instance methods ########## - def form_temp_path(filepath, prefix='') - return File.join( @configurator.project_temp_path, prefix + File.basename(filepath) ) - end - ### release ### def form_release_build_cache_path(filepath) return File.join( @configurator.project_release_build_cache_path, File.basename(filepath) ) @@ -122,12 +118,12 @@ def form_test_dependencies_filepath(filepath) return File.join( @configurator.project_test_dependencies_path, File.basename(filepath).ext(@configurator.extension_dependencies) ) end - def form_pass_results_filepath(filepath) - return File.join( @configurator.project_test_results_path, File.basename(filepath).ext(@configurator.extension_testpass) ) + def form_pass_results_filepath(build_output_path, filepath) + return File.join( build_output_path, File.basename(filepath).ext(@configurator.extension_testpass) ) end - def form_fail_results_filepath(filepath) - return File.join( @configurator.project_test_results_path, File.basename(filepath).ext(@configurator.extension_testfail) ) + def form_fail_results_filepath(build_output_path, filepath) + return File.join( build_output_path, File.basename(filepath).ext(@configurator.extension_testfail) ) end def form_runner_filepath_from_test(filepath) @@ -150,43 +146,33 @@ def form_test_build_asm_object_filepath(filepath) return File.join( @configurator.project_test_build_output_asm_path, File.basename(filepath).ext(@configurator.extension_object) ) end - def form_test_executable_filepath(filepath) - return File.join( @configurator.project_test_build_output_path, File.basename(filepath).ext(@configurator.extension_executable) ) + def form_test_executable_filepath(build_output_path, filepath) + return File.join( build_output_path, File.basename(filepath).ext(@configurator.extension_executable) ) end - def form_test_build_map_filepath(filepath) - return File.join( @configurator.project_test_build_output_path, File.basename(filepath).ext(@configurator.extension_map) ) + def form_test_build_map_filepath(build_output_path, filepath) + return File.join( build_output_path, File.basename(filepath).ext(@configurator.extension_map) ) end def form_test_build_list_filepath(filepath) return File.join( @configurator.project_test_build_output_path, File.basename(filepath).ext(@configurator.extension_list) ) end - def form_preprocessed_file_filepath(filepath) - return File.join( @configurator.project_test_preprocess_files_path, File.basename(filepath) ) + def form_preprocessed_file_filepath(filepath, subdir) + return File.join( @configurator.project_test_preprocess_files_path, subdir, File.basename(filepath) ) end - def form_preprocessed_includes_list_filepath(filepath) - return File.join( @configurator.project_test_preprocess_includes_path, File.basename(filepath) ) + def form_preprocessed_includes_list_filepath(filepath, subdir) + return File.join( @configurator.project_test_preprocess_includes_path, subdir, File.basename(filepath) + @configurator.extension_yaml ) end - def form_test_build_objects_filelist(sources) - return (@file_wrapper.instantiate_file_list(sources)).pathmap("#{@configurator.project_test_build_output_c_path}/%n#{@configurator.extension_object}") - end - - def form_preprocessed_mockable_headers_filelist(mocks) - list = @file_wrapper.instantiate_file_list(mocks) - headers = list.map do |file| - module_name = File.basename(file).sub(/^#{@configurator.cmock_mock_prefix}/, '').sub(/\.[a-zA-Z]+$/,'') - "#{@configurator.project_test_preprocess_files_path}/#{module_name}#{@configurator.extension_header}" - end - return headers + def form_test_build_objects_filelist(path, sources) + return (@file_wrapper.instantiate_file_list(sources)).pathmap("#{path}/%n#{@configurator.extension_object}") end - def form_mocks_source_filelist(mocks) + def form_mocks_source_filelist(path, mocks) list = (@file_wrapper.instantiate_file_list(mocks)) - sources = list.map{|file| "#{@configurator.cmock_mock_path}/#{file}#{@configurator.extension_source}"} - return sources + return list.map{ |file| File.join(path, File.basename(file).ext(@configurator.extension_source)) } end def form_test_dependencies_filelist(files) diff --git a/tools/vendor/ceedling/lib/ceedling/file_system_utils.rb b/tools/vendor/ceedling/lib/ceedling/file_system_utils.rb index 97e5856f..bf29650c 100644 --- a/tools/vendor/ceedling/lib/ceedling/file_system_utils.rb +++ b/tools/vendor/ceedling/lib/ceedling/file_system_utils.rb @@ -53,7 +53,7 @@ def collect_paths(*paths) FilePathUtils.add_path?(path) ? plus.merge(dirs) : minus.merge(dirs) end - return (plus - minus).to_a.uniq + return (plus - minus).to_a.uniq.sort end diff --git a/tools/vendor/ceedling/lib/ceedling/file_wrapper.rb b/tools/vendor/ceedling/lib/ceedling/file_wrapper.rb index 9e5a909b..59662fca 100644 --- a/tools/vendor/ceedling/lib/ceedling/file_wrapper.rb +++ b/tools/vendor/ceedling/lib/ceedling/file_wrapper.rb @@ -20,6 +20,10 @@ def exist?(filepath) return File.exist?(filepath) end + def extname(filepath) + return File.extname(filepath) + end + def directory?(path) return File.directory?(path) end @@ -40,14 +44,34 @@ def rm_r(filepath, options={}) FileUtils.rm_r(filepath, **options={}) end + def rm_rf(path, options={}) + FileUtils.rm_rf(path, **options={}) + end + def cp(source, destination, options={}) FileUtils.cp(source, destination, **options) end + def cp_r(source, destination, options={}) + FileUtils.cp_r(source, destination, **options) + end + + def mv(source, destination, options={}) + FileUtils.mv(source, destination, **options) + end + def compare(from, to) return FileUtils.compare_file(from, to) end + # Is filepath A newer than B? + def newer?(filepathA, filepathB) + return false unless File.exist?(filepathA) + return false unless File.exist?(filepathB) + + return (File.mtime(filepathA) > File.mtime(filepathB)) + end + def open(filepath, flags) File.open(filepath, flags) do |file| yield(file) diff --git a/tools/vendor/ceedling/lib/ceedling/flaginator.rb b/tools/vendor/ceedling/lib/ceedling/flaginator.rb index 31d62c46..87953c77 100644 --- a/tools/vendor/ceedling/lib/ceedling/flaginator.rb +++ b/tools/vendor/ceedling/lib/ceedling/flaginator.rb @@ -1,74 +1,57 @@ -require 'rubygems' -require 'rake' # for ext() -require 'fileutils' -require 'ceedling/constants' - # :flags: -# :release: +# :test: # :compile: -# :'test_.+' -# - -pedantic # add '-pedantic' to every test file -# :*: # add '-foo' to compilation of all files not main.c +# :*: # Add '-foo' to compilation of all files for all test executables # - -foo -# :main: # add '-Wall' to compilation of main.c +# :Model: # Add '-Wall' to compilation of any test executable with Model in its filename # - -Wall -# :test: # :link: -# :test_main: # add '--bar --baz' to linking of test_main.exe +# :tests/comm/TestUsart.c: # Add '--bar --baz' to link step of TestUsart executable # - --bar # - --baz +# :release: +# - -std=c99 -def partition(hash, &predicate) - hash.partition(&predicate).map(&:to_h) -end +# :flags: +# :test: +# :compile: # Equivalent to [test][compile]['*'] -- i.e. same extra flags for all test executables +# - -foo +# - -Wall +# :link: # Equivalent to [test][link]['*'] -- i.e. same flags for all test executables +# - --bar +# - --baz class Flaginator - constructor :configurator + constructor :configurator, :streaminator, :config_matchinator - def get_flag(hash, file_name) - file_key = file_name.to_sym - - # 1. try literals - literals, magic = partition(hash) { |k, v| k.to_s =~ /^\w+$/ } - return literals[file_key] if literals.include?(file_key) - - any, regex = partition(magic) { |k, v| (k == :'*') || (k == :'.*') } # glob or regex wild card - - # 2. try regexes - find_res = regex.find { |k, v| file_name =~ /^#{k.to_s}$/ } - return find_res[1] if find_res - - # 3. try anything - find_res = any.find { |k, v| file_name =~ /.*/ } - return find_res[1] if find_res - - # 4. well, we've tried - return [] + def setup + @section = :flags end - - def flag_down( operation, context, file ) - # create configurator accessor method - accessor = ('flags_' + context.to_s).to_sym - # create simple filename key from whatever filename provided - file_name = File.basename( file ).ext('') - file_key = File.basename( file ).ext('').to_sym - - # if no entry in configuration for flags for this context, bail out - return [] if not @configurator.respond_to?( accessor ) + def flags_defined?(context:, operation:nil) + return @config_matchinator.config_include?(section:@section, context:context, operation:operation) + end - # get flags sub hash associated with this context - flags = @configurator.send( accessor ) + def flag_down(context:, operation:, filepath:nil) + flags = @config_matchinator.get_config(section:@section, context:context, operation:operation) - # if operation not represented in flags hash, bail out - return [] if not flags.include?( operation ) + if flags == nil then return [] + elsif flags.is_a?(Array) then return flags.flatten # Flatten to handle YAML aliases + elsif flags.is_a?(Hash) + @config_matchinator.validate_matchers(hash:flags, section:@section, context:context, operation:operation) - # redefine flags to sub hash associated with the operation - flags = flags[operation] + return @config_matchinator.matches?( + hash: flags, + filepath: filepath, + section: @section, + context: context, + operation: operation) + end - return get_flag(flags, file_name) + # Handle unexpected config element type + return [] end end diff --git a/tools/vendor/ceedling/lib/ceedling/generator.rb b/tools/vendor/ceedling/lib/ceedling/generator.rb index 0b890247..877d2c2b 100644 --- a/tools/vendor/ceedling/lib/ceedling/generator.rb +++ b/tools/vendor/ceedling/lib/ceedling/generator.rb @@ -1,53 +1,57 @@ require 'ceedling/constants' +require 'ceedling/file_path_utils' class Generator constructor :configurator, :generator_helper, :preprocessinator, - :cmock_builder, + :generator_mocks, :generator_test_runner, :generator_test_results, - :flaginator, - :test_includes_extractor, + :test_context_extractor, :tool_executor, :file_finder, :file_path_utils, + :reportinator, :streaminator, :plugin_manager, - :file_wrapper - - - def generate_shallow_includes_list(context, file) - @streaminator.stdout_puts("Generating include list for #{File.basename(file)}...", Verbosity::NORMAL) - @preprocessinator.preprocess_shallow_includes(file) - end - - def generate_preprocessed_file(context, file) - @streaminator.stdout_puts("Preprocessing #{File.basename(file)}...", Verbosity::NORMAL) - @preprocessinator.preprocess_file(file) - end - - def generate_dependencies_file(tool, context, source, object, dependencies) - @streaminator.stdout_puts("Generating dependencies for #{File.basename(source)}...", Verbosity::NORMAL) - - command = - @tool_executor.build_command_line( - tool, - [], # extra per-file command line parameters - source, - dependencies, - object) - - @tool_executor.exec( command[:line], command[:options] ) - end - - def generate_mock(context, header_filepath) - arg_hash = {:header_file => header_filepath, :context => context} + :file_wrapper, + :debugger_utils, + :unity_utils + + + def generate_mock(context:, mock:, test:, input_filepath:, output_path:) + arg_hash = { + :header_file => input_filepath, + :test => test, + :context => context, + :output_path => output_path } + @plugin_manager.pre_mock_generate( arg_hash ) begin - @cmock_builder.cmock.setup_mocks( arg_hash[:header_file] ) + # Below is a workaround that nsantiates CMock anew: + # 1. To allow dfferent output path per mock + # 2. To avoid any thread safety complications + + # TODO: + # - Add option to CMock to generate mock to any destination path + # - Make CMock thread-safe + + # Get default config created by Ceedling and customize it + config = @generator_mocks.build_configuration( output_path ) + + # Generate mock + msg = @reportinator.generate_module_progress( + operation: "Generating mock for", + module_name: test, + filename: File.basename(input_filepath) + ) + @streaminator.stdout_puts(msg, Verbosity::NORMAL) + + cmock = @generator_mocks.manufacture( config ) + cmock.setup_mocks( arg_hash[:header_file] ) rescue raise ensure @@ -56,22 +60,38 @@ def generate_mock(context, header_filepath) end # test_filepath may be either preprocessed test file or original test file - def generate_test_runner(context, test_filepath, runner_filepath) - arg_hash = {:context => context, :test_file => test_filepath, :runner_file => runner_filepath} + def generate_test_runner(context:, mock_list:, test_filepath:, input_filepath:, runner_filepath:) + arg_hash = { + :context => context, + :test_file => test_filepath, + :input_file => input_filepath, + :runner_file => runner_filepath} + @plugin_manager.pre_runner_generate(arg_hash) - # collect info we need - module_name = File.basename(arg_hash[:test_file]) - test_cases = @generator_test_runner.find_test_cases( @file_finder.find_test_from_runner_path(runner_filepath) ) - mock_list = @test_includes_extractor.lookup_raw_mock_list(arg_hash[:test_file]) + # Instantiate the test runner generator each time needed for thread safety + # TODO: Make UnityTestRunnerGenerator thread-safe + generator = @generator_test_runner.manufacture() - @streaminator.stdout_puts("Generating runner for #{module_name}...", Verbosity::NORMAL) + # collect info we need + module_name = File.basename( arg_hash[:test_file] ) + test_cases = @generator_test_runner.find_test_cases( + generator: generator, + test_filepath: arg_hash[:test_file], + input_filepath: arg_hash[:input_file] + ) - test_file_includes = [] # Empty list for now, since apparently unused + msg = @reportinator.generate_progress("Generating runner for #{module_name}") + @streaminator.stdout_puts(msg, Verbosity::NORMAL) # build runner file begin - @generator_test_runner.generate(module_name, runner_filepath, test_cases, mock_list, test_file_includes) + @generator_test_runner.generate( + generator: generator, + module_name: module_name, + runner_filepath: runner_filepath, + test_cases: test_cases, + mock_list: mock_list) rescue raise ensure @@ -79,19 +99,120 @@ def generate_test_runner(context, test_filepath, runner_filepath) end end - def generate_object_file(tool, operation, context, source, object, list='', dependencies='') + def generate_object_file_c( + tool:, + module_name:, + context:, + source:, + object:, + search_paths:[], + flags:[], + defines:[], + list:'', + dependencies:'', + msg:nil + ) + + shell_result = {} + arg_hash = { :tool => tool, + :module_name => module_name, + :operation => OPERATION_COMPILE_SYM, + :context => context, + :source => source, + :object => object, + :search_paths => search_paths, + :flags => flags, + :defines => defines, + :list => list, + :dependencies => dependencies + } + + @plugin_manager.pre_compile_execute(arg_hash) + + msg = String(msg) + msg = @reportinator.generate_module_progress( + operation: "Compiling", + module_name: module_name, + filename: File.basename(arg_hash[:source]) + ) if msg.empty? + @streaminator.stdout_puts(msg, Verbosity::NORMAL) + + command = + @tool_executor.build_command_line( + arg_hash[:tool], + arg_hash[:flags], + arg_hash[:source], + arg_hash[:object], + arg_hash[:list], + arg_hash[:dependencies], + arg_hash[:search_paths], + arg_hash[:defines] + ) + + @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) + + begin + shell_result = @tool_executor.exec( command[:line], command[:options] ) + rescue ShellExecutionException => ex + shell_result = ex.shell_result + raise ex + ensure + arg_hash[:shell_command] = command[:line] + arg_hash[:shell_result] = shell_result + @plugin_manager.post_compile_execute(arg_hash) + end + end + + def generate_object_file_asm( + tool:, + module_name:, + context:, + source:, + object:, + search_paths:[], + flags:[], + defines:[], + list:'', + dependencies:'', + msg:nil + ) + shell_result = {} - arg_hash = {:tool => tool, :operation => operation, :context => context, :source => source, :object => object, :list => list, :dependencies => dependencies} + + arg_hash = { :tool => tool, + :module_name => module_name, + :operation => OPERATION_ASSEMBLE_SYM, + :context => context, + :source => source, + :object => object, + :search_paths => search_paths, + :flags => flags, + :defines => defines, + :list => list, + :dependencies => dependencies + } + @plugin_manager.pre_compile_execute(arg_hash) - @streaminator.stdout_puts("Compiling #{File.basename(arg_hash[:source])}...", Verbosity::NORMAL) + msg = String(msg) + msg = @reportinator.generate_module_progress( + operation: "Assembling", + module_name: module_name, + filename: File.basename(arg_hash[:source]) + ) if msg.empty? + @streaminator.stdout_puts(msg, Verbosity::NORMAL) + command = - @tool_executor.build_command_line( arg_hash[:tool], - @flaginator.flag_down( operation, context, source ), - arg_hash[:source], - arg_hash[:object], - arg_hash[:list], - arg_hash[:dependencies]) + @tool_executor.build_command_line( + arg_hash[:tool], + arg_hash[:flags], + arg_hash[:source], + arg_hash[:object], + arg_hash[:search_paths], + arg_hash[:defines], + arg_hash[:list], + arg_hash[:dependencies] + ) @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) @@ -107,11 +228,12 @@ def generate_object_file(tool, operation, context, source, object, list='', depe end end - def generate_executable_file(tool, context, objects, executable, map='', libraries=[], libpaths=[]) + def generate_executable_file(tool, context, objects, flags, executable, map='', libraries=[], libpaths=[]) shell_result = {} arg_hash = { :tool => tool, :context => context, :objects => objects, + :flags => flags, :executable => executable, :map => map, :libraries => libraries, @@ -120,32 +242,43 @@ def generate_executable_file(tool, context, objects, executable, map='', librari @plugin_manager.pre_link_execute(arg_hash) - @streaminator.stdout_puts("Linking #{File.basename(arg_hash[:executable])}...", Verbosity::NORMAL) + msg = @reportinator.generate_progress("Linking #{File.basename(arg_hash[:executable])}") + @streaminator.stdout_puts(msg, Verbosity::NORMAL) + command = - @tool_executor.build_command_line( arg_hash[:tool], - @flaginator.flag_down( OPERATION_LINK_SYM, context, executable ), - arg_hash[:objects], - arg_hash[:executable], - arg_hash[:map], - arg_hash[:libraries], - arg_hash[:libpaths] - ) + @tool_executor.build_command_line( + arg_hash[:tool], + arg_hash[:flags], + arg_hash[:objects], + arg_hash[:executable], + arg_hash[:map], + arg_hash[:libraries], + arg_hash[:libpaths] + ) @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) begin shell_result = @tool_executor.exec( command[:line], command[:options] ) rescue ShellExecutionException => ex notice = "\n" + - "NOTICE: If the linker reports missing symbols, the following may be to blame:\n" + - " 1. Test lacks #include statements corresponding to needed source files.\n" + - " 2. Project search paths do not contain source files corresponding to #include statements in the test.\n" + "NOTICE: Ceedling assumes header files correspond to source files. A test file directs its build\n" + + "with #include statemetns as to which source files to compile and link into the executable.\n\n" + + "If the linker reports missing symbols, the following may be to blame:\n" + + " 1. This test lacks #include header statements corresponding to needed source files.\n" + + " 2. Project file paths omit source files corresponding to #include statements in this test.\n" + + " 3. Complex macros, #ifdefs, etc. have obscured correct #include statements in this test.\n" if (@configurator.project_use_mocks) - notice += " 3. Test does not #include needed mocks.\n\n" + notice += " 4. This test does not #include needed mocks to be generated.\n\n" else notice += "\n" end + notice += "OPTIONS:\n" + + " 1. Doublecheck this test's #include statements.\n" + + " 2. Simplify complex macros or fully specify defines for this test in project config.\n" + + " 3. Use #{UNITY_TEST_SOURCE_FILE}() macro in this test to include a source file in the build.\n\n" + @streaminator.stderr_puts(notice, Verbosity::COMPLAIN) shell_result = ex.shell_result raise '' @@ -155,22 +288,48 @@ def generate_executable_file(tool, context, objects, executable, map='', librari end end - def generate_test_results(tool, context, executable, result) + def generate_test_results(tool:, context:, executable:, result:) arg_hash = {:tool => tool, :context => context, :executable => executable, :result_file => result} @plugin_manager.pre_test_fixture_execute(arg_hash) - @streaminator.stdout_puts("Running #{File.basename(arg_hash[:executable])}...", Verbosity::NORMAL) + msg = @reportinator.generate_progress("Running #{File.basename(arg_hash[:executable])}") + @streaminator.stdout_puts(msg, Verbosity::NORMAL) # Unity's exit code is equivalent to the number of failed tests, so we tell @tool_executor not to fail out if there are failures # so that we can run all tests and collect all results command = @tool_executor.build_command_line(arg_hash[:tool], [], arg_hash[:executable]) + + # Configure debugger + @debugger_utils.configure_debugger(command) + + # Apply additional test case filters + command[:line] += @unity_utils.collect_test_runner_additional_args @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) + + # Enable collecting GCOV results even when segmenatation fault is appearing + # The gcda and gcno files will be generated for a test cases which doesn't + # cause segmentation fault + @debugger_utils.enable_gcov_with_gdb_and_cmdargs(command) + + # Run the test itself (allow it to fail. we'll analyze it in a moment) command[:options][:boom] = false shell_result = @tool_executor.exec( command[:line], command[:options] ) - #Don't Let The Failure Count Make Us Believe Things Aren't Working - shell_result[:exit_code] = 0 - @generator_helper.test_results_error_handler(executable, shell_result) + # Handle SegFaults + if shell_result[:output] =~ /\s*Segmentation\sfault.*/i + if @configurator.project_config_hash[:project_use_backtrace_gdb_reporter] && @configurator.project_config_hash[:test_runner_cmdline_args] + # If we have the options and tools to learn more, dig into the details + shell_result = @debugger_utils.gdb_output_collector(shell_result) + else + # Otherwise, call a segfault a single failure so it shows up in the report + shell_result[:output] = "#{File.basename(@file_finder.find_compilation_input_file(executable))}:1:test_Unknown:FAIL:Segmentation Fault" + shell_result[:output] += "\n-----------------------\n1 Tests 1 Failures 0 Ignored\nFAIL\n" + shell_result[:exit_code] = 1 + end + else + # Don't Let The Failure Count Make Us Believe Things Aren't Working + @generator_helper.test_results_error_handler(executable, shell_result) + end processed = @generator_test_results.process_and_write_results( shell_result, arg_hash[:result_file], diff --git a/tools/vendor/ceedling/lib/ceedling/generator_mocks.rb b/tools/vendor/ceedling/lib/ceedling/generator_mocks.rb new file mode 100644 index 00000000..b4025b50 --- /dev/null +++ b/tools/vendor/ceedling/lib/ceedling/generator_mocks.rb @@ -0,0 +1,31 @@ +require 'cmock' + +class GeneratorMocks + + constructor :configurator + + def manufacture(config) + return CMock.new(config) + end + + def build_configuration( output_path ) + config = @configurator.get_cmock_config + config[:mock_path] = output_path + + # Verbosity management for logging messages + case @configurator.project_verbosity + when Verbosity::SILENT + config[:verbosity] = 0 # CMock is silent + when Verbosity::ERRORS + when Verbosity::COMPLAIN + when Verbosity::NORMAL + when Verbosity::OBNOXIOUS + config[:verbosity] = 1 # Errors and warnings only so we can customize generation message ourselves + else # DEBUG + config[:verbosity] = 3 # Max verbosity + end + + return config + end + +end diff --git a/tools/vendor/ceedling/lib/ceedling/generator_test_results.rb b/tools/vendor/ceedling/lib/ceedling/generator_test_results.rb index 3af2d720..5c865f52 100644 --- a/tools/vendor/ceedling/lib/ceedling/generator_test_results.rb +++ b/tools/vendor/ceedling/lib/ceedling/generator_test_results.rb @@ -4,15 +4,16 @@ class GeneratorTestResults - constructor :configurator, :generator_test_results_sanity_checker, :yaml_wrapper + constructor :configurator, :generator_test_results_sanity_checker, :yaml_wrapper, :debugger_utils def process_and_write_results(unity_shell_result, results_file, test_file) output_file = results_file results = get_results_structure - results[:source][:path] = File.dirname(test_file) - results[:source][:file] = File.basename(test_file) + results[:source][:dirname] = File.dirname(test_file) + results[:source][:basename] = File.basename(test_file) + results[:source][:file] = test_file results[:time] = unity_shell_result[:time] unless unity_shell_result[:time].nil? # process test statistics @@ -21,32 +22,51 @@ def process_and_write_results(unity_shell_result, results_file, test_file) results[:counts][:failed] = $2.to_i results[:counts][:ignored] = $3.to_i results[:counts][:passed] = (results[:counts][:total] - results[:counts][:failed] - results[:counts][:ignored]) + else + if @configurator.project_config_hash[:project_use_backtrace_gdb_reporter] + # Accessing this code block we expect failure during test execution + # which should be connected with SIGSEGV + results[:counts][:total] = 1 # Set to one as the amount of test is unknown in segfault, and one of the test is failing + results[:counts][:failed] = 1 # Set to one as the one of tests is failing with segfault + results[:counts][:ignored] = 0 + results[:counts][:passed] = 0 + + #Collect function name which cause issue and line number + if unity_shell_result[:output] =~ /\s"(.*)",\sline_num=(\d*)/ + results[:failures] << { :test => $1, :line =>$2, :message => unity_shell_result[:output], :unity_test_time => unity_shell_result[:time]} + else + #In case if regex fail write default values + results[:failures] << { :test => '??', :line =>-1, :message => unity_shell_result[:output], :unity_test_time => unity_shell_result[:time]} + end + end end # remove test statistics lines output_string = unity_shell_result[:output].sub(TEST_STDOUT_STATISTICS_PATTERN, '') - output_string.lines do |line| # process unity output - case line + case line.chomp when /(:IGNORE)/ elements = extract_line_elements(line, results[:source][:file]) - results[:ignores] << elements[0] + results[:ignores] << elements[0] results[:stdout] << elements[1] if (!elements[1].nil?) when /(:PASS$)/ elements = extract_line_elements(line, results[:source][:file]) - results[:successes] << elements[0] + results[:successes] << elements[0] results[:stdout] << elements[1] if (!elements[1].nil?) when /(:PASS \(.* ms\)$)/ elements = extract_line_elements(line, results[:source][:file]) - results[:successes] << elements[0] + results[:successes] << elements[0] results[:stdout] << elements[1] if (!elements[1].nil?) when /(:FAIL)/ elements = extract_line_elements(line, results[:source][:file]) + elements[0][:test] = @debugger_utils.restore_new_line_character_in_flatten_log(elements[0][:test]) results[:failures] << elements[0] results[:stdout] << elements[1] if (!elements[1].nil?) else # collect up all other - results[:stdout] << line.chomp + if !@configurator.project_config_hash[:project_use_backtrace_gdb_reporter] + results[:stdout] << line.chomp + end end end @@ -54,6 +74,9 @@ def process_and_write_results(unity_shell_result, results_file, test_file) output_file = results_file.ext(@configurator.extension_testfail) if (results[:counts][:failed] > 0) + results[:failures].each do |failure| + failure[:message] = @debugger_utils.unflat_debugger_log(failure[:message]) + end @yaml_wrapper.dump(output_file, results) return { :result_file => output_file, :result => results } @@ -63,7 +86,7 @@ def process_and_write_results(unity_shell_result, results_file, test_file) def get_results_structure return { - :source => {:path => '', :file => ''}, + :source => {:file => '', :dirname => '', :basename => '' }, :successes => [], :failures => [], :ignores => [], @@ -81,7 +104,9 @@ def extract_line_elements(line, filename) if (line =~ stdout_regex) stdout = $1.clone - line.sub!(/#{Regexp.escape(stdout)}/, '') + unless @configurator.project_config_hash[:project_use_backtrace_gdb_reporter] + line.sub!(/#{Regexp.escape(stdout)}/, '') + end end # collect up test results minus and extra output @@ -92,8 +117,14 @@ def extract_line_elements(line, filename) unity_test_time = $1.to_f / 1000 elements[-1].sub!(/ \((\d*(?:\.\d*)?) ms\)/, '') end + if elements[3..-1] + message = (elements[3..-1].join(':')).strip + message = @debugger_utils.unflat_debugger_log(message) + else + message = nil + end - return {:test => elements[1], :line => elements[0].to_i, :message => (elements[3..-1].join(':')).strip, :unity_test_time => unity_test_time}, stdout if elements.size >= 3 + return {:test => elements[1], :line => elements[0].to_i, :message => message, :unity_test_time => unity_test_time}, stdout if elements.size >= 3 return {:test => '???', :line => -1, :message => nil, :unity_test_time => unity_test_time} #fallback safe option. TODO better handling end diff --git a/tools/vendor/ceedling/lib/ceedling/generator_test_runner.rb b/tools/vendor/ceedling/lib/ceedling/generator_test_runner.rb index 79ed7140..0c84e2f2 100644 --- a/tools/vendor/ceedling/lib/ceedling/generator_test_runner.rb +++ b/tools/vendor/ceedling/lib/ceedling/generator_test_runner.rb @@ -1,26 +1,23 @@ +require 'generate_test_runner.rb' # Unity's test runner generator class GeneratorTestRunner constructor :configurator, :file_path_utils, :file_wrapper - def find_test_cases(test_file) + def manufacture() + return UnityTestRunnerGenerator.new( @configurator.get_runner_config ) + end - #Pull in Unity's Test Runner Generator - require 'generate_test_runner.rb' - @test_runner_generator ||= UnityTestRunnerGenerator.new( @configurator.get_runner_config ) + def find_test_cases(generator:, test_filepath:, input_filepath:) if (@configurator.project_use_test_preprocessor) - - #redirect to use the preprocessor file if we're doing that sort of thing - pre_test_file = @file_path_utils.form_preprocessed_file_filepath(test_file) - #actually look for the tests using Unity's test runner generator - contents = @file_wrapper.read(pre_test_file) - tests_and_line_numbers = @test_runner_generator.find_tests(contents) - @test_runner_generator.find_setup_and_teardown(contents) + contents = @file_wrapper.read(input_filepath) + tests_and_line_numbers = generator.find_tests(contents) + generator.find_setup_and_teardown(contents) #look up the line numbers in the original file - source_lines = @file_wrapper.read(test_file).split("\n") + source_lines = @file_wrapper.read(test_filepath).split("\n") source_index = 0; tests_and_line_numbers.size.times do |i| source_lines[source_index..-1].each_with_index do |line, index| @@ -32,27 +29,26 @@ def find_test_cases(test_file) end end else - #Just look for the tests using Unity's test runner generator - contents = @file_wrapper.read(test_file) - tests_and_line_numbers = @test_runner_generator.find_tests(contents) - @test_runner_generator.find_setup_and_teardown(contents) + # Just look for the tests using Unity's test runner generator + contents = @file_wrapper.read(test_filepath) + tests_and_line_numbers = generator.find_tests(contents) + generator.find_setup_and_teardown(contents) end return tests_and_line_numbers end - def generate(module_name, runner_filepath, test_cases, mock_list, test_file_includes=[]) - require 'generate_test_runner.rb' - + def generate(generator:, module_name:, runner_filepath:, test_cases:, mock_list:, test_file_includes:[]) header_extension = @configurator.extension_header - #actually build the test runner using Unity's test runner generator - #(there is no need to use preprocessor here because we've already looked up test cases and are passing them in here) - @test_runner_generator ||= UnityTestRunnerGenerator.new( @configurator.get_runner_config ) - @test_runner_generator.generate( module_name, - runner_filepath, - test_cases, - mock_list.map{|f| File.basename(f,'.*')+header_extension}, - test_file_includes.map{|f| File.basename(f,'.*')+header_extension}) + # Actually build the test runner using Unity's test runner generator. + # (There is no need to use preprocessor here because we've already looked up test cases and are passing them in here.) + generator.generate( + module_name, + runner_filepath, + test_cases, + mock_list.map{ |mock| mock + header_extension }, + test_file_includes.map{|f| File.basename(f,'.*') + header_extension} + ) end end diff --git a/tools/vendor/ceedling/lib/ceedling/include_pathinator.rb b/tools/vendor/ceedling/lib/ceedling/include_pathinator.rb new file mode 100644 index 00000000..70b3cc12 --- /dev/null +++ b/tools/vendor/ceedling/lib/ceedling/include_pathinator.rb @@ -0,0 +1,52 @@ + +require 'pathname' + +class IncludePathinator + + constructor :configurator, :test_context_extractor, :streaminator, :file_wrapper + + def setup + # TODO: When Ceedling's base project path handling is resolved, update this value to automatically + # modify TEST_INCLUDE_PATH() locations relative to the working directory or project file location + # @base_path = '.' + + # Alias for brevity + @extractor = @test_context_extractor + end + + def validate_test_directive_paths + @extractor.inspect_include_paths do |test_filepath, include_paths| + include_paths.each do |path| + + # TODO: When Ceedling's base project path handling is resolved, enable this path redefinition + # path = File.join( @base_path, path ) + unless @file_wrapper.exist?(path) + @streaminator.stderr_puts("'#{path}' specified by #{UNITY_TEST_INCLUDE_PATH}() within #{test_filepath} not found", Verbosity::NORMAL) + raise + end + end + end + end + + def augment_environment_header_files + # Get existing, possibly minimal header file collection + headers = @configurator.collection_all_headers + + # Get all paths specified by TEST_INCLUDE_PATH() directive in test files + directive_paths = @extractor.lookup_all_include_paths + + # Add to collection of headers (Rake FileList) with directive paths and shallow wildcard matching on header file extension + headers += @file_wrapper.instantiate_file_list( directive_paths.map { |path| File.join(path, '*' + EXTENSION_HEADER) } ) + + headers.uniq! + + @configurator.redefine_element(:collection_all_headers, headers) + end + + def lookup_test_directive_include_paths(filepath) + # TODO: When Ceedling's base project path handling is resolved, enable this path redefinition + # return @extractor.lookup_include_paths_list(filepath).map { |path| File.join( @base_path, path) } + return @extractor.lookup_include_paths_list(filepath) + end + +end diff --git a/tools/vendor/ceedling/lib/ceedling/objects.yml b/tools/vendor/ceedling/lib/ceedling/objects.yml index 43bbc066..7114a53f 100644 --- a/tools/vendor/ceedling/lib/ceedling/objects.yml +++ b/tools/vendor/ceedling/lib/ceedling/objects.yml @@ -11,8 +11,6 @@ yaml_wrapper: system_wrapper: -cmock_builder: - reportinator: rake_utils: @@ -38,6 +36,16 @@ project_file_loader: - system_wrapper - file_wrapper +unity_utils: + compose: + - configurator + +debugger_utils: + compose: + - configurator + - tool_executor + - unity_utils + project_config_manager: compose: - cacheinator @@ -62,6 +70,7 @@ tool_executor: - configurator - tool_executor_helper - streaminator + - verbosinator - system_wrapper tool_executor_helper: @@ -75,7 +84,6 @@ configurator: - configurator_setup - configurator_plugins - configurator_builder - - cmock_builder - yaml_wrapper - system_wrapper @@ -163,39 +171,61 @@ file_finder: file_finder_helper: compose: streaminator -test_includes_extractor: +test_context_extractor: compose: - configurator - - yaml_wrapper + - file_wrapper + +include_pathinator: + compose: + - configurator + - test_context_extractor + - streaminator - file_wrapper task_invoker: compose: - dependinator + - build_batchinator - rake_utils - rake_wrapper - project_config_manager +config_matchinator: + compose: + - configurator + - streaminator + flaginator: compose: - configurator + - streaminator + - config_matchinator + +defineinator: + compose: + - configurator + - streaminator + - config_matchinator generator: compose: - configurator - generator_helper - preprocessinator - - cmock_builder + - generator_mocks - generator_test_runner - generator_test_results - - flaginator - - test_includes_extractor + - test_context_extractor - tool_executor - file_finder - file_path_utils + - reportinator - streaminator - plugin_manager - file_wrapper + - unity_utils + - debugger_utils generator_helper: compose: @@ -206,12 +236,17 @@ generator_test_results: - configurator - generator_test_results_sanity_checker - yaml_wrapper + - debugger_utils generator_test_results_sanity_checker: compose: - configurator - streaminator +generator_mocks: + compose: + - configurator + generator_test_runner: compose: - configurator @@ -222,72 +257,85 @@ dependinator: compose: - configurator - project_config_manager - - test_includes_extractor + - test_context_extractor - file_path_utils - rake_wrapper - file_wrapper preprocessinator: compose: - - preprocessinator_helper - preprocessinator_includes_handler - preprocessinator_file_handler - task_invoker + - file_finder - file_path_utils + - file_wrapper - yaml_wrapper - project_config_manager - configurator - -preprocessinator_helper: - compose: - - configurator - - test_includes_extractor - - task_invoker - - file_finder - - file_path_utils + - test_context_extractor + - streaminator + - reportinator + - rake_wrapper preprocessinator_includes_handler: compose: - configurator - tool_executor - - task_invoker - - file_path_utils + - test_context_extractor - yaml_wrapper - - file_wrapper - - file_finder + - streaminator + - reportinator preprocessinator_file_handler: compose: - preprocessinator_extractor - configurator + - flaginator - tool_executor - file_path_utils - file_wrapper + - streaminator preprocessinator_extractor: +build_batchinator: + compose: + - configurator + - streaminator + - reportinator + + test_invoker: compose: - configurator - test_invoker_helper - plugin_manager + - build_batchinator - streaminator - preprocessinator - task_invoker - - dependinator - - project_config_manager - build_invoker_utils + - generator + - test_context_extractor - file_path_utils - file_wrapper + - verbosinator test_invoker_helper: compose: - configurator + - streaminator + - build_batchinator - task_invoker - - test_includes_extractor + - test_context_extractor + - include_pathinator + - defineinator + - flaginator - file_finder - file_path_utils - file_wrapper + - generator release_invoker: compose: diff --git a/tools/vendor/ceedling/lib/ceedling/par_map.rb b/tools/vendor/ceedling/lib/ceedling/par_map.rb deleted file mode 100644 index 98198a2c..00000000 --- a/tools/vendor/ceedling/lib/ceedling/par_map.rb +++ /dev/null @@ -1,19 +0,0 @@ - - -def par_map(n, things, &block) - queue = Queue.new - things.each { |thing| queue << thing } - threads = (1..n).collect do - Thread.new do - begin - while true - yield queue.pop(true) - end - rescue ThreadError - - end - end - end - threads.each { |t| t.join } -end - diff --git a/tools/vendor/ceedling/lib/ceedling/plugin_builder.rb b/tools/vendor/ceedling/lib/ceedling/plugin_builder.rb index 1269141f..8d553046 100644 --- a/tools/vendor/ceedling/lib/ceedling/plugin_builder.rb +++ b/tools/vendor/ceedling/lib/ceedling/plugin_builder.rb @@ -1,4 +1,5 @@ require 'ceedling/plugin' +require 'ceedling/yaml_wrapper' class PluginBuilder @@ -11,7 +12,8 @@ def construct_plugin(plugin_name, object_map_yaml, system_objects) @system_objects = system_objects if object_map_yaml - @object_map = YAML.load(object_map_yaml) + ym = YamlMapper.new + @object_map = ym.load_string(object_map_yaml) @object_map.each_key do |obj| construct_object(obj) end diff --git a/tools/vendor/ceedling/lib/ceedling/plugin_reportinator.rb b/tools/vendor/ceedling/lib/ceedling/plugin_reportinator.rb index 8d83727b..f6fccded 100644 --- a/tools/vendor/ceedling/lib/ceedling/plugin_reportinator.rb +++ b/tools/vendor/ceedling/lib/ceedling/plugin_reportinator.rb @@ -24,7 +24,10 @@ def generate_banner(message) return @reportinator.generate_banner(message) end - + def generate_heading(message) + return @reportinator.generate_heading(message) + end + def assemble_test_results(results_list, options={:boom => false}) aggregated_results = get_results_structure diff --git a/tools/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb b/tools/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb index 322a530b..ea3a9dcb 100644 --- a/tools/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb +++ b/tools/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb @@ -44,7 +44,7 @@ def process_results(aggregate_results, results) def run_report(stream, template, hash, verbosity) - output = ERB.new(template, 0, "%<>") + output = ERB.new(template, trim_mode: "%<>") @streaminator.stream_puts(stream, output.result(binding()), verbosity) end diff --git a/tools/vendor/ceedling/lib/ceedling/preprocessinator.rb b/tools/vendor/ceedling/lib/ceedling/preprocessinator.rb index 52d82ca2..36525508 100644 --- a/tools/vendor/ceedling/lib/ceedling/preprocessinator.rb +++ b/tools/vendor/ceedling/lib/ceedling/preprocessinator.rb @@ -1,56 +1,153 @@ class Preprocessinator - constructor :preprocessinator_helper, :preprocessinator_includes_handler, :preprocessinator_file_handler, :task_invoker, :file_path_utils, :yaml_wrapper, :project_config_manager, :configurator + constructor :preprocessinator_includes_handler, + :preprocessinator_file_handler, + :task_invoker, + :file_finder, + :file_path_utils, + :file_wrapper, + :yaml_wrapper, + :project_config_manager, + :configurator, + :test_context_extractor, + :streaminator, + :reportinator, + :rake_wrapper def setup - # fashion ourselves callbacks @preprocessinator_helper can use - @preprocess_includes_proc = Proc.new { |filepath| self.preprocess_shallow_includes(filepath) } - @preprocess_mock_file_proc = Proc.new { |filepath| self.preprocess_file(filepath) } - @preprocess_test_file_directives_proc = Proc.new { |filepath| self.preprocess_file_directives(filepath) } - @preprocess_test_file_proc = Proc.new { |filepath| self.preprocess_file(filepath) } + # Aliases + @includes_handler = @preprocessinator_includes_handler + @file_handler = @preprocessinator_file_handler end - def preprocess_shallow_source_includes(test) - @preprocessinator_helper.preprocess_source_includes(test) + def extract_test_build_directives(filepath:) + # Parse file in Ruby to extract build directives + msg = @reportinator.generate_progress( "Parsing #{File.basename(filepath)}" ) + @streaminator.stdout_puts( msg, Verbosity::NORMAL ) + @test_context_extractor.collect_build_directives( filepath ) end - def preprocess_test_and_invoke_test_mocks(test) - @preprocessinator_helper.preprocess_includes(test, @preprocess_includes_proc) + def extract_testing_context(filepath:, test:, flags:, include_paths:, defines:) + if (not @configurator.project_use_test_preprocessor) + # Parse file in Ruby to extract testing details (e.g. header files, mocks, etc.) + msg = @reportinator.generate_progress( "Parsing & processing #include statements within #{File.basename(filepath)}" ) + @streaminator.stdout_puts( msg, Verbosity::NORMAL ) + @test_context_extractor.collect_includes( filepath ) + else + # Run test file through preprocessor to parse out include statements and then collect header files, mocks, etc. + includes = preprocess_includes( + filepath: filepath, + test: test, + flags: flags, + include_paths: include_paths, + defines: defines) + + msg = @reportinator.generate_progress( "Processing #include statements for #{File.basename(filepath)}" ) + @streaminator.stdout_puts( msg, Verbosity::NORMAL ) + + @test_context_extractor.ingest_includes( filepath, includes ) + end + end - mocks_list = @preprocessinator_helper.assemble_mocks_list(test) + def preprocess_header_file(filepath:, test:, flags:, include_paths:, defines:) + # Extract shallow includes & print status message + includes = preprocess_file_common( + filepath: filepath, + test: test, + flags: flags, + include_paths: include_paths, + defines: defines + ) + + # Run file through preprocessor & further process result + return @file_handler.preprocess_header_file( + filepath: filepath, + subdir: test, + includes: includes, + flags: flags, + include_paths: include_paths, + defines: defines + ) + end - @project_config_manager.process_test_defines_change(mocks_list) + def preprocess_test_file(filepath:, test:, flags:, include_paths:, defines:) + # Extract shallow includes & print status message + includes = preprocess_file_common( + filepath: filepath, + test: test, + flags: flags, + include_paths: include_paths, + defines: defines + ) + + # Run file through preprocessor & further process result + return @file_handler.preprocess_test_file( + filepath: filepath, + subdir: test, + includes: includes, + flags: flags, + include_paths: include_paths, + defines: defines + ) + end - @preprocessinator_helper.preprocess_mockable_headers(mocks_list, @preprocess_mock_file_proc) + def preprocess_file_directives(filepath) + @includes_handler.invoke_shallow_includes_list( filepath ) + @file_handler.preprocess_file_directives( filepath, + @yaml_wrapper.load( @file_path_utils.form_preprocessed_includes_list_filepath( filepath ) ) ) + end - @task_invoker.invoke_test_mocks(mocks_list) + ### Private ### + private - if (@configurator.project_use_preprocessor_directives) - @preprocessinator_helper.preprocess_test_file(test, @preprocess_test_file_directives_proc) - else - @preprocessinator_helper.preprocess_test_file(test, @preprocess_test_file_proc) - end + def preprocess_file_common(filepath:, test:, flags:, include_paths:, defines:) + msg = @reportinator.generate_module_progress( + operation: "Preprocessing", + module_name: test, + filename: File.basename(filepath) + ) - return mocks_list - end + @streaminator.stdout_puts(msg, Verbosity::NORMAL) - def preprocess_shallow_includes(filepath) - includes = @preprocessinator_includes_handler.extract_includes(filepath) + # Extract includes + includes = preprocess_includes( + filepath: filepath, + test: test, + flags: flags, + include_paths: include_paths, + defines: defines) - @preprocessinator_includes_handler.write_shallow_includes_list( - @file_path_utils.form_preprocessed_includes_list_filepath(filepath), includes) + return includes end - def preprocess_file(filepath) - @preprocessinator_includes_handler.invoke_shallow_includes_list(filepath) - @preprocessinator_file_handler.preprocess_file( filepath, @yaml_wrapper.load(@file_path_utils.form_preprocessed_includes_list_filepath(filepath)) ) - end + def preprocess_includes(filepath:, test:, flags:, include_paths:, defines:) + includes_list_filepath = @file_path_utils.form_preprocessed_includes_list_filepath( filepath, test ) - def preprocess_file_directives(filepath) - @preprocessinator_includes_handler.invoke_shallow_includes_list( filepath ) - @preprocessinator_file_handler.preprocess_file_directives( filepath, - @yaml_wrapper.load( @file_path_utils.form_preprocessed_includes_list_filepath( filepath ) ) ) + includes = [] + + if @file_wrapper.newer?(includes_list_filepath, filepath) + msg = @reportinator.generate_module_progress( + operation: "Loading #include statement listing file for", + module_name: test, + filename: File.basename(filepath) + ) + @streaminator.stdout_puts( msg, Verbosity::NORMAL ) + includes = @yaml_wrapper.load(includes_list_filepath) + else + includes = @includes_handler.extract_includes( + filepath: filepath, + test: test, + flags: flags, + include_paths: include_paths, + defines: defines + ) + + @includes_handler.write_includes_list(includes_list_filepath, includes) + end + + return includes end + end diff --git a/tools/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb b/tools/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb index 978fa0d0..bb810374 100644 --- a/tools/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb +++ b/tools/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb @@ -1,27 +1,121 @@ - class PreprocessinatorFileHandler - constructor :preprocessinator_extractor, :configurator, :tool_executor, :file_path_utils, :file_wrapper + constructor :preprocessinator_extractor, :configurator, :flaginator, :tool_executor, :file_path_utils, :file_wrapper, :streaminator + def preprocess_header_file(filepath:, subdir:, includes:, flags:, include_paths:, defines:) + preprocessed_filepath = @file_path_utils.form_preprocessed_file_filepath( filepath, subdir ) - def preprocess_file(filepath, includes) - preprocessed_filepath = @file_path_utils.form_preprocessed_file_filepath(filepath) + filename = File.basename(filepath) - command = @tool_executor.build_command_line(@configurator.tools_test_file_preprocessor, [], filepath, preprocessed_filepath) - @tool_executor.exec(command[:line], command[:options]) + command = @tool_executor.build_command_line( + @configurator.tools_test_file_preprocessor, + flags, + filepath, + preprocessed_filepath, + defines, + include_paths + ) + + @tool_executor.exec( command[:line], command[:options] ) - contents = @preprocessinator_extractor.extract_base_file_from_preprocessed_expansion(preprocessed_filepath) + @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) - includes.each{|include| contents.unshift("#include \"#{include}\"")} + contents = @preprocessinator_extractor.extract_base_file_from_preprocessed_expansion( preprocessed_filepath ) - @file_wrapper.write(preprocessed_filepath, contents.join("\n")) + # Reinsert #include statements into stripped down file + # ---------------------------------------------------- + # Notes: + # - Preprocessing expands #includes, and we strip out those expansions. + # - #include order can be important. Iterating with unshift() inverts the order. So, we use revese(). + includes.reverse.each{ |include| contents.unshift( "#include \"#{include}\"" ) } + + # Add #include guards for header files + # Note: These aren't truly needed as preprocessed header files are only ingested by CMock. + # They're created for sake of completeness and just in case... + # ---------------------------------------------------- + # abc-XYZ.h --> _ABC_XYZ_H_ + guardname = '_' + filename.gsub(/\W/, '_').upcase + '_' + + forward_guards = [ + "#ifndef #{guardname} // Ceedling-generated guard", + "#define #{guardname}", + '' + ] + + # Add guards to beginning of file contents + contents = forward_guards + contents + contents += ["#endif // #{guardname}", ''] # Rear guard + + # Insert Ceedling notice + # ---------------------------------------------------- + comment = "// CEEDLING NOTICE: This generated file only to be consumed by CMock" + contents = [comment, ''] + contents + + # Write file, collapsing any repeated blank lines + # ---------------------------------------------------- + contents = contents.join("\n") + contents.gsub!( /(\h*\n){3,}/, "\n\n" ) + + @file_wrapper.write( preprocessed_filepath, contents ) + + return preprocessed_filepath end + def preprocess_test_file(filepath:, subdir:, includes:, flags:, include_paths:, defines:) + preprocessed_filepath = @file_path_utils.form_preprocessed_file_filepath( filepath, subdir ) + + command = @tool_executor.build_command_line( + @configurator.tools_test_file_preprocessor, + flags, + filepath, + preprocessed_filepath, + defines, + include_paths + ) + + @tool_executor.exec( command[:line], command[:options] ) + + @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) + + contents = @preprocessinator_extractor.extract_base_file_from_preprocessed_expansion( preprocessed_filepath ) + + # Reinsert #include statements into stripped down file + # ---------------------------------------------------- + # Notes: + # - Preprocessing expands #includes, and we strip out those expansions. + # - #include order can be important. Iterating with unshift() inverts the order. So, we use revese(). + includes.reverse.each{ |include| contents.unshift( "#include \"#{include}\"" ) } + + # Insert Ceedling notice + # ---------------------------------------------------- + comment = "// CEEDLING NOTICE: This generated file only to be consumed for test runner creation" + contents = [comment, ''] + contents + + # Write file, doing some prettyifying along the way + # ---------------------------------------------------- + contents = contents.join("\n") + contents.gsub!( /^\s*;/, '' ) # Drop blank lines with semicolons left over from macro expansion + trailing semicolon + contents.gsub!( /\)\s+\{/, ")\n{" ) # Collapse any unnecessary white space between closing argument paren and opening function bracket + contents.gsub!( /\{(\n){2,}/, "{\n" ) # Collapse any unnecessary white space between opening function bracket and code + contents.gsub!( /(\n){2,}\}/, "\n}" ) # Collapse any unnecessary white space between code and closing function bracket + contents.gsub!( /(\h*\n){3,}/, "\n\n" ) # Collapse repeated blank lines + + @file_wrapper.write( preprocessed_filepath, contents ) + + return preprocessed_filepath + end + + def preprocess_file_directives(filepath, includes) preprocessed_filepath = @file_path_utils.form_preprocessed_file_filepath(filepath) - command = @tool_executor.build_command_line(@configurator.tools_test_file_preprocessor_directives, [], filepath, preprocessed_filepath) + command = + @tool_executor.build_command_line( @configurator.tools_test_file_preprocessor_directives, + @flaginator.flag_down( OPERATION_COMPILE_SYM, TEST_SYM, filepath ), + filepath, + preprocessed_filepath) + @tool_executor.exec(command[:line], command[:options]) contents = @preprocessinator_extractor.extract_base_file_from_preprocessed_directives(preprocessed_filepath) diff --git a/tools/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb b/tools/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb deleted file mode 100644 index 4bbda67f..00000000 --- a/tools/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb +++ /dev/null @@ -1,50 +0,0 @@ - - -class PreprocessinatorHelper - - constructor :configurator, :test_includes_extractor, :task_invoker, :file_finder, :file_path_utils - - - def preprocess_includes(test, preprocess_includes_proc) - if (@configurator.project_use_test_preprocessor) - preprocessed_includes_list = @file_path_utils.form_preprocessed_includes_list_filepath(test) - preprocess_includes_proc.call( @file_finder.find_test_from_file_path(preprocessed_includes_list) ) - @test_includes_extractor.parse_includes_list(preprocessed_includes_list) - else - @test_includes_extractor.parse_test_file(test) - end - end - - def preprocess_source_includes(test) - @test_includes_extractor.parse_test_file_source_include(test) - end - - def assemble_mocks_list(test) - return @file_path_utils.form_mocks_source_filelist( @test_includes_extractor.lookup_raw_mock_list(test) ) - end - - def preprocess_mockable_headers(mock_list, preprocess_file_proc) - if (@configurator.project_use_test_preprocessor) - preprocess_files_smartly( - @file_path_utils.form_preprocessed_mockable_headers_filelist(mock_list), - preprocess_file_proc ) { |file| @file_finder.find_header_file(file) } - end - end - - def preprocess_test_file(test, preprocess_file_proc) - return if (!@configurator.project_use_test_preprocessor) - - preprocess_file_proc.call(test) - end - - private ############################ - - def preprocess_files_smartly(file_list, preprocess_file_proc) - if (@configurator.project_use_deep_dependencies) - @task_invoker.invoke_test_preprocessed_files(file_list) - else - file_list.each { |file| preprocess_file_proc.call( yield(file) ) } - end - end - -end diff --git a/tools/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb b/tools/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb index 8b89c0b3..747b402a 100644 --- a/tools/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb +++ b/tools/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb @@ -2,188 +2,374 @@ class PreprocessinatorIncludesHandler - constructor :configurator, :tool_executor, :task_invoker, :file_path_utils, :yaml_wrapper, :file_wrapper, :file_finder - @@makefile_cache = {} + constructor :configurator, :tool_executor, :test_context_extractor, :yaml_wrapper, :streaminator, :reportinator - # shallow includes: only those headers a source file explicitly includes + ## + ## Includes Extraction Overview + ## ============================ + ## + ## BACKGROUND + ## #include extraction is hard to do. In simple cases a regex approach suffices. Not all the uncommon nested + ## header files, clever macros, and conditional preprocessing statements introduce high complexity. + ## + ## Unfortunately, there's no easily available C parsing tool that provides a simple means to extract the + ## #include statements directly embedded in a given file. Even the gcc preprocessor itself only comes close + ## to providing this information. + ## + ## APPROACH + ## -------- + ## (Full details including fallback options are in the extensive code comments among the methods below.) + ## + ## Sadly, we can't preprocess a file with full search paths and defines and ask for the #include statements + ## embedded in a file. We get far more #includes than we want with no was to discern which are at the depth + ## of the file being processed. + ## + ## Instead, we try our best to use some educated guessing to get as close as possible to the desired list. + ## + ## I. Try to extract shallow defines with no crawling out into other header files. This gives us a + ## reference point on possible directly included files. The results may be incomplete, though. They + ## also may mistakenly list #includes that should not be in the list--because of #ifndef defaults or + ## because of system headers or #include <...> statements and differences among gcc implementations. + ## + ## II. Extract a full list of #includes by spidering out into nested headers and processing all macros, etc. + ## + ## III. Find #includes common to (I) and (II). THe results of (I) should limit the potentially lengthy + ## results of (II). The complete and accurate list of (II) should cut out any mistaken entries in (I). + ## + ## IV. I–III are not foolproof. This approach should come quite close to an accurate list of shallow + ## includes. Edge cases and gaps will cause trouble. Other Ceedling features should provide the tools + ## to intervene. + ## + + def extract_includes(filepath:, test:, flags:, include_paths:, defines:) + msg = @reportinator.generate_module_progress( + operation: "Extracting #include statements via preprocessor from", + module_name: test, + filename: File.basename(filepath) + ) + @streaminator.stdout_puts(msg, Verbosity::NORMAL) + + # Extract shallow includes with preprocessor and fallback regex + shallow = extract_shallow_includes( + test: test, + filepath: filepath, + flags: flags, + defines: defines + ) + + # Extract nested includes but optionally act in fallback mode + nested = extract_nested_includes( + filepath: filepath, + include_paths: include_paths, + flags: flags, + defines: defines, + # If no shallow results, fall back to only depth 1 results of nested discovery + shallow: shallow.empty? + ) - def invoke_shallow_includes_list(filepath) - @task_invoker.invoke_test_shallow_include_lists( [@file_path_utils.form_preprocessed_includes_list_filepath(filepath)] ) + # Combine shallow and nested include knowledge of mocks + mocks = combine_mocks(shallow, nested) + + # Redefine shallow and nested results without any mocks + shallow = remove_mocks( shallow ) + nested = remove_mocks( nested ) + + # Return + # - Includes common to shallow and nested results, with paths from nested + # - Add mocks back in (may be empty if mocking not enabled) + return common_includes(shallow:shallow, nested:nested) + mocks end - ## - # Ask the preprocessor for a make-style dependency rule of only the headers - # the source file immediately includes. - # - # === Arguments - # +filepath+ _String_:: Path to the test file to process. - # - # === Return - # _String_:: The text of the dependency rule generated by the preprocessor. - def form_shallow_dependencies_rule(filepath) - if @@makefile_cache.has_key?(filepath) - return @@makefile_cache[filepath] - end - # change filename (prefix of '_') to prevent preprocessor from finding - # include files in temp directory containing file it's scanning - temp_filepath = @file_path_utils.form_temp_path(filepath, '_') - - # read the file and replace all include statements with a decorated version - # (decorating the names creates file names that don't exist, thus preventing - # the preprocessor from snaking out and discovering the entire include path - # that winds through the code). The decorated filenames indicate files that - # are included directly by the test file. - contents = @file_wrapper.read(filepath) - - if !contents.valid_encoding? - contents = contents.encode("UTF-16be", :invalid=>:replace, :replace=>"?").encode('UTF-8') + # Write to disk a yaml representation of a list of includes + def write_includes_list(filepath, list) + @yaml_wrapper.dump(filepath, list) + end + + ### Private ### + private + + def extract_shallow_includes(test:, filepath:, flags:, defines:) + # Shallow includes extraction, first attempt with preprocessor + success, shallow = + extract_shallow_includes_preprocessor( + test: test, + filepath: filepath, + flags: flags, + defines: defines + ) + + # Shallow includes extraction, second attempt with file read + regex + if not success + shallow = extract_shallow_includes_regex( + test: test, + filepath: filepath, + flags: flags, + defines: defines + ) end - contents.gsub!( /^\s*#include\s+[\"<]\s*(\S+)\s*[\">]/, "#include \"\\1\"\n#include \"@@@@\\1\"" ) - contents.gsub!( /^\s*TEST_FILE\(\s*\"\s*(\S+)\s*\"\s*\)/, "#include \"\\1\"\n#include \"@@@@\\1\"") - @file_wrapper.write( temp_filepath, contents ) + return shallow + end + + def extract_shallow_includes_preprocessor(test:, filepath:, flags:, defines:) + ## + ## Preprocessor Make Rule Handling + ## =============================== + ## + ## Creation: + ## - This output is created with the -MM -MG -MP command line options. + ## - No search paths are used towards extracting only the #include statements of the file. + ## The intent is to minimize the list of .h -> .c module matches to, in turn, minimize + ## unnecessary compilation when extracting includes from a test file. + ## - Note: This approach can have gaps with complex macros / conditional statements. + ## Gaps can be minimized with proper defines in the project file. + ## However, needed / complex macros located in other header files can still gum + ## up the works. + ## + ## Format: + ## - First line is .o file followed by colon and dependencies (on one or more lines). + ## - "Phony" make rules follow that conveniently list each #include, one per line. + ## + ## Notes: + ## - Many errors can occur but may not necessarily prevent usable results. + ## - A file with no includes will create the first line with self-referential .h file path. + ## - Make rule formation assumes any files not found in a search path will be generated. + ## - Since we're not using search paths, the preprocessor largely assumes all #include + ## files are generated (and include no paths). + ## - The exception is #include files that exist in the same directory as the file + ## being processed. + ## + ## Approach: + ## 1. Disable exceptions for tool execution as errors are likely. + ## - We may still have usable output. + ## - We do not want to stop execution on fatal error; instead use a fallback method. + ## 2. The only true error is no make rule present--check for this first. + ## - A make rule may be present but not depedencies if the file has no #includes. + ## 3. Extract includes from "phony" make rules that follow opening rule line. + ## - These may be .h or .c files. + ## + ## Example output follows + ## ----------------------------------------------------------------------------------------- + ## os.o: ../../src/app/task/os/os.h fstd_types.h FreeRTOS.h queue.h + ## fstd_types.h: + ## FreeRTOS.h: + ## queue.h: + ## ../../src/app/task/os/os.h:72:21: error: no include path in which to search for stdbool.h + ## 72 | #include + ## | ^ + ## ../../src/app/task/os/os.h:73:20: error: no include path in which to search for stdint.h + ## 73 | #include + ## | ^ + ## - # extract the make-style dependency rule telling the preprocessor to - # ignore the fact that it can't find the included files - command = @tool_executor.build_command_line(@configurator.tools_test_includes_preprocessor, [], temp_filepath) + # Matcher for the first line of the make rule output + make_rule_matcher = /^\S+\.o:\s+.+$/ # .o: + + # Matcher for the “phony“ make rule output lines for each #include dependency (.h, .c, etc.) + # Capture file name before the colon + include_matcher = /^(\S+\.\S+):\s*$/ # .: + + command = + @tool_executor.build_command_line( + @configurator.tools_test_shallow_includes_preprocessor, + flags, + filepath, + defines + ) + + @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) + + command[:options][:boom] = false # Assume errors and do not raise an exception shell_result = @tool_executor.exec(command[:line], command[:options]) - @@makefile_cache[filepath] = shell_result[:output] - return shell_result[:output] - end + make_rules = shell_result[:output] - ## - # Extract the headers that are directly included by a source file using the - # provided, annotated Make dependency rule. - # - # === Arguments - # +filepath+ _String_:: C source or header file to extract includes for. - # - # === Return - # _Array_ of _String_:: Array of the direct dependencies for the source file. - def extract_includes(filepath) - to_process = [filepath] - ignore_list = [] - list = [] - all_mocks = [] - - include_paths = @configurator.project_config_hash[:collection_paths_include] - include_paths = [] if include_paths.nil? - include_paths.map! {|path| File.expand_path(path)} - - while to_process.length > 0 - target = to_process.shift() - ignore_list << target - new_deps, new_to_process, all_mocks = extract_includes_helper(target, include_paths, ignore_list, all_mocks) - list += new_deps - to_process += new_to_process - if !@configurator.project_config_hash[:project_auto_link_deep_dependencies] - break - else - list = list.uniq() - to_process = to_process.uniq() - end + # Do not check exit code for success. In some error conditions we still get usable output. + # Look for the first line of the make rule output. + if not make_rules =~ make_rule_matcher + msg = "Preprocessor #include extraction failed: #{shell_result[:output]}" + @streaminator.stdout_puts(msg, Verbosity::DEBUG) + + return false, [] end - return list + includes = [] + + # Extract the #include dependencies from the "phony" make rules, one per line + includes = make_rules.scan( include_matcher ) + includes.flatten! # Regex results can be nested arrays becuase of paren captures + + return true, includes.uniq end - def extract_includes_helper(filepath, include_paths, ignore_list, mocks) - # Extract the dependencies from the make rule - make_rule = self.form_shallow_dependencies_rule(filepath) - target_file = make_rule.split[0].gsub(':', '').gsub('\\','/') - base = File.basename(target_file, File.extname(target_file)) - make_rule_dependencies = make_rule.gsub(/.*\b#{Regexp.escape(base)}\S*/, '').gsub(/\\$/, '') - - # Extract the headers dependencies from the make rule - hdr_ext = @configurator.extension_header - headers_dependencies = make_rule_dependencies.split.find_all {|path| path.end_with?(hdr_ext) }.uniq - headers_dependencies.map! {|hdr| hdr.gsub('\\','/') } - full_path_headers_dependencies = extract_full_path_dependencies(headers_dependencies) - - # Extract the sources dependencies from the make rule - src_ext = @configurator.extension_source - sources_dependencies = make_rule_dependencies.split.find_all {|path| path.end_with?(src_ext) }.uniq - sources_dependencies.map! {|src| src.gsub('\\','/') } - full_path_sources_dependencies = extract_full_path_dependencies(sources_dependencies) - - list = full_path_headers_dependencies + full_path_sources_dependencies - - mock_prefix = @configurator.project_config_hash[:cmock_mock_prefix] - # Creating list of mocks - mocks += full_path_headers_dependencies.find_all do |header| - File.basename(header) =~ /^#{mock_prefix}.*$/ - end.compact - - # ignore real file when both mock and real file exist - mocks.each do |mock| - list.each do |filename| - if File.basename(filename) == File.basename(mock).sub(mock_prefix, '') - ignore_list << filename - end - end - end.compact + def extract_shallow_includes_regex(test:, filepath:, flags:, defines:) + msg = @reportinator.generate_module_progress( + operation: "Using fallback regex #include extraction for", + module_name: test, + filename: File.basename( filepath ) + ) + @streaminator.stdout_puts(msg, Verbosity::NORMAL) + + # Use abilities of @test_context_extractor to extract the #includes via regex on the file + return @test_context_extractor.scan_includes( filepath ) + end + + def extract_nested_includes(filepath:, include_paths:, flags:, defines:, shallow:false) + ## + ## Preprocessor Header File Listing Handling + ## ========================================= + ## + ## Creation: + ## - This output is created with the -MM -MG -H command line options. + ## - -MM -MG generates unused make rule that significantly reduces overall output. + ## - -H creates the header file output listing we actually want. + ## - Search paths are provided towards fully preprocessing all macros / conditionals and + ## symbols. (This produces a rich list of #includes far greater than we need.) + ## + ## Format (ignoring throwaway make rule): + ## - Each included filepath is listed per line. + ## - The depth of the #include nesting is signified by precending '.'s. + ## - Files directly #include'd in the file being preprocessed are at depth 1 ('.') + ## + ## Notes: + ## - Because search paths and defines are provided, error-free executiion is assumed. + ## If the preprocessor fails, issues exist that will cause full compilation to fail. + ## - Unfortuantely, because of ordering and nesting effects, a file directly #include'd may + ## not be listed at depth 1 ('.'). Instead, it may end up listed at greater depth beneath + ## another #include'd file if both files reference it. That is, there is no way + ## to give the preprocessor full context and ask for only the files directly + ## #include'd in the file being processed. + ## - The preprocessor outputs the -H #include listing to STDERR. We must redirect to + ## STDOOUT in order to access the full output. + ## - Since we're using search paths, all #included files will include paths. Depending on + ## circumstances, this could yield a list with generated mocks with full build paths. + ## + ## Approach: + ## - Match on each listing line a filepath preceeded by its depth + ## - One mode of using this preprocessor approach is as a fallback / double-check method + ## if the simpler, earler shallow preprocessing produces no #include results. When used + ## this way we match only #include'd files at depth 1 ('.'), hoping we extract an + ## appropriate, usable list of #includes. + ## + ## Example output follows + ## ----------------------------------------------------------------------------------------- + ## . build/vendor/unity/src/unity.h + ## .. build/vendor/unity/src/unity_internals.h + ## . src/Types.h + ## . src/Model.h + ## . src/TimerModel.h + ## .. src/Testing.h + ## TestModel.o: test/TestModel.c build/vendor/unity/src/unity.h \ + ## build/vendor/unity/src/unity_internals.h setjmp.h math.h stddef.h \ + ## stdint.h limits.h stdio.h src/Types.h src/Model.h src/TimerModel.h \ + ## src/Testing.h MockTaskScheduler.h MockTemperatureFilter.h + ## + + command = + @tool_executor.build_command_line( + @configurator.tools_test_nested_includes_preprocessor, + flags, + filepath, + include_paths, + defines + ) - # Filtering list of final includes to only include mocks and anything that is NOT in the ignore_list - list = list.select do |item| - mocks.include? item or !(ignore_list.any? { |ignore_item| !item.match(/^(.*\/)?#{Regexp.escape(ignore_item)}$/).nil? }) + # Redirect -H output to STDERR to STDOUT so we can access it in the execution results + command[:options][:stderr_redirect] = StdErrRedirect::AUTO + + @streaminator.stdout_puts( "Command: #{command}", Verbosity::DEBUG ) + + shell_result = @tool_executor.exec( command[:line], command[:options] ) + + list = shell_result[:output] + + includes = [] + + # Extract entries from #include listing + if shallow + # First level of includes in preprocessor output + includes = list.scan(/^\. (.+$)\s*$/) # . + else + # All levels of includes in preprocessor output + includes = list.scan(/^\.+ (.+$)\s*$/) # ... end - to_process = [] + includes.flatten! # Regex results can be nested arrays becuase of paren captures - if @configurator.project_config_hash[:project_auto_link_deep_dependencies] - # Creating list of headers that should be recursively pre-processed - # Skipping mocks and vendor headers - headers_to_deep_link = full_path_headers_dependencies.select do |hdr| - !(mocks.include? hdr) and (hdr.match(/^(.*\/)(#{VENDORS_FILES.join('|')}) + #{Regexp.escape(hdr_ext)}$/).nil?) - end - headers_to_deep_link.map! {|hdr| File.expand_path(hdr) } - headers_to_deep_link.compact! - - headers_to_deep_link.each do |hdr| - if (ignore_list.none? {|ignore_header| hdr.match(/^(.*\/)?#{Regexp.escape(ignore_header)}$/)} and - include_paths.none? {|include_path| hdr =~ /^#{include_path}\.*/}) - if File.exist?(hdr) - to_process << hdr - src = @file_finder.find_compilation_input_file(hdr, :ignore) - to_process << src if src - end - end - end + return includes.uniq + end + + def combine_mocks(*lists) + # Handle mocks + # - Ensure no build filepaths in mock listings + # - Do not return mocks if mocking is disabled + mocks = [] + + if @configurator.project_use_mocks + # Use some greediness to ensure we get all possible mocks + lists.each { |list| mocks |= extract_mocks( list ) } end - return list, to_process, mocks + return mocks + end + # Return a list of mock .h files with no paths + def extract_mocks(includes) + return includes.select { |include| File.basename(include).start_with?( @configurator.cmock_mock_prefix ) } end - def write_shallow_includes_list(filepath, list) - @yaml_wrapper.dump(filepath, list) + # Return list of includes with any mocks removed + def remove_mocks(includes) + return includes.reject { |include| File.basename(include).start_with?( @configurator.cmock_mock_prefix ) } end - private + # Return includes common in both lists with the full paths of the nested list + def common_includes(shallow:, nested:) + return shallow if nested.empty? + return nested if shallow.empty? + + # Notes: + # - We want to preserve filepaths whenever possible. Other areas of Ceedling use or discard the + # filepath as needed. + # - We generally do not have filepaths in the shallow list--except when the #include is in the + # same directory as the file being processed + + # Approach + # 1. Create hashed lists of shallow and nested for easier matching / deletion + # 2. Iterate through nested hash list and extract to common[] any filepath also in shallow + # 3. For each filepath extracted + # a. Delete it from the nested hash list + # b. Delete the corresponding entry in the shallow hash list + # 4. Iterate remaining nested hash list and extract to common[] and filepath whose base + # filename matches a remaining entry in the shallow hash list + + common = [] - def extract_full_path_dependencies(dependencies) - # Separate the real files form the annotated ones and remove the '@@@@' - annotated_files, real_files = dependencies.partition {|file| file =~ /^@@@@/} - annotated_files.map! {|file| file.gsub('@@@@','') } - # Matching annotated_files values against real_files to ensure that - # annotated_files contain full path entries (as returned by make rule) - annotated_files.map! {|file| real_files.find {|real| !real.match(/^(.*\/)?#{Regexp.escape(file)}$/).nil?}} - annotated_files = annotated_files.compact - - # Find which of our annotated files are "real" dependencies. This is - # intended to weed out dependencies that have been removed due to build - # options defined in the project yaml and/or in the files themselves. - return annotated_files.find_all do |annotated_file| - # find the index of the "real" file that matches the annotated one. - idx = real_files.find_index do |real_file| - real_file =~ /^(.*\/)?#{Regexp.escape(annotated_file)}$/ + # Hash list + _shallow = {} + shallow.each { |item| _shallow[item] = nil } + + # Hash list + _nested = {} + nested.each { |item| _nested[item] = nil } + + # Iterate each _nested entry and extract filepaths with matching filepath in _shallow list + _nested.each_key do |filepath| + if _shallow.has_key?( filepath ) + common << filepath # Copy to common + _shallow.delete(filepath) # Remove matching filepath from _shallow list end - # If we found a real file, delete it from the array and return it, - # otherwise return nil. Since nil is falsy this has the effect of making - # find_all return only the annotated filess for which a real file was - # found/deleted - idx ? real_files.delete_at(idx) : nil - end.compact + end + + # For each mached filepath, remove it from _nested list + common.each { |item| _nested.delete(item) } + + # Find any reamining filepaths whose baseneame matches an entry in _shallow + _nested.each_key do |filepath| + common << filepath if _shallow.has_key?( File.basename(filepath) ) + end + + return common end + end diff --git a/tools/vendor/ceedling/lib/ceedling/project_config_manager.rb b/tools/vendor/ceedling/lib/ceedling/project_config_manager.rb index ed7a73b8..e0f7089f 100644 --- a/tools/vendor/ceedling/lib/ceedling/project_config_manager.rb +++ b/tools/vendor/ceedling/lib/ceedling/project_config_manager.rb @@ -22,14 +22,7 @@ def merge_options(config_hash, option_filepath) config_hash.deep_merge!( @yaml_wrapper.load( option_filepath ) ) end - - def filter_internal_sources(sources) - filtered_sources = sources.clone - filtered_sources.delete_if { |item| item =~ /#{CMOCK_MOCK_PREFIX}.+#{Regexp.escape(EXTENSION_SOURCE)}$/ } - filtered_sources.delete_if { |item| item =~ /#{VENDORS_FILES.map{|source| '\b' + Regexp.escape(source.ext(EXTENSION_SOURCE)) + '\b'}.join('|')}$/ } - return filtered_sources - end - + def process_release_config_change # has project configuration changed since last release build @release_config_changed = @cacheinator.diff_cached_release_config?( @config_hash ) diff --git a/tools/vendor/ceedling/lib/ceedling/rakefile.rb b/tools/vendor/ceedling/lib/ceedling/rakefile.rb index 1bcb8249..583867ee 100644 --- a/tools/vendor/ceedling/lib/ceedling/rakefile.rb +++ b/tools/vendor/ceedling/lib/ceedling/rakefile.rb @@ -18,10 +18,9 @@ require 'diy' require 'constructor' - require 'ceedling/constants' require 'ceedling/target_loader' - +require 'deep_merge' # construct all our objects # ensure load path contains all libraries needed first @@ -46,6 +45,16 @@ @ceedling[:setupinator].do_setup( project_config ) +# Configure Ruby's default reporting for Thread exceptions. +unless @ceedling[:configurator].project_verbosity == Verbosity::DEBUG + # In Ceedling's case thread scenarios will fall into these buckets: + # 1. Jobs shut down cleanly + # 2. Jobs shut down at garbage collected after a build step terminates with an error + # + # Since Ceedling is not a daemon, server app, or something to run continuously, + # we can safely disable forced exception reporting. + Thread.report_on_exception = false +end # tell all our plugins we're about to do something @ceedling[:plugin_manager].pre_build @@ -66,11 +75,6 @@ @ceedling[:cacheinator].cache_test_config( @ceedling[:setupinator].config_hash ) if (@ceedling[:task_invoker].test_invoked?) @ceedling[:cacheinator].cache_release_config( @ceedling[:setupinator].config_hash ) if (@ceedling[:task_invoker].release_invoked?) - # delete all temp files unless we're in debug mode - if (not @ceedling[:configurator].project_debug) - @ceedling[:file_wrapper].rm_f( @ceedling[:file_wrapper].directory_listing( File.join(@ceedling[:configurator].project_temp_path, '*') )) - end - # only perform these final steps if we got here without runtime exceptions or errors if (@ceedling[:system_wrapper].ruby_success) diff --git a/tools/vendor/ceedling/lib/ceedling/release_invoker.rb b/tools/vendor/ceedling/lib/ceedling/release_invoker.rb index 19bbca72..34bb5149 100644 --- a/tools/vendor/ceedling/lib/ceedling/release_invoker.rb +++ b/tools/vendor/ceedling/lib/ceedling/release_invoker.rb @@ -10,9 +10,6 @@ def setup_and_invoke_c_objects( c_files ) objects = @file_path_utils.form_release_build_c_objects_filelist( c_files ) begin - @release_invoker_helper.process_deep_dependencies( @file_path_utils.form_release_dependencies_filelist( c_files ) ) - - @dependinator.enhance_release_file_dependencies( objects ) @task_invoker.invoke_release_objects( objects ) rescue => e @build_invoker_utils.process_exception( e, RELEASE_SYM, false ) @@ -26,7 +23,6 @@ def setup_and_invoke_asm_objects( asm_files ) objects = @file_path_utils.form_release_build_asm_objects_filelist( asm_files ) begin - @dependinator.enhance_release_file_dependencies( objects ) @task_invoker.invoke_release_objects( objects ) rescue => e @build_invoker_utils.process_exception( e, RELEASE_SYM, false ) @@ -36,19 +32,6 @@ def setup_and_invoke_asm_objects( asm_files ) end - def refresh_c_deep_dependencies - return if (not @configurator.project_use_deep_dependencies) - - @file_wrapper.rm_f( - @file_wrapper.directory_listing( - File.join( @configurator.project_release_dependencies_path, '*' + @configurator.extension_dependencies ) ) ) - - @release_invoker_helper.process_deep_dependencies( - @file_path_utils.form_release_dependencies_filelist( - @configurator.collection_all_source ) ) - end - - def artifactinate( *files ) files.flatten.each do |file| @file_wrapper.cp( file, @configurator.project_release_artifacts_path ) if @file_wrapper.exist?( file ) diff --git a/tools/vendor/ceedling/lib/ceedling/reportinator.rb b/tools/vendor/ceedling/lib/ceedling/reportinator.rb index 0f583d06..77761a8c 100644 --- a/tools/vendor/ceedling/lib/ceedling/reportinator.rb +++ b/tools/vendor/ceedling/lib/ceedling/reportinator.rb @@ -23,4 +23,23 @@ def generate_banner(message, width=nil) return "#{'-' * dash_count}\n#{message}\n#{'-' * dash_count}\n" end + def generate_heading(message) + # + # --------- + return "\n#{message}\n#{'-' * message.length}" + end + + def generate_progress(message) + # ... + return "#{message}..." + end + + def generate_module_progress(module_name:, filename:, operation:) + # ..." + + # If filename is the module name, don't add the module label + label = (File.basename(filename).ext('') == module_name.to_s) ? '' : "#{module_name}::" + return generate_progress("#{operation} #{label}#{filename}") + end + end diff --git a/tools/vendor/ceedling/lib/ceedling/rules_cmock.rake b/tools/vendor/ceedling/lib/ceedling/rules_cmock.rake deleted file mode 100644 index 70ddcbc2..00000000 --- a/tools/vendor/ceedling/lib/ceedling/rules_cmock.rake +++ /dev/null @@ -1,9 +0,0 @@ - - -rule(/#{CMOCK_MOCK_PREFIX}[^\/\\]+#{'\\'+EXTENSION_SOURCE}$/ => [ - proc do |task_name| - @ceedling[:file_finder].find_header_input_for_mock_file(task_name) - end - ]) do |mock| - @ceedling[:generator].generate_mock(TEST_SYM, mock.source) -end diff --git a/tools/vendor/ceedling/lib/ceedling/rules_preprocess.rake b/tools/vendor/ceedling/lib/ceedling/rules_preprocess.rake deleted file mode 100644 index c2911127..00000000 --- a/tools/vendor/ceedling/lib/ceedling/rules_preprocess.rake +++ /dev/null @@ -1,26 +0,0 @@ - - -# invocations against this rule should only happen when enhanced dependencies are enabled; -# otherwise, dependency tracking will be too shallow and preprocessed files could intermittently -# fail to be updated when they actually need to be. -rule(/#{PROJECT_TEST_PREPROCESS_FILES_PATH}\/.+/ => [ - proc do |task_name| - @ceedling[:file_finder].find_test_or_source_or_header_file(task_name) - end - ]) do |file| - if (not @ceedling[:configurator].project_use_deep_dependencies) - raise 'ERROR: Ceedling preprocessing rule invoked though neccessary auxiliary dependency support not enabled.' - end - @ceedling[:generator].generate_preprocessed_file(TEST_SYM, file.source) -end - - -# invocations against this rule can always happen as there are no deeper dependencies to consider -rule(/#{PROJECT_TEST_PREPROCESS_INCLUDES_PATH}\/.+/ => [ - proc do |task_name| - @ceedling[:file_finder].find_test_or_source_or_header_file(task_name) - end - ]) do |file| - @ceedling[:generator].generate_shallow_includes_list(TEST_SYM, file.source) -end - diff --git a/tools/vendor/ceedling/lib/ceedling/rules_release.rake b/tools/vendor/ceedling/lib/ceedling/rules_release.rake index 4a583bd6..0bb3b30d 100644 --- a/tools/vendor/ceedling/lib/ceedling/rules_release.rake +++ b/tools/vendor/ceedling/lib/ceedling/rules_release.rake @@ -20,29 +20,36 @@ rule(/#{PROJECT_RELEASE_BUILD_OUTPUT_ASM_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => @ceedling[:file_finder].find_assembly_file(task_name) end ]) do |object| - @ceedling[:generator].generate_object_file( - TOOLS_RELEASE_ASSEMBLER, - OPERATION_ASSEMBLE_SYM, - RELEASE_SYM, - object.source, - object.name ) + @ceedling[:generator].generate_object_file_asm( + tool: TOOLS_RELEASE_ASSEMBLER, + module_name: File.basename(object.source).ext(), # Source filename as module name + context: RELEASE_SYM, + source: object.source, + object: object.name, + search_paths: COLLECTION_PATHS_SOURCE_AND_INCLUDE, + flags: @ceedling[:flaginator].flag_down( context:RELEASE_SYM, operation:OPERATION_ASSEMBLE_SYM ), + defines: @ceedling[:defineinator].defines( context:RELEASE_SYM ), + list: @ceedling[:file_path_utils].form_release_build_c_list_filepath( object.name ), + dependencies: @ceedling[:file_path_utils].form_release_dependencies_filepath( object.name ) ) end end - rule(/#{PROJECT_RELEASE_BUILD_OUTPUT_C_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [ proc do |task_name| @ceedling[:file_finder].find_compilation_input_file(task_name, :error, true) end ]) do |object| - @ceedling[:generator].generate_object_file( - TOOLS_RELEASE_COMPILER, - OPERATION_COMPILE_SYM, - RELEASE_SYM, - object.source, - object.name, - @ceedling[:file_path_utils].form_release_build_c_list_filepath( object.name ), - @ceedling[:file_path_utils].form_release_dependencies_filepath( object.name ) ) + @ceedling[:generator].generate_object_file_c( + tool: TOOLS_RELEASE_COMPILER, + module_name: File.basename(object.source).ext(), # Source filename as module name + context: RELEASE_SYM, + source: object.source, + object: object.name, + search_paths: COLLECTION_PATHS_INCLUDE, + flags: @ceedling[:flaginator].flag_down( context:RELEASE_SYM, operation:OPERATION_COMPILE_SYM ), + defines: @ceedling[:defineinator].defines( context:RELEASE_SYM ), + list: @ceedling[:file_path_utils].form_release_build_c_list_filepath( object.name ), + dependencies: @ceedling[:file_path_utils].form_release_dependencies_filepath( object.name ) ) end @@ -52,10 +59,12 @@ rule(/#{PROJECT_RELEASE_BUILD_TARGET}/) do |bin_file| lib_args = @ceedling[:release_invoker].convert_libraries_to_arguments(libraries) lib_paths = @ceedling[:release_invoker].get_library_paths_to_arguments() map_file = @ceedling[:configurator].project_release_build_map + @ceedling[:generator].generate_executable_file( tool, RELEASE_SYM, objects, + [], # Flags bin_file.name, map_file, lib_args, diff --git a/tools/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake b/tools/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake deleted file mode 100644 index 9550783c..00000000 --- a/tools/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake +++ /dev/null @@ -1,15 +0,0 @@ - - -rule(/#{PROJECT_RELEASE_DEPENDENCIES_PATH}\/#{'.+\\'+EXTENSION_DEPENDENCIES}$/ => [ - proc do |task_name| - @ceedling[:file_finder].find_compilation_input_file(task_name, :error, true) - end - ]) do |dep| - @ceedling[:generator].generate_dependencies_file( - TOOLS_RELEASE_DEPENDENCIES_GENERATOR, - RELEASE_SYM, - dep.source, - @ceedling[:file_path_utils].form_release_build_c_object_filepath(dep.source), - dep.name) -end - diff --git a/tools/vendor/ceedling/lib/ceedling/rules_tests.rake b/tools/vendor/ceedling/lib/ceedling/rules_tests.rake index 61e15e2c..14f676e2 100644 --- a/tools/vendor/ceedling/lib/ceedling/rules_tests.rake +++ b/tools/vendor/ceedling/lib/ceedling/rules_tests.rake @@ -1,64 +1,37 @@ -rule(/#{PROJECT_TEST_FILE_PREFIX}#{'.+'+TEST_RUNNER_FILE_SUFFIX}#{'\\'+EXTENSION_SOURCE}$/ => [ +rule(/#{PROJECT_TEST_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_OBJECT}$/ => [ proc do |task_name| - @ceedling[:file_finder].find_test_input_for_runner_file(task_name) + _, object = (task_name.split('+')) + @ceedling[:file_finder].find_compilation_input_file(object) end - ]) do |runner| - @ceedling[:generator].generate_test_runner(TEST_SYM, runner.source, runner.name) -end - -rule(/#{PROJECT_TEST_BUILD_OUTPUT_C_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [ - proc do |task_name| - @ceedling[:file_finder].find_compilation_input_file(task_name) + ]) do |target| + test, object = (target.name.split('+')) + + if (File.basename(target.source) =~ /#{EXTENSION_SOURCE}$/) + @ceedling[:test_invoker].compile_test_component(test: test.to_sym, source: target.source, object: object) + elsif (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) + @ceedling[:generator].generate_object_file( + TOOLS_TEST_ASSEMBLER, + OPERATION_ASSEMBLE_SYM, + TEST_SYM, + object.source, + object.name ) end - ]) do |object| - if (File.basename(object.source) =~ /#{EXTENSION_SOURCE}$/) - @ceedling[:generator].generate_object_file( - TOOLS_TEST_COMPILER, - OPERATION_COMPILE_SYM, - TEST_SYM, - object.source, - object.name, - @ceedling[:file_path_utils].form_test_build_list_filepath( object.name ), - @ceedling[:file_path_utils].form_test_dependencies_filepath( object.name )) - elsif (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) - @ceedling[:generator].generate_object_file( - TOOLS_TEST_ASSEMBLER, - OPERATION_ASSEMBLE_SYM, - TEST_SYM, - object.source, - object.name ) end -end - - -rule(/#{PROJECT_TEST_BUILD_OUTPUT_PATH}\/#{'.+\\'+EXTENSION_EXECUTABLE}$/) do |bin_file| - lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments() - lib_paths = @ceedling[:test_invoker].get_library_paths_to_arguments() - @ceedling[:generator].generate_executable_file( - TOOLS_TEST_LINKER, - TEST_SYM, - bin_file.prerequisites, - bin_file.name, - @ceedling[:file_path_utils].form_test_build_map_filepath( bin_file.name ), - lib_args, - lib_paths ) -end +namespace TEST_SYM do + TOOL_COLLECTION_TEST_RULES = { + :context => TEST_SYM, + :test_compiler => TOOLS_TEST_COMPILER, + :test_assembler => TOOLS_TEST_ASSEMBLER, + :test_linker => TOOLS_TEST_LINKER, + :test_fixture => TOOLS_TEST_FIXTURE + } -rule(/#{PROJECT_TEST_RESULTS_PATH}\/#{'.+\\'+EXTENSION_TESTPASS}$/ => [ - proc do |task_name| - @ceedling[:file_path_utils].form_test_executable_filepath(task_name) - end - ]) do |test_result| - @ceedling[:generator].generate_test_results(TOOLS_TEST_FIXTURE, TEST_SYM, test_result.source, test_result.name) -end - + @ceedling[:unity_utils].create_test_runner_additional_args -namespace TEST_SYM do # use rules to increase efficiency for large projects (instead of iterating through all sources and creating defined tasks) - rule(/^#{TEST_TASK_ROOT}\S+$/ => [ # test task names by regex proc do |task_name| test = task_name.sub(/#{TEST_TASK_ROOT}/, '') @@ -67,7 +40,7 @@ namespace TEST_SYM do end ]) do |test| @ceedling[:rake_wrapper][:test_deps].invoke - @ceedling[:test_invoker].setup_and_invoke([test.source]) + @ceedling[:test_invoker].setup_and_invoke(tests:[test.source], options:{:force_run => true, :build_only => false}.merge(TOOL_COLLECTION_TEST_RULES)) end end diff --git a/tools/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake b/tools/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake deleted file mode 100644 index 7175ee3f..00000000 --- a/tools/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake +++ /dev/null @@ -1,15 +0,0 @@ - - -rule(/#{PROJECT_TEST_DEPENDENCIES_PATH}\/#{'.+\\'+EXTENSION_DEPENDENCIES}$/ => [ - proc do |task_name| - @ceedling[:file_finder].find_compilation_input_file(task_name) - end - ]) do |dep| - @ceedling[:generator].generate_dependencies_file( - TOOLS_TEST_DEPENDENCIES_GENERATOR, - TEST_SYM, - dep.source, - @ceedling[:file_path_utils].form_test_build_c_object_filepath(dep.source), - dep.name) -end - diff --git a/tools/vendor/ceedling/lib/ceedling/setupinator.rb b/tools/vendor/ceedling/lib/ceedling/setupinator.rb index ea78fd97..92d1934d 100644 --- a/tools/vendor/ceedling/lib/ceedling/setupinator.rb +++ b/tools/vendor/ceedling/lib/ceedling/setupinator.rb @@ -23,6 +23,7 @@ def do_setup(config_hash) @ceedling[:configurator].populate_defaults( config_hash ) @ceedling[:configurator].populate_unity_defaults( config_hash ) @ceedling[:configurator].populate_cmock_defaults( config_hash ) + @ceedling[:configurator].copy_vendor_defines( config_hash ) @ceedling[:configurator].find_and_merge_plugins( config_hash ) @ceedling[:configurator].merge_imports( config_hash ) @ceedling[:configurator].eval_environment_variables( config_hash ) @@ -31,7 +32,7 @@ def do_setup(config_hash) @ceedling[:configurator].standardize_paths( config_hash ) @ceedling[:configurator].validate( config_hash ) @ceedling[:configurator].build( config_hash, :environment ) - + @ceedling[:configurator].insert_rake_plugins( @ceedling[:configurator].rake_plugins ) @ceedling[:configurator].tools_supplement_arguments( config_hash ) diff --git a/tools/vendor/ceedling/lib/ceedling/stream_wrapper.rb b/tools/vendor/ceedling/lib/ceedling/stream_wrapper.rb index 7e160527..d69b8bf9 100644 --- a/tools/vendor/ceedling/lib/ceedling/stream_wrapper.rb +++ b/tools/vendor/ceedling/lib/ceedling/stream_wrapper.rb @@ -1,6 +1,30 @@ + +BEGIN { + require 'io/nonblock' + + # If possible, capture standard data streams non-blocking mode at startup (to be restored at shutdown). + # A complex build setup may have intended this change, but it will cause trouble for Ceedling. + + if STDOUT.respond_to?(:nonblock?) # Non-blocking mode query not implemented on all platforms + STDIN_STARTUP_NONBLOCKING_MODE = (STDIN.nonblock?).freeze + STDOUT_STARTUP_NONBLOCKING_MODE = (STDOUT.nonblock?).freeze + STDERR_STARTUP_NONBLOCKING_MODE = (STDERR.nonblock?).freeze + end + + # Ensure standard data streams are in blocking mode for Ceedling runs + STDIN.nonblock = false + STDOUT.nonblock = false + STDERR.nonblock = false +} + class StreamWrapper + def initialize + STDOUT.sync + STDERR.sync + end + def stdout_override(&fnc) @stdout_overide_fnc = fnc end @@ -13,16 +37,17 @@ def stdout_puts(string) end end - def stdout_flush - $stdout.flush - end - def stderr_puts(string) $stderr.puts(string) end - def stderr_flush - $stderr.flush - end - end + +END { + require 'io/nonblock' + + # If they were captured, reset standard data streams' non-blocking mode to the setting captured at startup + STDIN.nonblock = STDIN_STARTUP_NONBLOCKING_MODE if defined?(STDIN_STARTUP_NONBLOCKING_MODE) + STDOUT.nonblock = STDOUT_STARTUP_NONBLOCKING_MODE if defined?(STDOUT_STARTUP_NONBLOCKING_MODE) + STDERR.nonblock = STDERR_STARTUP_NONBLOCKING_MODE if defined?(STDERR_STARTUP_NONBLOCKING_MODE) +} diff --git a/tools/vendor/ceedling/lib/ceedling/streaminator.rb b/tools/vendor/ceedling/lib/ceedling/streaminator.rb index b8dcd070..11ed109c 100644 --- a/tools/vendor/ceedling/lib/ceedling/streaminator.rb +++ b/tools/vendor/ceedling/lib/ceedling/streaminator.rb @@ -10,7 +10,6 @@ class Streaminator def stdout_puts(string, verbosity=Verbosity::NORMAL) if (@verbosinator.should_output?(verbosity)) @stream_wrapper.stdout_puts(string) - @stream_wrapper.stdout_flush end # write to log as though Verbosity::OBNOXIOUS @@ -20,7 +19,6 @@ def stdout_puts(string, verbosity=Verbosity::NORMAL) def stderr_puts(string, verbosity=Verbosity::NORMAL) if (@verbosinator.should_output?(verbosity)) @stream_wrapper.stderr_puts(string) - @stream_wrapper.stderr_flush end # write to log as though Verbosity::OBNOXIOUS @@ -30,7 +28,6 @@ def stderr_puts(string, verbosity=Verbosity::NORMAL) def stream_puts(stream, string, verbosity=Verbosity::NORMAL) if (@verbosinator.should_output?(verbosity)) stream.puts(string) - stream.flush end # write to log as though Verbosity::OBNOXIOUS diff --git a/tools/vendor/ceedling/lib/ceedling/system_wrapper.rb b/tools/vendor/ceedling/lib/ceedling/system_wrapper.rb index 2b0f1edd..e53c3e26 100644 --- a/tools/vendor/ceedling/lib/ceedling/system_wrapper.rb +++ b/tools/vendor/ceedling/lib/ceedling/system_wrapper.rb @@ -1,4 +1,5 @@ -require 'rbconfig' +require 'rbconfig' +require 'open3' class SystemWrapper @@ -41,6 +42,23 @@ def time_now return Time.now.asctime end + def shell_capture3(command, boom = true) + begin + stdout, stderr, status = Open3.capture3(command) + rescue => err + stderr = err + status = -1 + end + $exit_code = status.freeze if boom + if (status != 0) + stdout += stderr + end + return { + :output => stdout.freeze, + :exit_code => status.freeze + } + end + def shell_backticks(command, boom = true) retval = `#{command}`.freeze $exit_code = ($?.exitstatus).freeze if boom diff --git a/tools/vendor/ceedling/lib/ceedling/target_loader.rb b/tools/vendor/ceedling/lib/ceedling/target_loader.rb index 7fbc0959..f1e95120 100644 --- a/tools/vendor/ceedling/lib/ceedling/target_loader.rb +++ b/tools/vendor/ceedling/lib/ceedling/target_loader.rb @@ -1,10 +1,10 @@ module TargetLoader - class NoTargets < Exception; end - class NoDirectory < Exception; end - class NoDefault < Exception; end - class NoSuchTarget < Exception; end + class NoTargets < RuntimeError; end + class NoDirectory < RuntimeError; end + class NoDefault < RuntimeError; end + class NoSuchTarget < RuntimeError; end - class RequestReload < Exception; end + class RequestReload < RuntimeError; end def self.inspect(config, target_name=nil) unless config[:targets] @@ -27,7 +27,7 @@ def self.inspect(config, target_name=nil) target_path.call(targets[:default_target]) end - unless File.exists? target + unless File.exist? target raise NoSuchTarget.new("No such target: #{target}") end diff --git a/tools/vendor/ceedling/lib/ceedling/task_invoker.rb b/tools/vendor/ceedling/lib/ceedling/task_invoker.rb index 7bfabbb1..d1b5d525 100644 --- a/tools/vendor/ceedling/lib/ceedling/task_invoker.rb +++ b/tools/vendor/ceedling/lib/ceedling/task_invoker.rb @@ -1,15 +1,17 @@ -require 'ceedling/par_map' class TaskInvoker attr_accessor :first_run - constructor :dependinator, :rake_utils, :rake_wrapper, :project_config_manager + constructor :dependinator, :build_batchinator, :rake_utils, :rake_wrapper, :project_config_manager def setup @test_regexs = [/^#{TEST_ROOT_NAME}:/] @release_regexs = [/^#{RELEASE_ROOT_NAME}(:|$)/] @first_run = true + + # Alias for brevity + @batchinator = @build_batchinator end def add_test_task_regex(regex) @@ -46,75 +48,15 @@ def invoked?(regex) return @rake_utils.task_invoked?(regex) end - def reset_rake_task_for_changed_defines(file) - if !(file =~ /#{VENDORS_FILES.map{|ignore| '\b' + ignore.ext(File.extname(file)) + '\b'}.join('|')}$/) - @rake_wrapper[file].clear_actions if @first_run == false && @project_config_manager.test_defines_changed - @rake_wrapper[file].reenable if @first_run == false && @project_config_manager.test_defines_changed + def invoke_test_objects(test:, objects:) + @batchinator.exec(workload: :compile, things: objects) do |object| + # Encode context with concatenated compilation target: + + @rake_wrapper["#{test}+#{object}"].invoke end end - def invoke_test_mocks(mocks) - @dependinator.enhance_mock_dependencies( mocks ) - mocks.each { |mock| - reset_rake_task_for_changed_defines( mock ) - @rake_wrapper[mock].invoke - } - end - - def invoke_test_runner(runner) - @dependinator.enhance_runner_dependencies( runner ) - reset_rake_task_for_changed_defines( runner ) - @rake_wrapper[runner].invoke - end - - def invoke_test_shallow_include_lists(files) - @dependinator.enhance_shallow_include_lists_dependencies( files ) - par_map(PROJECT_COMPILE_THREADS, files) do |file| - reset_rake_task_for_changed_defines( file ) - @rake_wrapper[file].invoke - end - end - - def invoke_test_preprocessed_files(files) - @dependinator.enhance_preprocesed_file_dependencies( files ) - par_map(PROJECT_COMPILE_THREADS, files) do |file| - reset_rake_task_for_changed_defines( file ) - @rake_wrapper[file].invoke - end - end - - def invoke_test_dependencies_files(files) - @dependinator.enhance_dependencies_dependencies( files ) - par_map(PROJECT_COMPILE_THREADS, files) do |file| - reset_rake_task_for_changed_defines( file ) - @rake_wrapper[file].invoke - end - end - - def invoke_test_objects(objects) - par_map(PROJECT_COMPILE_THREADS, objects) do |object| - reset_rake_task_for_changed_defines( object ) - @rake_wrapper[object].invoke - end - end - - def invoke_test_executable(file) - @rake_wrapper[file].invoke - end - - def invoke_test_results(result) - @dependinator.enhance_results_dependencies( result ) - @rake_wrapper[result].invoke - end - - def invoke_release_dependencies_files(files) - par_map(PROJECT_COMPILE_THREADS, files) do |file| - @rake_wrapper[file].invoke - end - end - def invoke_release_objects(objects) - par_map(PROJECT_COMPILE_THREADS, objects) do |object| + @batchinator.exec(workload: :compile, things: objects) do |object| @rake_wrapper[object].invoke end end diff --git a/tools/vendor/ceedling/lib/ceedling/tasks_base.rake b/tools/vendor/ceedling/lib/ceedling/tasks_base.rake index a35cde75..ad1d7c20 100644 --- a/tools/vendor/ceedling/lib/ceedling/tasks_base.rake +++ b/tools/vendor/ceedling/lib/ceedling/tasks_base.rake @@ -14,15 +14,6 @@ desc "Set verbose output (silent:[#{Verbosity::SILENT}] - obnoxious:[#{Verbosity task :verbosity, :level do |t, args| verbosity_level = args.level.to_i - if (PROJECT_USE_MOCKS) - # don't store verbosity level in setupinator's config hash, use a copy; - # otherwise, the input configuration will change and trigger entire project rebuilds - hash = @ceedling[:setupinator].config_hash[:cmock].clone - hash[:verbosity] = verbosity_level - - @ceedling[:cmock_builder].manufacture( hash ) - end - @ceedling[:configurator].project_verbosity = verbosity_level # control rake's verbosity with new setting diff --git a/tools/vendor/ceedling/lib/ceedling/tasks_filesystem.rake b/tools/vendor/ceedling/lib/ceedling/tasks_filesystem.rake index 7b950ca0..50d3e983 100644 --- a/tools/vendor/ceedling/lib/ceedling/tasks_filesystem.rake +++ b/tools/vendor/ceedling/lib/ceedling/tasks_filesystem.rake @@ -16,7 +16,6 @@ CLOBBER.include(File.join(PROJECT_BUILD_ARTIFACTS_ROOT, '**/*')) CLOBBER.include(File.join(PROJECT_BUILD_TESTS_ROOT, '**/*')) CLOBBER.include(File.join(PROJECT_BUILD_RELEASE_ROOT, '**/*')) CLOBBER.include(File.join(PROJECT_LOG_PATH, '**/*')) -CLOBBER.include(File.join(PROJECT_TEMP_PATH, '**/*')) # just in case they're using git, let's make sure we allow them to preserved the build directory if desired. CLOBBER.exclude(File.join(TESTS_BASE_PATH), '**/.gitkeep') @@ -33,22 +32,14 @@ task(:clean) do if (not @ceedling[:task_invoker].invoked?(/^clobber$/)) @ceedling[:streaminator].stdout_puts("\nCleaning build artifacts...\n(For large projects, this task may take a long time to complete)\n\n") end - begin - CLEAN.each { |fn| REMOVE_FILE_PROC.call(fn) } - rescue - end + CLEAN.each { |fn| REMOVE_FILE_PROC.call(fn) } end # redefine clobber so we can override how it advertises itself desc "Delete all generated files (and build artifacts)." task(:clobber => [:clean]) do @ceedling[:streaminator].stdout_puts("\nClobbering all generated files...\n(For large projects, this task may take a long time to complete)\n\n") - begin - CLOBBER.each { |fn| REMOVE_FILE_PROC.call(fn) } - @ceedling[:rake_wrapper][:directories].invoke - @ceedling[:dependinator].touch_force_rebuild_files - rescue - end + CLOBBER.each { |fn| REMOVE_FILE_PROC.call(fn) } end # create a directory task for each of the paths, so we know how to build them @@ -57,54 +48,34 @@ PROJECT_BUILD_PATHS.each { |path| directory(path) } # create a single directory task which verifies all the others get built task :directories => PROJECT_BUILD_PATHS -# when the force file doesn't exist, it probably means we clobbered or are on a fresh -# install. In either case, stuff was deleted, so assume we want to rebuild it all -file @ceedling[:configurator].project_test_force_rebuild_filepath do - unless File.exists?(@ceedling[:configurator].project_test_force_rebuild_filepath) - @ceedling[:dependinator].touch_force_rebuild_files - end -end - # list paths discovered at load time namespace :paths do - standard_paths = ['test','source','include'] + standard_paths = ['test', 'source', 'include', 'support'] paths = @ceedling[:setupinator].config_hash[:paths].keys.map{|n| n.to_s.downcase} - paths = (paths + standard_paths).uniq paths.each do |name| - path_list = Object.const_get("COLLECTION_PATHS_#{name.upcase}") - - if (path_list.size != 0) || (standard_paths.include?(name)) - desc "List all collected #{name} paths." - task(name.to_sym) { puts "#{name} paths:"; path_list.sort.each {|path| puts " - #{path}" } } + desc "List all collected #{name} paths." if standard_paths.include?(name) + task(name.to_sym) do + path_list = Object.const_get("COLLECTION_PATHS_#{name.upcase}") + puts "#{name.capitalize} paths:" + path_list.sort.each {|path| puts " - #{path}" } + puts "path count: #{path_list.size}" end end - end # list files & file counts discovered at load time namespace :files do - categories = [ - ['test', COLLECTION_ALL_TESTS], - ['source', COLLECTION_ALL_SOURCE], - ['include', COLLECTION_ALL_HEADERS], - ['support', COLLECTION_ALL_SUPPORT] - ] - - using_assembly = (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) || - (defined?(RELEASE_BUILD_USE_ASSEMBLY) && RELEASE_BUILD_USE_ASSEMBLY) - categories << ['assembly', COLLECTION_ALL_ASSEMBLY] if using_assembly + categories = ['tests', 'source', 'assembly', 'include', 'support'] categories.each do |category| - name = category[0] - collection = category[1] - - desc "List all collected #{name} files." - task(name.to_sym) do - puts "#{name} files:" - collection.sort.each { |filepath| puts " - #{filepath}" } - puts "file count: #{collection.size}" + desc "List all collected #{category.chomp('s')} files." + task(category.chomp('s').to_sym) do + files_list = Object.const_get("COLLECTION_ALL_#{category.upcase}") + puts "#{category.chomp('s').capitalize} files:" + files_list.sort.each { |filepath| puts " - #{filepath}" } + puts "file count: #{files_list.size}" end end diff --git a/tools/vendor/ceedling/lib/ceedling/tasks_release.rake b/tools/vendor/ceedling/lib/ceedling/tasks_release.rake index b313b2f5..60e060ed 100644 --- a/tools/vendor/ceedling/lib/ceedling/tasks_release.rake +++ b/tools/vendor/ceedling/lib/ceedling/tasks_release.rake @@ -16,13 +16,23 @@ task RELEASE_SYM => [:directories] do @ceedling[:project_config_manager].process_release_config_change core_objects.concat( @ceedling[:release_invoker].setup_and_invoke_c_objects( COLLECTION_ALL_SOURCE ) ) - # if assembler use isn't enabled, COLLECTION_ALL_ASSEMBLY is empty array & nothing happens + # If assembler use isn't enabled, COLLECTION_ALL_ASSEMBLY is empty array & nothing happens core_objects.concat( @ceedling[:release_invoker].setup_and_invoke_asm_objects( COLLECTION_ALL_ASSEMBLY ) ) - # if we're using libraries, we need to add those to our collection as well + # If we're using libraries, we need to add those to our collection as well library_objects = (defined? LIBRARIES_RELEASE && !LIBRARIES_RELEASE.empty?) ? LIBRARIES_RELEASE.flatten.compact : [] file( PROJECT_RELEASE_BUILD_TARGET => (core_objects + extra_objects + library_objects) ) Rake::Task[PROJECT_RELEASE_BUILD_TARGET].invoke + + rescue StandardError => e + @ceedling[:streaminator].stderr_puts("Error ==> #{e.class}:: #{e.message}") + + # Debug backtrace + @ceedling[:streaminator].stderr_puts("Backtrace ==>", Verbosity::DEBUG) + if @ceedling[:verbosinator].should_output?(Verbosity::DEBUG) + $stderr.puts(e.backtrace) # Formats properly when directly passed to puts() + end + ensure @ceedling[:plugin_manager].post_release end diff --git a/tools/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake b/tools/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake deleted file mode 100644 index db2be5f3..00000000 --- a/tools/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake +++ /dev/null @@ -1,9 +0,0 @@ -require 'ceedling/constants' - -namespace REFRESH_SYM do - - task RELEASE_SYM do - @ceedling[:release_invoker].refresh_c_deep_dependencies - end - -end diff --git a/tools/vendor/ceedling/lib/ceedling/tasks_tests.rake b/tools/vendor/ceedling/lib/ceedling/tasks_tests.rake index 6c51ebcc..72350f4f 100644 --- a/tools/vendor/ceedling/lib/ceedling/tasks_tests.rake +++ b/tools/vendor/ceedling/lib/ceedling/tasks_tests.rake @@ -1,6 +1,24 @@ require 'ceedling/constants' -task :test_deps => [:directories] +task :test_deps => [:directories] do + # Copy Unity C files into build/vendor directory structure + @ceedling[:file_wrapper].cp_r( + # '/.' to cause cp_r to copy directory contents + File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, '/.' ), + PROJECT_BUILD_VENDOR_UNITY_PATH ) + + # Copy CMock C files into build/vendor directory structure + @ceedling[:file_wrapper].cp_r( + # '/.' to cause cp_r to copy directory contents + File.join( CMOCK_VENDOR_PATH, CMOCK_LIB_PATH, '/.' ), + PROJECT_BUILD_VENDOR_CMOCK_PATH ) if PROJECT_USE_MOCKS + + # Copy CException C files into build/vendor directory structure + @ceedling[:file_wrapper].cp_r( + # '/.' to cause cp_r to copy directory contents + File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, '/.' ), + PROJECT_BUILD_VENDOR_CEXCEPTION_PATH ) if PROJECT_USE_EXCEPTIONS +end task :test => [:test_deps] do Rake.application['test:all'].invoke @@ -8,12 +26,21 @@ end namespace TEST_SYM do + TOOL_COLLECTION_TEST_TASKS = { + :test_compiler => TOOLS_TEST_COMPILER, + :test_assembler => TOOLS_TEST_ASSEMBLER, + :test_linker => TOOLS_TEST_LINKER, + :test_fixture => TOOLS_TEST_FIXTURE + } + desc "Run all unit tests (also just 'test' works)." task :all => [:test_deps] do - @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS) + @ceedling[:test_invoker].setup_and_invoke( + tests:COLLECTION_ALL_TESTS, + options:{:force_run => true, :build_only => false}.merge(TOOL_COLLECTION_TEST_TASKS)) end - desc "Run single test ([*] real test or source file name, no path)." + desc "Run single test ([*] test or source file name, no path)." task :* do message = "\nOops! '#{TEST_ROOT_NAME}:*' isn't a real task. " + "Use a real test or source file name (no path) in place of the wildcard.\n" + @@ -22,14 +49,9 @@ namespace TEST_SYM do @ceedling[:streaminator].stdout_puts( message ) end - desc "Run tests for changed files." - task :delta => [:test_deps] do - @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, TEST_SYM, {:force_run => false}) - end - desc "Just build tests without running." task :build_only => [:test_deps] do - @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, TEST_SYM, {:build_only => true}) + @ceedling[:test_invoker].setup_and_invoke(tests:COLLECTION_ALL_TESTS, options:{:build_only => true}.merge(TOOL_COLLECTION_TEST_TASKS)) end desc "Run tests by matching regular expression pattern." @@ -39,7 +61,7 @@ namespace TEST_SYM do COLLECTION_ALL_TESTS.each { |test| matches << test if (test =~ /#{args.regex}/) } if (matches.size > 0) - @ceedling[:test_invoker].setup_and_invoke(matches, TEST_SYM, {:force_run => false}) + @ceedling[:test_invoker].setup_and_invoke(tests:matches, options:{:force_run => false}.merge(TOOL_COLLECTION_TEST_TASKS)) else @ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.") end @@ -52,7 +74,7 @@ namespace TEST_SYM do COLLECTION_ALL_TESTS.each { |test| matches << test if File.dirname(test).include?(args.dir.gsub(/\\/, '/')) } if (matches.size > 0) - @ceedling[:test_invoker].setup_and_invoke(matches, TEST_SYM, {:force_run => false}) + @ceedling[:test_invoker].setup_and_invoke(tests:matches, options:{:force_run => false}.merge(TOOL_COLLECTION_TEST_TASKS)) else @ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.") end diff --git a/tools/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake b/tools/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake deleted file mode 100644 index f8994071..00000000 --- a/tools/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake +++ /dev/null @@ -1,9 +0,0 @@ -require 'ceedling/constants' - -namespace REFRESH_SYM do - - task TEST_SYM do - @ceedling[:test_invoker].refresh_deep_dependencies - end - -end diff --git a/tools/vendor/ceedling/lib/ceedling/tasks_vendor.rake b/tools/vendor/ceedling/lib/ceedling/tasks_vendor.rake deleted file mode 100644 index 63c2ca55..00000000 --- a/tools/vendor/ceedling/lib/ceedling/tasks_vendor.rake +++ /dev/null @@ -1,35 +0,0 @@ -require 'ceedling/constants' -require 'ceedling/file_path_utils' - -# create file dependencies to ensure C-based components of vendor tools are recompiled when they are updated with new versions -# forming these explicitly rather than depend on auxiliary dependencies so all scenarios are explicitly covered - -file( @ceedling[:file_path_utils].form_test_build_c_object_filepath( UNITY_C_FILE ) => [ - File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, UNITY_C_FILE ), - File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, UNITY_H_FILE ), - File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, UNITY_INTERNALS_H_FILE ) ] - ) - - -if (PROJECT_USE_MOCKS) -file( @ceedling[:file_path_utils].form_test_build_c_object_filepath( CMOCK_C_FILE ) => [ - File.join( CMOCK_VENDOR_PATH, CMOCK_LIB_PATH, CMOCK_C_FILE ), - File.join( CMOCK_VENDOR_PATH, CMOCK_LIB_PATH, CMOCK_H_FILE ) ] - ) -end - - -if (PROJECT_USE_EXCEPTIONS) -file( @ceedling[:file_path_utils].form_test_build_c_object_filepath( CEXCEPTION_C_FILE ) => [ - File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_C_FILE ), - File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_H_FILE ) ] - ) -end - - -if (PROJECT_USE_EXCEPTIONS and PROJECT_RELEASE_BUILD) -file( @ceedling[:file_path_utils].form_release_build_c_object_filepath( CEXCEPTION_C_FILE ) => [ - File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_C_FILE ), - File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_H_FILE ) ] - ) -end diff --git a/tools/vendor/ceedling/lib/ceedling/test_context_extractor.rb b/tools/vendor/ceedling/lib/ceedling/test_context_extractor.rb new file mode 100644 index 00000000..37e74bf4 --- /dev/null +++ b/tools/vendor/ceedling/lib/ceedling/test_context_extractor.rb @@ -0,0 +1,180 @@ + +class TestContextExtractor + + constructor :configurator, :file_wrapper + + def setup + @header_includes = {} + @source_includes = {} + @source_extras = {} + @mocks = {} + @include_paths = {} + @all_include_paths = [] + + @lock = Mutex.new + end + + + # Scan for & store build directives + # - TEST_SOURCE_FILE() + # - TEST_INCLUDE_PATH() + def collect_build_directives(filepath) + include_paths, source_extras = extract_build_directives( filepath, @file_wrapper.read(filepath) ) + ingest_build_directives( + filepath:filepath, + include_paths:include_paths, + source_extras:source_extras + ) + end + + # Scan for & store includes (.h & .c) and mocks + def collect_includes(filepath) + includes = extract_includes( filepath, @file_wrapper.read(filepath) ) + ingest_includes(filepath, includes) + end + + # Scan for all includes + def scan_includes(filepath) + return extract_includes( filepath, @file_wrapper.read(filepath) ) + end + + # Header header_includes of test file with file extension + def lookup_header_includes_list(filepath) + return @header_includes[form_file_key(filepath)] || [] + end + + # Include paths of test file specified with TEST_INCLUDE_PATH() + def lookup_include_paths_list(filepath) + return @include_paths[form_file_key(filepath)] || [] + end + + # Source header_includes within test file + def lookup_source_includes_list(filepath) + return @source_includes[form_file_key(filepath)] || [] + end + + # Source extras via TEST_SOURCE_FILE() within test file + def lookup_build_directive_sources_list(filepath) + return @source_extras[form_file_key(filepath)] || [] + end + + # Mocks within test file with no file extension + def lookup_raw_mock_list(filepath) + return @mocks[form_file_key(filepath)] || [] + end + + def lookup_all_include_paths + return @all_include_paths.uniq + end + + def inspect_include_paths + @include_paths.each { |test, paths| yield test, paths } + end + + def ingest_includes(filepath, includes) + mock_prefix = @configurator.cmock_mock_prefix + file_key = form_file_key(filepath) + + mocks = [] + headers = [] + sources = [] + + includes.each do |include| + # <*.h> + if include =~ /#{Regexp.escape(@configurator.extension_header)}$/ + # Check if include is a mock with regex match that extracts only mock name (no .h) + scan_results = include.scan(/(#{mock_prefix}.+)#{Regexp.escape(@configurator.extension_header)}/) + mocks << scan_results[0][0] if (scan_results.size > 0) + + # Add to .h includes list + headers << include + # <*.c> + elsif include =~ /#{Regexp.escape(@configurator.extension_source)}$/ + # Add to .c includes list + sources << include + end + end + + @lock.synchronize do + @mocks[file_key] = mocks + @header_includes[file_key] = headers + @source_includes[file_key] = sources + end + end + + private ################################# + + def extract_build_directives(filepath, content) + include_paths = [] + source_extras = [] + + content = remove_comments(content) + + content.split("\n").each do |line| + # Look for TEST_INCLUDE_PATH("<*>") statements + results = line.scan(/#{UNITY_TEST_INCLUDE_PATH}\(\s*\"\s*(.+)\s*\"\s*\)/) + include_paths << FilePathUtils.standardize( results[0][0] ) if (results.size > 0) + + # Look for TEST_SOURCE_FILE("<*>.<*>) statement + results = line.scan(/#{UNITY_TEST_SOURCE_FILE}\(\s*\"\s*(.+\.\w+)\s*\"\s*\)/) + source_extras << FilePathUtils.standardize( results[0][0] ) if (results.size > 0) + end + + return include_paths.uniq, source_extras.uniq + end + + def extract_includes(filepath, content) + includes = [] + + content = check_encoding(content) + content = remove_comments(content) + + content.split("\n").each do |line| + # Look for #include statements + results = line.scan(/#\s*include\s+\"\s*(.+)\s*\"/) + includes << results[0][0] if (results.size > 0) + end + + return includes.uniq + end + + def ingest_build_directives(filepath:, include_paths:, source_extras:) + key = form_file_key(filepath) + + @lock.synchronize do + @include_paths[key] = include_paths + end + + @lock.synchronize do + @source_extras[key] = source_extras + end + + @lock.synchronize do + @all_include_paths += include_paths + end + end + + # Note: This method modifies encoding in place (encode!) in an attempt to reduce long string copies + def check_encoding(content) + if not content.valid_encoding? + content.encode!("UTF-16be", :invalid=>:replace, :replace=>"?").encode('UTF-8') + end + return content + end + + # Note: This method is destructive to argument content in an attempt to reduce memory usage + def remove_comments(content) + # Remove line comments + content.gsub!(/\/\/.*$/, '') + + # Remove block comments + content.gsub!(/\/\*.*?\*\//m, '') + + return content + end + + def form_file_key(filepath) + return filepath.to_s.to_sym + end + +end diff --git a/tools/vendor/ceedling/lib/ceedling/test_includes_extractor.rb b/tools/vendor/ceedling/lib/ceedling/test_includes_extractor.rb deleted file mode 100644 index 393b0be8..00000000 --- a/tools/vendor/ceedling/lib/ceedling/test_includes_extractor.rb +++ /dev/null @@ -1,111 +0,0 @@ - -class TestIncludesExtractor - - constructor :configurator, :yaml_wrapper, :file_wrapper - - def setup - @includes = {} - @mocks = {} - end - - - # for includes_list file, slurp up array from yaml file and sort & store includes - def parse_includes_list(includes_list) - gather_and_store_includes( includes_list, @yaml_wrapper.load(includes_list) ) - end - - # open, scan for, and sort & store includes of test file - def parse_test_file(test) - gather_and_store_includes( test, extract_from_file(test) ) - end - - # open, scan for, and sort & store includes of test file - def parse_test_file_source_include(test) - return extract_source_include_from_file(test) - end - - # mocks with no file extension - def lookup_raw_mock_list(test) - file_key = form_file_key(test) - return [] if @mocks[file_key].nil? - return @mocks[file_key] - end - - # includes with file extension - def lookup_includes_list(file) - file_key = form_file_key(file) - return [] if (@includes[file_key]).nil? - return @includes[file_key] - end - - private ################################# - - def form_file_key(filepath) - return File.basename(filepath).to_sym - end - - def extract_from_file(file) - includes = [] - header_extension = @configurator.extension_header - - contents = @file_wrapper.read(file) - - # remove line comments - contents = contents.gsub(/\/\/.*$/, '') - # remove block comments - contents = contents.gsub(/\/\*.*?\*\//m, '') - - contents.split("\n").each do |line| - # look for include statement - scan_results = line.scan(/#include\s+\"\s*(.+#{'\\'+header_extension})\s*\"/) - - includes << scan_results[0][0] if (scan_results.size > 0) - - # look for TEST_FILE statement - scan_results = line.scan(/TEST_FILE\(\s*\"\s*(.+\.\w+)\s*\"\s*\)/) - - includes << scan_results[0][0] if (scan_results.size > 0) - end - - return includes.uniq - end - - def extract_source_include_from_file(file) - source_includes = [] - source_extension = @configurator.extension_source - - contents = @file_wrapper.read(file) - - # remove line comments - contents = contents.gsub(/\/\/.*$/, '') - # remove block comments - contents = contents.gsub(/\/\*.*?\*\//m, '') - - contents.split("\n").each do |line| - # look for include statement - scan_results = line.scan(/#include\s+\"\s*(.+#{'\\'+source_extension})\s*\"/) - - source_includes << scan_results[0][0] if (scan_results.size > 0) - end - - return source_includes.uniq - end - - def gather_and_store_includes(file, includes) - mock_prefix = @configurator.cmock_mock_prefix - header_extension = @configurator.extension_header - file_key = form_file_key(file) - @mocks[file_key] = [] - - # add includes to lookup hash - @includes[file_key] = includes - - includes.each do |include_file| - # check if include is a mock - scan_results = include_file.scan(/(#{mock_prefix}.+)#{'\\'+header_extension}/) - # add mock to lookup hash - @mocks[file_key] << scan_results[0][0] if (scan_results.size > 0) - end - end - -end diff --git a/tools/vendor/ceedling/lib/ceedling/test_invoker.rb b/tools/vendor/ceedling/lib/ceedling/test_invoker.rb index ae686a11..12834468 100644 --- a/tools/vendor/ceedling/lib/ceedling/test_invoker.rb +++ b/tools/vendor/ceedling/lib/ceedling/test_invoker.rb @@ -1,5 +1,5 @@ require 'ceedling/constants' - +require 'fileutils' class TestInvoker @@ -9,149 +9,350 @@ class TestInvoker :test_invoker_helper, :plugin_manager, :streaminator, + :build_batchinator, :preprocessinator, :task_invoker, - :dependinator, - :project_config_manager, :build_invoker_utils, + :generator, + :test_context_extractor, :file_path_utils, - :file_wrapper + :file_wrapper, + :verbosinator def setup - @sources = [] - @tests = [] - @mocks = [] - end + # Master data structure for all test activities + @testables = {} + # For thread-safe operations on @testables + @lock = Mutex.new - # Convert libraries configuration form YAML configuration - # into a string that can be given to the compiler. - def convert_libraries_to_arguments() - args = ((@configurator.project_config_hash[:libraries_test] || []) + ((defined? LIBRARIES_SYSTEM) ? LIBRARIES_SYSTEM : [])).flatten - if (defined? LIBRARIES_FLAG) - args.map! {|v| LIBRARIES_FLAG.gsub(/\$\{1\}/, v) } - end - return args + # Aliases for brevity in code that follows + @helper = @test_invoker_helper + @batchinator = @build_batchinator end - def get_library_paths_to_arguments() - paths = (defined? PATHS_LIBRARIES) ? (PATHS_LIBRARIES || []).clone : [] - if (defined? LIBRARIES_PATH_FLAG) - paths.map! {|v| LIBRARIES_PATH_FLAG.gsub(/\$\{1\}/, v) } - end - return paths - end + def setup_and_invoke(tests:, context:TEST_SYM, options:{}) + # Wrap everything in an exception handler + begin + + # Begin fleshing out the testables data structure + @batchinator.build_step("Preparing Build Paths", heading: false) do + results_path = File.join( @configurator.project_build_root, context.to_s, 'results' ) + + @batchinator.exec(workload: :compile, things: tests) do |filepath| + filepath = filepath.to_s + key = testable_symbolize(filepath) + name = key.to_s + build_path = File.join( @configurator.project_build_root, context.to_s, 'out', name ) + mocks_path = File.join( @configurator.cmock_mock_path, name ) + preprocess_includes_path = File.join( @configurator.project_test_preprocess_includes_path, name ) + preprocess_files_path = File.join( @configurator.project_test_preprocess_files_path, name ) + + @lock.synchronize do + @testables[key] = { + :filepath => filepath, + :name => name, + :paths => {} + } + + paths = @testables[key][:paths] + paths[:build] = build_path + paths[:results] = results_path + paths[:mocks] = mocks_path if @configurator.project_use_mocks + if @configurator.project_use_test_preprocessor + paths[:preprocess_incudes] = preprocess_includes_path + paths[:preprocess_files] = preprocess_files_path + end + end - def setup_and_invoke(tests, context=TEST_SYM, options={:force_run => true, :build_only => false}) + @testables[key][:paths].each {|_, path| @file_wrapper.mkdir(path) } + end - @tests = tests + # Remove any left over test results from previous runs + @helper.clean_test_results( results_path, @testables.map{ |_, t| t[:name] } ) + end - @project_config_manager.process_test_config_change + # Collect in-test build directives, etc. from test files + @batchinator.build_step("Extracting Build Directive Macros") do + @batchinator.exec(workload: :compile, things: @testables) do |_, details| + @preprocessinator.extract_test_build_directives( filepath:details[:filepath] ) + end - @tests.each do |test| - # announce beginning of test run - header = "Test '#{File.basename(test)}'" - @streaminator.stdout_puts("\n\n#{header}\n#{'-' * header.length}") + # Validate test build directive paths via TEST_INCLUDE_PATH() & augment header file collection from the same + @helper.process_project_include_paths - begin - @plugin_manager.pre_test( test ) - test_name ="#{File.basename(test)}".chomp('.c') - def_test_key="defines_#{test_name.downcase}" + # Validate test build directive source file entries via TEST_SOURCE_FILE() + @batchinator.exec(workload: :compile, things: @testables) do |_, details| + @helper.validate_build_directive_source_files( test:details[:name], filepath:details[:filepath] ) + end + end - if @configurator.project_config_hash.has_key?(def_test_key.to_sym) || @configurator.defines_use_test_definition - defs_bkp = Array.new(COLLECTION_DEFINES_TEST_AND_VENDOR) - tst_defs_cfg = Array.new(defs_bkp) - if @configurator.project_config_hash.has_key?(def_test_key.to_sym) - tst_defs_cfg.replace(@configurator.project_config_hash[def_test_key.to_sym]) - tst_defs_cfg .concat(COLLECTION_DEFINES_VENDOR) if COLLECTION_DEFINES_VENDOR + # Fill out testables data structure with build context + @batchinator.build_step("Ingesting Test Configurations") do + @batchinator.exec(workload: :compile, things: @testables) do |_, details| + filepath = details[:filepath] + + search_paths = @helper.search_paths( filepath, details[:name] ) + compile_flags = @helper.flags( context:context, operation:OPERATION_COMPILE_SYM, filepath:filepath ) + link_flags = @helper.flags( context:context, operation:OPERATION_LINK_SYM, filepath:filepath ) + compile_defines = @helper.compile_defines( context:context, filepath:filepath ) + preprocess_defines = @helper.preprocess_defines( test_defines: compile_defines, filepath:filepath ) + + @streaminator.stdout_puts( "Collecting search paths, flags, and defines for #{File.basename(filepath)}...", Verbosity::NORMAL) + + @lock.synchronize do + details[:search_paths] = search_paths + details[:compile_flags] = compile_flags + details[:link_flags] = link_flags + details[:compile_defines] = compile_defines + details[:preprocess_defines] = preprocess_defines end - if @configurator.defines_use_test_definition - tst_defs_cfg << File.basename(test, ".*").strip.upcase.sub(/@.*$/, "") - end - COLLECTION_DEFINES_TEST_AND_VENDOR.replace(tst_defs_cfg) end + end - # redefine the project out path and preprocessor defines - if @configurator.project_config_hash.has_key?(def_test_key.to_sym) - @streaminator.stdout_puts("Updating test definitions for #{test_name}", Verbosity::NORMAL) - orig_path = @configurator.project_test_build_output_path - @configurator.project_config_hash[:project_test_build_output_path] = File.join(@configurator.project_test_build_output_path, test_name) - @file_wrapper.mkdir(@configurator.project_test_build_output_path) + # Collect include statements & mocks from test files + @batchinator.build_step("Collecting Testing Context") do + @batchinator.exec(workload: :compile, things: @testables) do |_, details| + @preprocessinator.extract_testing_context( + filepath: details[:filepath], + test: details[:name], + flags: details[:compile_flags], + include_paths: details[:search_paths], + defines: details[:preprocess_defines] ) end + end - # collect up test fixture pieces & parts - runner = @file_path_utils.form_runner_filepath_from_test( test ) - mock_list = @preprocessinator.preprocess_test_and_invoke_test_mocks( test ) - sources = @test_invoker_helper.extract_sources( test ) - extras = @configurator.collection_test_fixture_extra_link_objects - core = [test] + mock_list + sources - objects = @file_path_utils.form_test_build_objects_filelist( [runner] + core + extras ).uniq - results_pass = @file_path_utils.form_pass_results_filepath( test ) - results_fail = @file_path_utils.form_fail_results_filepath( test ) - - # identify all the objects shall not be linked and then remove them from objects list. - no_link_objects = @file_path_utils.form_test_build_objects_filelist(@preprocessinator.preprocess_shallow_source_includes( test )) - objects = objects.uniq - no_link_objects + # Determine Runners & Mocks For All Tests + @batchinator.build_step("Determining Files to be Generated", heading: false) do + @batchinator.exec(workload: :compile, things: @testables) do |test, details| + runner_filepath = @file_path_utils.form_runner_filepath_from_test( details[:filepath] ) + + mocks = {} + mocks_list = @configurator.project_use_mocks ? @test_context_extractor.lookup_raw_mock_list( details[:filepath] ) : [] + mocks_list.each do |name| + source = @helper.find_header_input_for_mock_file( name, details[:search_paths] ) + preprocessed_input = @file_path_utils.form_preprocessed_file_filepath( source, details[:name] ) + mocks[name.to_sym] = { + :name => name, + :source => source, + :input => (@configurator.project_use_test_preprocessor ? preprocessed_input : source) + } + end - @project_config_manager.process_test_defines_change(@project_config_manager.filter_internal_sources(sources)) + @lock.synchronize do + details[:runner] = { + :output_filepath => runner_filepath, + :input_filepath => details[:filepath] # Default of the test file + } + details[:mocks] = mocks + details[:mock_list] = mocks_list + end + end + end - # clean results files so we have a missing file with which to kick off rake's dependency rules - @test_invoker_helper.clean_results( {:pass => results_pass, :fail => results_fail}, options ) + # Create inverted/flattened mock lookup list to take advantage of threading + # (Iterating each testable and mock list instead would limits the number of simultaneous mocking threads) + mocks = [] + if @configurator.project_use_mocks + @testables.each do |_, details| + details[:mocks].each do |name, elems| + mocks << {:name => name, :details => elems, :testable => details} + end + end + end - # load up auxiliary dependencies so deep changes cause rebuilding appropriately - @test_invoker_helper.process_deep_dependencies( core ) do |dependencies_list| - @dependinator.load_test_object_deep_dependencies( dependencies_list ) + # Preprocess Header Files + @batchinator.build_step("Preprocessing for Mocks") { + @batchinator.exec(workload: :compile, things: mocks) do |mock| + details = mock[:details] + testable = mock[:testable] + @preprocessinator.preprocess_header_file( + filepath: details[:source], + test: testable[:name], + flags: testable[:compile_flags], + include_paths: testable[:search_paths], + defines: testable[:preprocess_defines]) + end + } if @configurator.project_use_mocks and @configurator.project_use_test_preprocessor + + # Generate mocks for all tests + @batchinator.build_step("Mocking") { + @batchinator.exec(workload: :compile, things: mocks) do |mock| + details = mock[:details] + testable = mock[:testable] + @generator.generate_mock( + context: TEST_SYM, + mock: mock[:name], + test: testable[:name], + input_filepath: details[:input], + output_path: testable[:paths][:mocks] ) end + } if @configurator.project_use_mocks - # tell rake to create test runner if needed - @task_invoker.invoke_test_runner( runner ) + # Preprocess test files + @batchinator.build_step("Preprocessing for Test Runners") { + @batchinator.exec(workload: :compile, things: @testables) do |_, details| - # enhance object file dependencies to capture externalities influencing regeneration - @dependinator.enhance_test_build_object_dependencies( objects ) + filepath = @preprocessinator.preprocess_test_file( + filepath: details[:filepath], + test: details[:name], + flags: details[:compile_flags], + include_paths: details[:search_paths], + defines: details[:preprocess_defines]) - # associate object files with executable - @dependinator.enhance_test_executable_dependencies( test, objects ) + @lock.synchronize { details[:runner][:input_filepath] = filepath } # Replace default input with preprocessed fle + end + } if @configurator.project_use_test_preprocessor + + # Build runners for all tests + @batchinator.build_step("Test Runners") do + @batchinator.exec(workload: :compile, things: @testables) do |_, details| + @generator.generate_test_runner( + context: TEST_SYM, + mock_list: details[:mock_list], + test_filepath: details[:filepath], + input_filepath: details[:runner][:input_filepath], + runner_filepath: details[:runner][:output_filepath]) + end + end - # build test objects - @task_invoker.invoke_test_objects( objects ) + # Determine objects required for each test + @batchinator.build_step("Determining Artifacts to Be Built", heading: false) do + @batchinator.exec(workload: :compile, things: @testables) do |test, details| + # Source files referenced by conventions or specified by build directives in a test file + test_sources = @test_invoker_helper.extract_sources( details[:filepath] ) + test_core = test_sources + details[:mock_list] + # CMock + Unity + CException + test_frameworks = @helper.collect_test_framework_sources + # Extra suport source files (e.g. microcontroller startup code needed by simulator) + test_support = @configurator.collection_all_support + + compilations = [] + compilations << details[:filepath] + compilations += test_core + compilations << details[:runner][:output_filepath] + compilations += test_frameworks + compilations += test_support + compilations.uniq! + + test_objects = @file_path_utils.form_test_build_objects_filelist( details[:paths][:build], compilations ) + + test_executable = @file_path_utils.form_test_executable_filepath( details[:paths][:build], details[:filepath] ) + test_pass = @file_path_utils.form_pass_results_filepath( details[:paths][:results], details[:filepath] ) + test_fail = @file_path_utils.form_fail_results_filepath( details[:paths][:results], details[:filepath] ) + + # Identify all the objects shall not be linked and then remove them from objects list. + test_no_link_objects = @file_path_utils.form_test_build_objects_filelist(details[:paths][:build], @helper.fetch_shallow_source_includes( details[:filepath] )) + test_objects = test_objects.uniq - test_no_link_objects + + @lock.synchronize do + details[:sources] = test_sources + details[:frameworks] = test_frameworks + details[:core] = test_core + details[:objects] = test_objects + details[:executable] = test_executable + details[:no_link_objects] = test_no_link_objects + details[:results_pass] = test_pass + details[:results_fail] = test_fail + end + end + end + + # Build All Test objects + @batchinator.build_step("Building Objects") do + # FYI: Temporarily removed direct object generation to allow rake invoke() to execute custom compilations (plugins, special cases) + # @test_invoker_helper.generate_objects_now(object_list, options) + @testables.each do |_, details| + @task_invoker.invoke_test_objects(test: details[:name], objects:details[:objects]) + end + end - # if the option build_only has been specified, build only the executable - # but don't run the test - if (options[:build_only]) - executable = @file_path_utils.form_test_executable_filepath( test ) - @task_invoker.invoke_test_executable( executable ) - else - # 3, 2, 1... launch - @task_invoker.invoke_test_results( results_pass ) + # Create Final Tests And/Or Executable Links + @batchinator.build_step("Building Test Executables") do + lib_args = @helper.convert_libraries_to_arguments() + lib_paths = @helper.get_library_paths_to_arguments() + @batchinator.exec(workload: :compile, things: @testables) do |_, details| + @test_invoker_helper.generate_executable_now( + context: context, + build_path: details[:paths][:build], + executable: details[:executable], + objects: details[:objects], + flags: details[:link_flags], + lib_args: lib_args, + lib_paths: lib_paths, + options: options + ) end - rescue => e - @build_invoker_utils.process_exception( e, context ) - ensure - @plugin_manager.post_test( test ) - # restore the project test defines - if @configurator.project_config_hash.has_key?(def_test_key.to_sym) || @configurator.defines_use_test_definition - COLLECTION_DEFINES_TEST_AND_VENDOR.replace(defs_bkp) - if @configurator.project_config_hash.has_key?(def_test_key.to_sym) - @configurator.project_config_hash[:project_test_build_output_path] = orig_path - @streaminator.stdout_puts("Restored defines and build path to standard", Verbosity::NORMAL) + end + + # Execute Final Tests + @batchinator.build_step("Executing") { + @batchinator.exec(workload: :test, things: @testables) do |_, details| + begin + @plugin_manager.pre_test( details[:filepath] ) + @test_invoker_helper.run_fixture_now( + context: context, + executable: details[:executable], + result: details[:results_pass], + options: options + ) + rescue => e + @build_invoker_utils.process_exception( e, context ) + ensure + @plugin_manager.post_test( details[:filepath] ) end end + } unless options[:build_only] + + # Handle application-level exceptions. + # StandardError is the parent class of all application-level exceptions. + # Runtime errors (parent is Exception) continue on up to be caught by Ruby itself. + rescue StandardError => e + @streaminator.stderr_puts("Error ==> #{e.class}:: #{e.message}") + + # Debug backtrace + @streaminator.stderr_puts("Backtrace ==>", Verbosity::DEBUG) + if @verbosinator.should_output?(Verbosity::DEBUG) + $stderr.puts(e.backtrace) # Formats properly when directly passed to puts() end + end - # store away what's been processed - @mocks.concat( mock_list ) - @sources.concat( sources ) + end - @task_invoker.first_run = false + def each_test_with_sources + @testables.each do |test, details| + yield(test.to_s, lookup_sources(test:test)) end + end - # post-process collected mock list - @mocks.uniq! - - # post-process collected sources list - @sources.uniq! + def lookup_sources(test:) + _test = test.is_a?(Symbol) ? test : test.to_sym + return (@testables[_test])[:sources] end + def compile_test_component(tool:TOOLS_TEST_COMPILER, context:TEST_SYM, test:, source:, object:, msg:nil) + testable = @testables[test] + filepath = testable[:filepath] + search_paths = testable[:search_paths] + flags = testable[:compile_flags] + + # If source file is one of our vendor frameworks, augments its defines + defines = @helper.augment_vendor_defines(defines:testable[:compile_defines], filepath:source) + + @generator.generate_object_file_c( + tool: tool, + module_name: test, + context: context, + source: source, + object: object, + search_paths: search_paths, + flags: flags, + defines: defines, + list: @file_path_utils.form_test_build_list_filepath( object ), + dependencies: @file_path_utils.form_test_dependencies_filepath( object ), + msg: msg + ) + end def refresh_deep_dependencies @file_wrapper.rm_f( @@ -159,7 +360,13 @@ def refresh_deep_dependencies File.join( @configurator.project_test_dependencies_path, '*' + @configurator.extension_dependencies ) ) ) @test_invoker_helper.process_deep_dependencies( - @configurator.collection_all_tests + @configurator.collection_all_source ) + (@configurator.collection_all_tests + @configurator.collection_all_source).uniq ) + end + + private + + def testable_symbolize(filepath) + return (File.basename( filepath ).ext('')).to_sym end end diff --git a/tools/vendor/ceedling/lib/ceedling/test_invoker_helper.rb b/tools/vendor/ceedling/lib/ceedling/test_invoker_helper.rb index 403d93e3..194384a6 100644 --- a/tools/vendor/ceedling/lib/ceedling/test_invoker_helper.rb +++ b/tools/vendor/ceedling/lib/ceedling/test_invoker_helper.rb @@ -1,11 +1,119 @@ class TestInvokerHelper - constructor :configurator, :task_invoker, :test_includes_extractor, :file_finder, :file_path_utils, :file_wrapper + constructor :configurator, + :streaminator, + :build_batchinator, + :task_invoker, + :test_context_extractor, + :include_pathinator, + :defineinator, + :flaginator, + :file_finder, + :file_path_utils, + :file_wrapper, + :generator - def clean_results(results, options) - @file_wrapper.rm_f( results[:fail] ) - @file_wrapper.rm_f( results[:pass] ) if (options[:force_run]) + def setup + # Alias for brevity + @batchinator = @build_batchinator + end + + def process_project_include_paths + @include_pathinator.validate_test_directive_paths + @include_pathinator.augment_environment_header_files + end + + def validate_build_directive_source_files(test:, filepath:) + sources = @test_context_extractor.lookup_build_directive_sources_list(filepath) + + sources.each do |source| + ext = @configurator.extension_source + unless @file_wrapper.extname(source) == ext + @streaminator.stderr_puts("File '#{source}' specified with #{UNITY_TEST_SOURCE_FILE}() in #{test} is not a #{ext} source file", Verbosity::NORMAL) + raise + end + + if @file_finder.find_compilation_input_file(source, :ignore).nil? + @streaminator.stderr_puts("File '#{source}' specified with #{UNITY_TEST_SOURCE_FILE}() in #{test} cannot be found in the source file collection", Verbosity::NORMAL) + raise + end + end + end + + def search_paths(filepath, subdir) + paths = @include_pathinator.lookup_test_directive_include_paths( filepath ) + paths += @configurator.collection_paths_include + paths += @configurator.collection_paths_support + paths << File.join( @configurator.cmock_mock_path, subdir ) if @configurator.project_use_mocks + paths += @configurator.collection_paths_libraries + paths += @configurator.collection_paths_vendor + paths += @configurator.collection_paths_test_toolchain_include + + return paths.uniq + end + + def compile_defines(context:, filepath:) + # If this context exists ([:defines][context]), use it. Otherwise, default to test context. + context = TEST_SYM unless @defineinator.defines_defined?( context:context ) + + # Defines for the test file + return @defineinator.defines( context:context, filepath:filepath ) + end + + def augment_vendor_defines(filepath:, defines:) + # Start with base defines provided + _defines = defines + + # Unity defines + if filepath == File.join(PROJECT_BUILD_VENDOR_UNITY_PATH, UNITY_C_FILE) + _defines += @defineinator.defines( context:UNITY_SYM ) + + # CMock defines + elsif filepath == File.join(PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE) + _defines += @defineinator.defines( context:CMOCK_SYM ) if @configurator.project_use_mocks + + # CException defines + elsif filepath == File.join(PROJECT_BUILD_VENDOR_CEXCEPTION_PATH, CEXCEPTION_C_FILE) + _defines += @defineinator.defines( context:CEXCEPTION_SYM ) if @configurator.project_use_exceptions + end + + return _defines.uniq + end + + def preprocess_defines(test_defines:, filepath:) + # Preprocessing defines for the test file + preprocessing_defines = @defineinator.defines( context:PREPROCESS_SYM, filepath:filepath ) + + # If no preprocessing defines are present, default to the test compilation defines + return (preprocessing_defines.empty? ? test_defines : preprocessing_defines) + end + + def flags(context:, operation:, filepath:) + # If this context + operation exists ([:flags][context][operation]), use it. Otherwise, default to test context. + context = TEST_SYM unless @flaginator.flags_defined?( context:context, operation:operation ) + + return @flaginator.flag_down( context:context, operation:operation, filepath:filepath ) + end + + def collect_test_framework_sources + sources = [] + + sources << File.join(PROJECT_BUILD_VENDOR_UNITY_PATH, UNITY_C_FILE) + sources << File.join(PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE) if @configurator.project_use_mocks + sources << File.join(PROJECT_BUILD_VENDOR_CEXCEPTION_PATH, CEXCEPTION_C_FILE) if @configurator.project_use_exceptions + + # If we're (a) using mocks (b) a Unity helper is defined and (c) that unity helper includes a source file component, + # then link in the unity_helper object file too. + if ( @configurator.project_use_mocks and @configurator.cmock_unity_helper ) + @configurator.cmock_unity_helper.each do |helper| + if @file_wrapper.exist?(helper.ext(EXTENSION_SOURCE)) + sources << helper + end + end + end + + return sources end def process_deep_dependencies(files) @@ -20,13 +128,104 @@ def process_deep_dependencies(files) yield( dependencies_list ) if block_given? end - def extract_sources(test) - sources = [] - includes = @test_includes_extractor.lookup_includes_list(test) - - includes.each { |include| sources << @file_finder.find_compilation_input_file(include, :ignore) } - - return sources.compact + def extract_sources(test_filepath) + sources = [] + + # Get any additional source files specified by TEST_SOURCE_FILE() in test file + _sources = @test_context_extractor.lookup_build_directive_sources_list(test_filepath) + _sources.each do |source| + sources << @file_finder.find_compilation_input_file(source, :ignore) + end + + # Get all #include .h files from test file so we can find any source files by convention + includes = @test_context_extractor.lookup_header_includes_list(test_filepath) + includes.each do |include| + next if File.basename(include).start_with?(CMOCK_MOCK_PREFIX) # Ignore mocks in this list + sources << @file_finder.find_compilation_input_file(include, :ignore) + end + + # Remove any nil or duplicate entries in list + return sources.compact.uniq + end + + def fetch_shallow_source_includes(test_filepath) + return @test_context_extractor.lookup_source_includes_list(test_filepath) + end + + def fetch_include_search_paths_for_test_file(test_filepath) + return @test_context_extractor.lookup_include_paths_list(test_filepath) + end + + # TODO: Use search_paths to find/match header file from which to generate mock + def find_header_input_for_mock_file(mock, search_paths) + return @file_finder.find_header_input_for_mock_file(mock) + end + + def clean_test_results(path, tests) + tests.each do |test| + @file_wrapper.rm_f( Dir.glob( File.join( path, test + '.*' ) ) ) + end + end + + def generate_objects_now(object_list, context, options) + @batchinator.exec(workload: :compile, things: object_list) do |object| + src = @file_finder.find_compilation_input_file(object) + if (File.basename(src) =~ /#{EXTENSION_SOURCE}$/) + @generator.generate_object_file( + options[:test_compiler], + OPERATION_COMPILE_SYM, + context, + src, + object, + @file_path_utils.form_test_build_list_filepath( object ), + @file_path_utils.form_test_dependencies_filepath( object )) + elsif (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) + @generator.generate_object_file( + options[:test_assembler], + OPERATION_ASSEMBLE_SYM, + context, + src, + object ) + end + end + end + + # Convert libraries configuration form YAML configuration + # into a string that can be given to the compiler. + def convert_libraries_to_arguments() + args = ((@configurator.project_config_hash[:libraries_test] || []) + ((defined? LIBRARIES_SYSTEM) ? LIBRARIES_SYSTEM : [])).flatten + if (defined? LIBRARIES_FLAG) + args.map! {|v| LIBRARIES_FLAG.gsub(/\$\{1\}/, v) } + end + return args + end + + def get_library_paths_to_arguments() + paths = (defined? PATHS_LIBRARIES) ? (PATHS_LIBRARIES || []).clone : [] + if (defined? LIBRARIES_PATH_FLAG) + paths.map! {|v| LIBRARIES_PATH_FLAG.gsub(/\$\{1\}/, v) } + end + return paths + end + + def generate_executable_now(context:, build_path:, executable:, objects:, flags:, lib_args:, lib_paths:, options:) + @generator.generate_executable_file( + options[:test_linker], + context, + objects.map{|v| "\"#{v}\""}, + flags, + executable, + @file_path_utils.form_test_build_map_filepath( build_path, executable ), + lib_args, + lib_paths ) + end + + def run_fixture_now(context:, executable:, result:, options:) + @generator.generate_test_results( + tool: options[:test_fixture], + context: context, + executable: executable, + result: result) end end diff --git a/tools/vendor/ceedling/lib/ceedling/tool_executor.rb b/tools/vendor/ceedling/lib/ceedling/tool_executor.rb index 0ab5ddca..fd8ec4f7 100644 --- a/tools/vendor/ceedling/lib/ceedling/tool_executor.rb +++ b/tools/vendor/ceedling/lib/ceedling/tool_executor.rb @@ -3,44 +3,40 @@ class ShellExecutionException < RuntimeError attr_reader :shell_result - def initialize(shell_result) + def initialize(shell_result:, message:) @shell_result = shell_result + super(message) end end class ToolExecutor - constructor :configurator, :tool_executor_helper, :streaminator, :system_wrapper + constructor :configurator, :tool_executor_helper, :streaminator, :verbosinator, :system_wrapper def setup - @tool_name = '' - @executable = '' + end # build up a command line from yaml provided config - # @param extra_params is an array of parameters to append to executable + # @param extra_params is an array of parameters to append to executable (prepend to rest of command line) def build_command_line(tool_config, extra_params, *args) - @tool_name = tool_config[:name] - @executable = tool_config[:executable] - command = {} # basic premise is to iterate top to bottom through arguments using '$' as # a string replacement indicator to expand globals or inline yaml arrays # into command line arguments via substitution strings # executable must be quoted if it includes spaces (common on windows) - executable = @tool_executor_helper.osify_path_separators( expandify_element(@executable, *args) ) + executable = @tool_executor_helper.osify_path_separators( expandify_element(tool_config[:name], tool_config[:executable], *args) ) executable = "\"#{executable}\"" if executable.include?(' ') command[:line] = [ executable, extra_params.join(' ').strip, - build_arguments(tool_config[:arguments], *args), + build_arguments(tool_config[:name], tool_config[:arguments], *args), ].reject{|s| s.nil? || s.empty?}.join(' ').strip command[:options] = { - :stderr_redirect => @tool_executor_helper.stderr_redirection(tool_config, @configurator.project_logging), - :background_exec => tool_config[:background_exec] + :stderr_redirect => @tool_executor_helper.stderr_redirection(tool_config, @configurator.project_logging) } return command @@ -51,31 +47,24 @@ def build_command_line(tool_config, extra_params, *args) def exec(command, options={}, args=[]) options[:boom] = true if (options[:boom].nil?) options[:stderr_redirect] = StdErrRedirect::NONE if (options[:stderr_redirect].nil?) - options[:background_exec] = BackgroundExec::NONE if (options[:background_exec].nil?) - # build command line + + # Build command line command_line = [ - @tool_executor_helper.background_exec_cmdline_prepend( options ), command.strip, args, @tool_executor_helper.stderr_redirect_cmdline_append( options ), - @tool_executor_helper.background_exec_cmdline_append( options ), ].flatten.compact.join(' ') - @streaminator.stderr_puts("Verbose: #{__method__.to_s}(): #{command_line}", Verbosity::DEBUG) + @streaminator.stderr_puts("Verbose: #{__method__}(): #{command_line}", Verbosity::DEBUG) shell_result = {} - # depending on background exec option, we shell out differently time = Benchmark.realtime do - if (options[:background_exec] != BackgroundExec::NONE) - shell_result = @system_wrapper.shell_system( command_line, options[:boom] ) - else - shell_result = @system_wrapper.shell_backticks( command_line, options[:boom] ) - end + shell_result = @system_wrapper.shell_capture3( command_line, options[:boom] ) end shell_result[:time] = time - #scrub the string for illegal output + # Scrub the string for illegal output unless shell_result[:output].nil? shell_result[:output] = shell_result[:output].scrub if "".respond_to?(:scrub) shell_result[:output].gsub!(/\033\[\d\dm/,'') @@ -84,8 +73,10 @@ def exec(command, options={}, args=[]) @tool_executor_helper.print_happy_results( command_line, shell_result, options[:boom] ) @tool_executor_helper.print_error_results( command_line, shell_result, options[:boom] ) - # go boom if exit code isn't 0 (but in some cases we don't want a non-0 exit code to raise) - raise ShellExecutionException.new(shell_result) if ((shell_result[:exit_code] != 0) and options[:boom]) + # Go boom if exit code is not 0 and we want to debug (in some cases we don't want a non-0 exit code to raise) + if ((shell_result[:exit_code] != 0) and options[:boom]) + raise ShellExecutionException.new(shell_result: shell_result, message: "Tool exited with an error") + end return shell_result end @@ -94,26 +85,25 @@ def exec(command, options={}, args=[]) private ############################# - def build_arguments(config, *args) + def build_arguments(tool_name, config, *args) build_string = '' return nil if (config.nil?) - # iterate through each argument + # Iterate through each argument - # the yaml blob array needs to be flattened so that yaml substitution - # is handled correctly, since it creates a nested array when an anchor is - # dereferenced + # The yaml blob array needs to be flattened so that yaml substitution is handled + # correctly as it creates a nested array when an anchor is dereferenced config.flatten.each do |element| argument = '' case(element) # if we find a simple string then look for string replacement operators # and expand with the parameters in this method's argument list - when String then argument = expandify_element(element, *args) + when String then argument = expandify_element(tool_name, element, *args) # if we find a hash, then we grab the key as a substitution string and expand the # hash's value(s) within that substitution string - when Hash then argument = dehashify_argument_elements(element) + when Hash then argument = dehashify_argument_elements(tool_name, element) end build_string.concat("#{argument} ") if (argument.length > 0) @@ -126,7 +116,7 @@ def build_arguments(config, *args) # handle simple text string argument & argument array string replacement operators - def expandify_element(element, *args) + def expandify_element(tool_name, element, *args) match = // to_process = nil args_index = 0 @@ -136,7 +126,7 @@ def expandify_element(element, *args) args_index = ($2.to_i - 1) if (args.nil? or args[args_index].nil?) - @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' expected valid argument data to accompany replacement operator #{$1}.", Verbosity::ERRORS) + @streaminator.stderr_puts("ERROR: Tool '#{tool_name}' expected valid argument data to accompany replacement operator #{$1}.", Verbosity::ERRORS) raise end @@ -171,7 +161,7 @@ def expandify_element(element, *args) # handle argument hash: keys are substitution strings, values are data to be expanded within substitution strings - def dehashify_argument_elements(hash) + def dehashify_argument_elements(tool_name, hash) build_string = '' elements = [] @@ -181,7 +171,7 @@ def dehashify_argument_elements(hash) expand = hash[hash.keys[0]] if (expand.nil?) - @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' could not expand nil elements for substitution string '#{substitution}'.", Verbosity::ERRORS) + @streaminator.stderr_puts("ERROR: Tool '#{tool_name}' could not expand nil elements for substitution string '#{substitution}'.", Verbosity::ERRORS) raise end @@ -199,7 +189,7 @@ def dehashify_argument_elements(hash) elsif (@system_wrapper.constants_include?(item)) const = Object.const_get(item) if (const.nil?) - @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' found constant '#{item}' to be nil.", Verbosity::ERRORS) + @streaminator.stderr_puts("ERROR: Tool '#{tool_name}' found constant '#{item}' to be nil.", Verbosity::ERRORS) raise else elements << const @@ -207,10 +197,10 @@ def dehashify_argument_elements(hash) elsif (item.class == Array) elements << item elsif (item.class == String) - @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' cannot expand nonexistent value '#{item}' for substitution string '#{substitution}'.", Verbosity::ERRORS) + @streaminator.stderr_puts("ERROR: Tool '#{tool_name}' cannot expand nonexistent value '#{item}' for substitution string '#{substitution}'.", Verbosity::ERRORS) raise else - @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' cannot expand value having type '#{item.class}' for substitution string '#{substitution}'.", Verbosity::ERRORS) + @streaminator.stderr_puts("ERROR: Tool '#{tool_name}' cannot expand value having type '#{item.class}' for substitution string '#{substitution}'.", Verbosity::ERRORS) raise end end diff --git a/tools/vendor/ceedling/lib/ceedling/tool_executor_helper.rb b/tools/vendor/ceedling/lib/ceedling/tool_executor_helper.rb index de4cafe4..1936c683 100644 --- a/tools/vendor/ceedling/lib/ceedling/tool_executor_helper.rb +++ b/tools/vendor/ceedling/lib/ceedling/tool_executor_helper.rb @@ -24,30 +24,6 @@ def stderr_redirection(tool_config, logging) return StdErrRedirect::AUTO end - - ## - # Returns the background execution prepend based on the config. - # ==== Attributes - # - # * _tool_config_: A hash containing config information. - # - def background_exec_cmdline_prepend(tool_config) - return nil if (tool_config.nil? || tool_config[:background_exec].nil?) - - config_exec = tool_config[:background_exec] - - if ((config_exec == BackgroundExec::AUTO) and (@system_wrapper.windows?)) - return 'start' - end - - if (config_exec == BackgroundExec::WIN) - return 'start' - end - - return nil - end - - ## # Modifies an executables path based on platform. # ==== Attributes @@ -82,7 +58,6 @@ def stderr_redirect_cmdline_append(tool_config) end case redirect - # we may need more complicated processing after some learning with various environments when StdErrRedirect::NONE then nil when StdErrRedirect::WIN then '2>&1' when StdErrRedirect::UNIX then '2>&1' @@ -91,31 +66,6 @@ def stderr_redirect_cmdline_append(tool_config) end end - ## - # Returns the background execution append based on the config. - # ==== Attributes - # - # * _tool_config_: A hash containing config information. - # - def background_exec_cmdline_append(tool_config) - return nil if (tool_config.nil? || tool_config[:background_exec].nil?) - - config_exec = tool_config[:background_exec] - - # if :auto & windows, then we already prepended 'start' and should append nothing - return nil if ((config_exec == BackgroundExec::AUTO) and (@system_wrapper.windows?)) - - # if :auto & not windows, then we append standard '&' - return '&' if ((config_exec == BackgroundExec::AUTO) and (not @system_wrapper.windows?)) - - # if explicitly Unix, then append '&' - return '&' if (config_exec == BackgroundExec::UNIX) - - # * _command_str_: A hash containing config information. - # all other cases, including :none, :win, & anything unrecognized, append nothing - return nil - end - ## # Outputs success results if command succeeded and we have verbosity cranked up. # ==== Attributes diff --git a/tools/vendor/ceedling/lib/ceedling/unity_utils.rb b/tools/vendor/ceedling/lib/ceedling/unity_utils.rb new file mode 100644 index 00000000..88e8684e --- /dev/null +++ b/tools/vendor/ceedling/lib/ceedling/unity_utils.rb @@ -0,0 +1,109 @@ +# The Unity utils class, +# Store functions to enable test execution of single test case under test file +# and additional warning definitions +class UnityUtils + attr_reader :test_runner_disabled_replay, :arg_option_map + attr_accessor :test_case_incl, :test_case_excl, :not_supported + + constructor :configurator + + def setup + @test_runner_disabled_replay = "NOTICE: \n" \ + "The option[s]: %.s \ncannot be applied." \ + 'To enable it, please add `:cmdline_args` under' \ + ' :test_runner option in your project.yml.' + @test_case_incl = '' + @test_case_excl = '' + @not_supported = '' + + # Refering to Unity implementation of the parser implemented in the unit.c : + # + # case 'l': /* list tests */ + # case 'n': /* include tests with name including this string */ + # case 'f': /* an alias for -n */ + # case 'q': /* quiet */ + # case 'v': /* verbose */ + # case 'x': /* exclude tests with name including this string */ + @arg_option_map = + { + 'test_case' => 'n', + 'list_test_cases' => 'l', + 'run_tests_verbose' => 'v', + 'exclude_test_case' => 'x' + } + end + + # Create test runner args which can be passed to executable test file as + # filter to execute one test case from test file + # + # @param [String, #argument] argument passed after test file name + # e.g.: ceedling test:: + # @param [String, #option] one of the supported by unity arguments. + # At current moment only "test_case_name" to + # run single test + # + # @return String - empty if cmdline_args is not set + # In other way properly formated command line for Unity + def additional_test_run_args(argument, option) + # Confirm wherever cmdline_args is set to true + # and parsing arguments under generated test runner in Unity is enabled + # and passed argument is not nil + + return nil if argument.nil? + + raise TypeError, 'option expects an arg_option_map key' unless \ + option.is_a?(String) + raise 'Unknown Unity argument option' unless \ + @arg_option_map.key?(option) + + " -#{@arg_option_map[option]} #{argument} " + end + + # Return test case arguments + # + # @return [String] formatted arguments for test file + def collect_test_runner_additional_args + "#{@test_case_incl} #{@test_case_excl}" + end + + # Parse passed by user arguments + def create_test_runner_additional_args + if ENV['CEEDLING_INCLUDE_TEST_CASE_NAME'] + if @configurator.project_config_hash[:test_runner_cmdline_args] + @test_case_incl += additional_test_run_args( + ENV['CEEDLING_INCLUDE_TEST_CASE_NAME'], + 'test_case') + else + @not_supported += "\n\t--test_case" + end + end + + if ENV['CEEDLING_EXCLUDE_TEST_CASE_NAME'] + if @configurator.project_config_hash[:test_runner_cmdline_args] + @test_case_excl += additional_test_run_args( + ENV['CEEDLING_EXCLUDE_TEST_CASE_NAME'], + 'exclude_test_case') + else + @not_supported += "\n\t--exclude_test_case" + end + end + + if ENV['CEEDLING_EXCLUDE_TEST_CASE_NAME'] || ENV['CEEDLING_INCLUDE_TEST_CASE_NAME'] + print_warning_about_not_enabled_cmdline_args + end + end + + # Return UNITY_USE_COMMAND_LINE_ARGS define required by Unity to + # compile unity with enabled cmd line arguments + # + # @return [Array] - empty if cmdline_args is not set + def self.update_defines_if_args_enables(in_hash) + in_hash[:test_runner_cmdline_args] ? ['UNITY_USE_COMMAND_LINE_ARGS'] : [] + end + + # Print on output console warning about lack of support for single test run + # if cmdline_args is not set to true in project.yml file, that + def print_warning_about_not_enabled_cmdline_args + puts(format(@test_runner_disabled_replay, opt: @not_supported)) unless @not_supported.empty? + end +end diff --git a/tools/vendor/ceedling/lib/ceedling/version.rb b/tools/vendor/ceedling/lib/ceedling/version.rb index ebda10b7..b3cf5110 100644 --- a/tools/vendor/ceedling/lib/ceedling/version.rb +++ b/tools/vendor/ceedling/lib/ceedling/version.rb @@ -9,13 +9,13 @@ module Version # Check for local or global version of vendor directory in order to look up versions path1 = File.expand_path( File.join("..","..","vendor",path) ) path2 = File.expand_path( File.join(File.dirname(__FILE__),"..","..","vendor",path) ) - filename = if (File.exists?(path1)) + filename = if (File.exist?(path1)) path1 - elsif (File.exists?(path2)) + elsif (File.exist?(path2)) path2 - elsif File.exists?(CEEDLING_VENDOR) + elsif File.exist?(CEEDLING_VENDOR) path3 = File.expand_path( File.join(CEEDLING_VENDOR,path) ) - if (File.exists?(path3)) + if (File.exist?(path3)) path3 else basepath = File.join( CEEDLING_VENDOR, path.split(/\\\//)[0], 'release') @@ -48,7 +48,9 @@ module Version eval("#{name} = '#{a.join(".")}'") end - GEM = "0.31.1" + GEM = "0.32.0" CEEDLING = GEM + + puts CEEDLING if __FILE__ == $0 end end diff --git a/tools/vendor/ceedling/lib/ceedling/yaml_wrapper.rb b/tools/vendor/ceedling/lib/ceedling/yaml_wrapper.rb index 00ece514..d5b9355d 100644 --- a/tools/vendor/ceedling/lib/ceedling/yaml_wrapper.rb +++ b/tools/vendor/ceedling/lib/ceedling/yaml_wrapper.rb @@ -5,7 +5,20 @@ class YamlWrapper def load(filepath) - return YAML.load(ERB.new(File.read(filepath)).result) + source = ERB.new(File.read(filepath)).result + begin + return YAML.load(source, aliases: true) + rescue ArgumentError + return YAML.load(source) + end + end + + def load_string(source) + begin + return YAML.load(source, aliases: true) + rescue ArgumentError + return YAML.load(source) + end end def dump(filepath, structure) diff --git a/tools/vendor/ceedling/license.txt b/tools/vendor/ceedling/license.txt deleted file mode 100644 index ba376616..00000000 --- a/tools/vendor/ceedling/license.txt +++ /dev/null @@ -1,31 +0,0 @@ - Copyright (c) 2007-2019 Mike Karlesky, Mark VanderVoord, Greg Williams - - 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 end-user documentation included with the redistribution, if - any, must include the following acknowledgment: "This product - includes software developed for the Unity Project, by Mike Karlesky, - Mark VanderVoord, and Greg Williams and other contributors", in - the same place and form as other third-party acknowledgments. - Alternately, this acknowledgment may appear in the software - itself, in the same form and location as other such third-party - acknowledgments. - - 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. diff --git a/tools/vendor/ceedling/plugins/beep/README.md b/tools/vendor/ceedling/plugins/beep/README.md index e59d881b..09047709 100644 --- a/tools/vendor/ceedling/plugins/beep/README.md +++ b/tools/vendor/ceedling/plugins/beep/README.md @@ -8,10 +8,10 @@ it's time to pay attention again. This plugin has very few configuration options. At this time it can beep on completion of a task and/or on an error condition. For each of these, you can configure the method that it should beep. -``` -:tools: - :beep_on_done: :bell - :beep_on_error: :bell +```yaml +:beep: + :on_done: :bell + :on_error: :bell ``` Each of these have the following options: diff --git a/tools/vendor/ceedling/plugins/beep/config/defaults.yml b/tools/vendor/ceedling/plugins/beep/config/defaults.yml new file mode 100644 index 00000000..d89ffe74 --- /dev/null +++ b/tools/vendor/ceedling/plugins/beep/config/defaults.yml @@ -0,0 +1,5 @@ +--- +:beep: + :on_done: :bell + :on_error: :bell +... diff --git a/tools/vendor/ceedling/plugins/beep/lib/beep.rb b/tools/vendor/ceedling/plugins/beep/lib/beep.rb index 6a6d01ab..2a9217b7 100644 --- a/tools/vendor/ceedling/plugins/beep/lib/beep.rb +++ b/tools/vendor/ceedling/plugins/beep/lib/beep.rb @@ -1,40 +1,38 @@ require 'ceedling/plugin' -require 'ceedling/constants' +require 'beep_tools' -class Beep < Plugin - - attr_reader :config +BEEP_ROOT_NAME = 'beep'.freeze +BEEP_SYM = BEEP_ROOT_NAME.to_sym +class Beep < Plugin + def setup - @config = { - :on_done => ((defined? TOOLS_BEEP_ON_DONE) ? TOOLS_BEEP_ON_DONE : :bell ), - :on_error => ((defined? TOOLS_BEEP_ON_ERROR) ? TOOLS_BEEP_ON_ERROR : :bell ), + project_config = @ceedling[:setupinator].config_hash + @config = project_config[BEEP_SYM] + @tools = { + :beep_on_done => BEEP_TOOLS[@config[:on_done]]&.deep_clone, + :beep_on_error => BEEP_TOOLS[@config[:on_error]]&.deep_clone } + + if @tools[:beep_on_done].nil? + @ceedling[:streaminator].stderr_puts("Tool :beep_on_done is not defined.", verbosity=Verbosity::COMPLAIN) + end + + if @tools[:beep_on_error].nil? + @ceedling[:streaminator].stderr_puts("Tool :beep_on_error is not defined.", verbosity=Verbosity::COMPLAIN) + end end - + def post_build - beep @config[:on_done] + return if @tools[:beep_on_done].nil? + command = @ceedling[:tool_executor].build_command_line(@tools[:beep_on_done], []) + system(command[:line]) end - + def post_error - beep @config[:on_error] - end - - private - - def beep(method = :none) - case method - when :bell - if (SystemWrapper.windows?) - puts "echo '\007'" - else - puts "echo -ne '\007'" - end - when :speaker_test - `speaker-test -t sine -f 1000 -l 1` - else - #do nothing with illegal or :none - end + return if @tools[:beep_on_error].nil? + command = @ceedling[:tool_executor].build_command_line(@tools[:beep_on_error], []) + system(command[:line]) end + end - diff --git a/tools/vendor/ceedling/plugins/beep/lib/beep_tools.rb b/tools/vendor/ceedling/plugins/beep/lib/beep_tools.rb new file mode 100644 index 00000000..51f54d7a --- /dev/null +++ b/tools/vendor/ceedling/plugins/beep/lib/beep_tools.rb @@ -0,0 +1,23 @@ +BEEP_TOOLS = { + :bell => { + :executable => 'echo'.freeze, + :name => 'default_beep_bell'.freeze, + :stderr_redirect => StdErrRedirect::NONE.freeze, + :optional => false.freeze, + :arguments => [ + *('-ne'.freeze unless SystemWrapper.windows?), + "\x07".freeze + ].freeze + }.freeze, + :speaker_test => { + :executable => 'speaker-test'.freeze, + :name => 'default_beep_speaker_test'.freeze, + :stderr_redirect => StdErrRedirect::NONE.freeze, + :optional => false.freeze, + :arguments => [ + - '-t sine'.freeze, + - '-f 1000'.freeze, + - '-l 1'.freeze + ].freeze + }.freeze +}.freeze diff --git a/tools/vendor/ceedling/plugins/bullseye/bullseye.rake b/tools/vendor/ceedling/plugins/bullseye/bullseye.rake index 11073e78..1fd4b36f 100644 --- a/tools/vendor/ceedling/plugins/bullseye/bullseye.rake +++ b/tools/vendor/ceedling/plugins/bullseye/bullseye.rake @@ -70,13 +70,22 @@ end task :directories => [BULLSEYE_BUILD_OUTPUT_PATH, BULLSEYE_RESULTS_PATH, BULLSEYE_DEPENDENCIES_PATH, BULLSEYE_ARTIFACTS_PATH] namespace BULLSEYE_SYM do + + TOOL_COLLECTION_BULLSEYE_TASKS = { + :context => BULLSEYE_SYM, + :test_compiler => TOOLS_BULLSEYE_COMPILER, + :test_assembler => TOOLS_TEST_ASSEMBLER, + :test_linker => TOOLS_BULLSEYE_LINKER, + :test_fixture => TOOLS_BULLSEYE_FIXTURE + } + task source_coverage: COLLECTION_ALL_SOURCE.pathmap("#{BULLSEYE_BUILD_OUTPUT_PATH}/%n#{@ceedling[:configurator].extension_object}") desc 'Run code coverage for all tests' task all: [:test_deps] do @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) @ceedling[BULLSEYE_SYM].enableBullseye(true) - @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, BULLSEYE_SYM) + @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, TOOL_COLLECTION_BULLSEYE_TASKS) @ceedling[:configurator].restore_config end @@ -100,7 +109,7 @@ namespace BULLSEYE_SYM do if !matches.empty? @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) @ceedling[BULLSEYE_SYM].enableBullseye(true) - @ceedling[:test_invoker].setup_and_invoke(matches, BULLSEYE_SYM, force_run: false) + @ceedling[:test_invoker].setup_and_invoke(matches, { force_run: false }.merge(TOOL_COLLECTION_BULLSEYE_TASKS)) @ceedling[:configurator].restore_config else @ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.") @@ -118,7 +127,7 @@ namespace BULLSEYE_SYM do if !matches.empty? @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) @ceedling[BULLSEYE_SYM].enableBullseye(true) - @ceedling[:test_invoker].setup_and_invoke(matches, BULLSEYE_SYM, force_run: false) + @ceedling[:test_invoker].setup_and_invoke(matches, { force_run: false }.merge(TOOL_COLLECTION_BULLSEYE_TASKS)) @ceedling[:configurator].restore_config else @ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.") @@ -129,7 +138,7 @@ namespace BULLSEYE_SYM do task delta: [:test_deps] do @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) @ceedling[BULLSEYE_SYM].enableBullseye(true) - @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, BULLSEYE_SYM, {:force_run => false}) + @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, {:force_run => false}.merge(TOOL_COLLECTION_BULLSEYE_TASKS)) @ceedling[:configurator].restore_config end @@ -145,7 +154,7 @@ namespace BULLSEYE_SYM do @ceedling[:rake_wrapper][:test_deps].invoke @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) @ceedling[BULLSEYE_SYM].enableBullseye(true) - @ceedling[:test_invoker].setup_and_invoke([test.source], BULLSEYE_SYM) + @ceedling[:test_invoker].setup_and_invoke([test.source], TOOL_COLLECTION_BULLSEYE_TASKS) @ceedling[:configurator].restore_config end diff --git a/tools/vendor/ceedling/plugins/bullseye/lib/bullseye.rb b/tools/vendor/ceedling/plugins/bullseye/lib/bullseye.rb index ffa444ac..19fd425b 100644 --- a/tools/vendor/ceedling/plugins/bullseye/lib/bullseye.rb +++ b/tools/vendor/ceedling/plugins/bullseye/lib/bullseye.rb @@ -26,6 +26,7 @@ def setup def config { :project_test_build_output_path => BULLSEYE_BUILD_OUTPUT_PATH, + :project_test_build_output_c_path => BULLSEYE_BUILD_OUTPUT_PATH, :project_test_results_path => BULLSEYE_RESULTS_PATH, :project_test_dependencies_path => BULLSEYE_DEPENDENCIES_PATH, :defines_test => DEFINES_TEST + ['CODE_COVERAGE'], diff --git a/tools/vendor/ceedling/plugins/compile_commands_json/lib/compile_commands_json.rb b/tools/vendor/ceedling/plugins/compile_commands_json/lib/compile_commands_json.rb index 269cea4d..b04999f3 100644 --- a/tools/vendor/ceedling/plugins/compile_commands_json/lib/compile_commands_json.rb +++ b/tools/vendor/ceedling/plugins/compile_commands_json/lib/compile_commands_json.rb @@ -5,7 +5,7 @@ class CompileCommandsJson < Plugin def setup @fullpath = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, "compile_commands.json") - @database = if (File.exists?(@fullpath)) + @database = if (File.exist?(@fullpath) && File.size(@fullpath) > 0) JSON.parse( File.read(@fullpath) ) else [] diff --git a/tools/vendor/ceedling/plugins/dependencies/dependencies.rake b/tools/vendor/ceedling/plugins/dependencies/dependencies.rake index 08a1a48e..87ab4b95 100644 --- a/tools/vendor/ceedling/plugins/dependencies/dependencies.rake +++ b/tools/vendor/ceedling/plugins/dependencies/dependencies.rake @@ -24,7 +24,7 @@ DEPENDENCIES_LIBRARIES.each do |deplib| # We double-check that it doesn't already exist, because this process sometimes # produces multiple files, but they may have already been flagged as invoked - unless (File.exists?(path)) + unless (File.exist?(path)) # Set Environment Variables, Fetch, and Build @ceedling[DEPENDENCIES_SYM].set_env_if_required(path) diff --git a/tools/vendor/ceedling/plugins/dependencies/lib/dependencies.rb b/tools/vendor/ceedling/plugins/dependencies/lib/dependencies.rb index fc8ae996..d6c00872 100644 --- a/tools/vendor/ceedling/plugins/dependencies/lib/dependencies.rb +++ b/tools/vendor/ceedling/plugins/dependencies/lib/dependencies.rb @@ -137,7 +137,7 @@ def fetch_if_required(lib_path) when :custom blob[:fetch][:executable] else - raise "Unknown fetch method '#{blob[:fetch][:method].to_s}' for dependency '#{blob[:name]}'" + raise "Unknown fetch method '#{blob[:fetch][:method]}' for dependency '#{blob[:name]}'" end # Perform the actual fetching diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/LICENSE b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/LICENSE new file mode 100644 index 00000000..7b3129bd --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/LICENSE @@ -0,0 +1,25 @@ +/* +LICENSE + +The MIT License (MIT) + +Copyright (c) 2010 Michael Long + +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. +*/ \ No newline at end of file diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/Makefile b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/Makefile new file mode 100644 index 00000000..a774e0b5 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/Makefile @@ -0,0 +1,10 @@ +all: + mkdir -p build + cd gtest; $(MAKE) all + cd test; $(MAKE) all + cd examples; $(MAKE) all + +clean: + cd gtest; $(MAKE) clean + cd test; $(MAKE) clean + cd examples; $(MAKE) clean diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/README.md b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/README.md new file mode 100644 index 00000000..d91bec47 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/README.md @@ -0,0 +1,454 @@ +# Fake Function Framework (fff) +----------------------------- +> How long can we _maintain_? I wonder. How long before one of us starts raving +> and jabbering at this boy? What will he think then? This same lonely desert +> was the last known home of the Manson family. Will he make that grim +> connection... + +## A Fake Function Framework for C +fff is a micro-framework for creating fake C functions for tests. Because life +is too short to spend time hand-writing fake functions for testing. + + +## Hello fake world! + +Say you are testing an embedded user interface and you have a function that +you want to create a fake for: + + // UI.c + ... + void DISPLAY_init(); + ... + +Here's how you would define a fake function for this in your test suite: + + // test.c(pp) + #include "fff.h" + DEFINE_FFF_GLOBALS; + FAKE_VOID_FUNC(DISPLAY_init); + +And the unit test might look something like this: + + TEST_F(GreeterTests, init_initialises_display) + { + UI_init(); + ASSERT_EQ(DISPLAY_init_fake.call_count, 1); + } + +So what has happened here? The first thing to note is that the framework is +header only, all you need to do to use it is download fff.h and include +it in your test suite. + +The magic is in the FAKE_VOID_FUNC. This +expands a macro that defines a function returning void +which has zero arguments. It also defines a struct +"function_name"_fake which contains all the information about the fake. +For instance, DISPLAY_init_fake.call_countis incremented every time the faked +function is called. + +Under the hood it generates a struct that looks like this: + + typedef struct DISPLAY_init_Fake { + unsigned int call_count; + unsigned int arg_history_len; + unsigned int arg_histories_dropped; + void(*custom_fake)(); + } DISPLAY_init_Fake; + DISPLAY_init_Fake DISPLAY_init_fake; + + + + + +## Capturing arguments + +Ok, enough with the toy examples. What about faking functions with arguments? + + // UI.c + ... + void DISPLAY_output(char * message); + ... + +Here's how you would define a fake function for this in your test suite: + + FAKE_VOID_FUNC(DISPLAY_output, char *); + +And the unit test might look something like this: + + TEST_F(UITests, write_line_outputs_lines_to_display) + { + char msg[] = "helloworld"; + UI_write_line(msg); + ASSERT_EQ(DISPLAY_output_fake.call_count, 1); + ASSERT_EQ(strncmp(DISPLAY_output_fake.arg0_val, msg, 26), 0); + } + + +There is no more magic here, the FAKE_VOID_FUNC works as in the +previous example. The number of arguments that the function takes is calculated, + and the macro arguments following the function name defines the argument +type (a char pointer in this example). + +A variable is created for every argument in the form +"function_name"fake.argN_val + + + +## Return values + +When you want to define a fake function that returns a value, you should use the +FAKE_VALUE_FUNC macro. For instance: + + // UI.c + ... + unsigned int DISPLAY_get_line_capacity(); + unsigned int DISPLAY_get_line_insert_index(); + ... + +Here's how you would define fake functions for these in your test suite: + + FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_capacity); + FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_insert_index); + +And the unit test might look something like this: + + TEST_F(UITests, when_empty_lines_write_line_doesnt_clear_screen) + { + // given + DISPLAY_get_line_insert_index_fake.return_val = 1; + char msg[] = "helloworld"; + // when + UI_write_line(msg); + // then + ASSERT_EQ(DISPLAY_clear_fake.call_count, 0); + } + +Of course you can mix and match these macros to define a value function with +arguments, for instance to fake: + + double pow(double base, double exponent); + +you would use a syntax like this: + + FAKE_VALUE_FUNC(double, pow, double, double); + + + +## Resetting a fake + +Good tests are isolated tests, so it is important to reset the fakes for each +unit test. All the fakes have a reset function to reset their arguments and +call counts. It is good prectice is to call the reset function for all the +fakes in the setup function of your test suite. + + void setup() + { + // Register resets + RESET_FAKE(DISPLAY_init); + RESET_FAKE(DISPLAY_clear); + RESET_FAKE(DISPLAY_output_message); + RESET_FAKE(DISPLAY_get_line_capacity); + RESET_FAKE(DISPLAY_get_line_insert_index); + } + +You might want to define a macro to do this: + +``` +/* List of fakes used by this unit tester */ +#define FFF_FAKES_LIST(FAKE) \ + FAKE(DISPLAY_init) \ + FAKE(DISPLAY_clear) \ + FAKE(DISPLAY_output_message) \ + FAKE(DISPLAY_get_line_capacity) \ + FAKE(DISPLAY_get_line_insert_index) + +void setup() +{ + /* Register resets */ + FFF_FAKES_LIST(RESET_FAKE); + + /* reset common FFF internal structures */ + FFF_RESET_HISTORY(); +} +``` + +## Call history +Say you want to test that a function calls functionA, then functionB, then +functionA again, how would you do that? Well fff maintains a call +history so that it is easy to assert these expectations. + +Here's how it works: + + FAKE_VOID_FUNC(voidfunc2, char, char); + FAKE_VALUE_FUNC(long, longfunc0); + + TEST_F(FFFTestSuite, calls_in_correct_order) + { + longfunc0(); + voidfunc2(); + longfunc0(); + + ASSERT_EQ(fff.call_history[0], (void *)longfunc0); + ASSERT_EQ(fff.call_history[1], (void *)voidfunc2); + ASSERT_EQ(fff.call_history[2], (void *)longfunc0); + } + +They are reset by calling FFF_RESET_HISTORY(); + + +## Default Argument History + +The framework will by default store the arguments for the last ten calls made +to a fake function. + + TEST_F(FFFTestSuite, when_fake_func_called_then_arguments_captured_in_history) + { + voidfunc2('g', 'h'); + voidfunc2('i', 'j'); + ASSERT_EQ('g', voidfunc2_fake.arg0_history[0]); + ASSERT_EQ('h', voidfunc2_fake.arg1_history[0]); + ASSERT_EQ('i', voidfunc2_fake.arg0_history[1]); + ASSERT_EQ('j', voidfunc2_fake.arg1_history[1]); + } + +There are two ways to find out if calls have been dropped. The first is to +check the dropped histories counter: + + TEST_F(FFFTestSuite, when_fake_func_called_max_times_plus_one_then_one_argument_history_dropped) + { + int i; + for(i = 0; i < 10; i++) + { + voidfunc2('1'+i, '2'+i); + } + voidfunc2('1', '2'); + ASSERT_EQ(1u, voidfunc2_fake.arg_histories_dropped); + } + +The other is to check if the call count is greater than the history size: + + ASSERT(voidfunc2_fake.arg_history_len < voidfunc2_fake.call_count); + +The argument histories for a fake function are reset when the RESET_FAKE +function is called + +## User Defined Argument History + +If you wish to control how many calls to capture for argument history you can +override the default by defining it before include the fff.h like this: + + // Want to keep the argument history for 13 calls + #define FFF_ARG_HISTORY_LEN 13 + // Want to keep the call sequence history for 17 function calls + #define FFF_CALL_HISTORY_LEN 17 + + #include "../fff.h" + + +## Function Return Value Sequences + +Often in testing we would like to test the behaviour of sequence of function call +events. One way to do this with fff is to specify a sequence of return values +with for the fake function. It is probably easier to describe with an example: + + // faking "long longfunc();" + FAKE_VALUE_FUNC(long, longfunc0); + + TEST_F(FFFTestSuite, return_value_sequences_exhausted) + { + long myReturnVals[3] = { 3, 7, 9 }; + SET_RETURN_SEQ(longfunc0, myReturnVals, 3); + ASSERT_EQ(myReturnVals[0], longfunc0()); + ASSERT_EQ(myReturnVals[1], longfunc0()); + ASSERT_EQ(myReturnVals[2], longfunc0()); + ASSERT_EQ(myReturnVals[2], longfunc0()); + ASSERT_EQ(myReturnVals[2], longfunc0()); + } + +By specifying a return value sequence using the SET_RETURN_SEQ macro, +the fake will return the values given in the parameter array in sequence. When +the end of the sequence is reached the fake will continue to return the last +value in the sequence indefinitely. + +## Custom Return Value Delegate + +You can specify your own function to provide the return value for the fake. This +is done by setting the custom_fake member of the fake. Here's an example: + + #define MEANING_OF_LIFE 42 + long my_custom_value_fake(void) + { + return MEANING_OF_LIFE; + } + TEST_F(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_return_value) + { + longfunc0_fake.custom_fake = my_custom_value_fake; + long retval = longfunc0(); + ASSERT_EQ(MEANING_OF_LIFE, retval); + } + +## How do I fake a function that returns a value by reference? +The basic mechanism that FFF provides you in this case is the custom_fake field described in the *Custom Return Value Delegate* example above. + +You need to create a custom function (e.g. getTime_custom_fake) to produce the output optionally by use of a helper variable (e.g. getTime_custom_now) to retrieve that output from. Then some creativity to tie it all together. The most important part (IMHO) is to keep your test case readable and maintainable. + +In case your project uses a C99 compliant C compiler you can even combine all this in a single unit test function so you can easily oversee all details of the test. See the example below. + + /* The time structure */ + typedef struct { + int hour, min; + } Time; + + /* Our fake function */ + FAKE_VOID_FUNC(getTime, Time*); + + /* A test using the getTime fake function */ + TEST_F(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_output) + { + Time t; + Time getTime_custom_now; + void getTime_custom_fake(Time *now) { + *now = getTime_custom_now; + } + getTime_fake.custom_fake = getTime_custom_fake; + + /* given a specific time */ + getTime_custom_now.hour = 13; + getTime_custom_now.min = 05; + + /* when getTime is called */ + getTime(&t); + + /* then the specific time must be produced */ + ASSERT_EQ(t.hour, 13); + ASSERT_EQ(t.min, 05); + } + +## How do I fake a function with a function pointer parameter? +Using FFF to stub functions that have function pointer parameter can cause problems when trying to stub them. Presented here is an example how to deal with this situation. + +If you need to stub a function that has a function pointer parameter, e.g. something like: + +``` +/* timer.h */ +typedef int timer_handle; +extern int timer_start(timer_handle handle, long delay, void (*cb_function) (int arg), int arg); +``` + +Then creating a fake like below will horribly fail when trying to compile because the FFF macro will internally expand into an illegal variable ```int (*)(int) arg2_val```. + +``` +/* The fake, attempt one */ +FAKE_VALUE_FUNC(int, + timer_start, + timer_handle, + long, + void (*) (int argument), + int); +``` + +The solution to this problem is to create a bridging type that needs only to be visible in the unit tester. The fake will use that intermediate type. This way the compiler will not complain because the types match. + +``` +/* Additional type needed to be able to use callback in FFF */ +typedef void (*timer_cb) (int argument); + +/* The fake, attempt two */ +FAKE_VALUE_FUNC(int, + timer_start, + timer_handle, + long, + timer_cb, + int); +``` + +Here are some ideas how to create a test case with callbacks. + +``` +/* Unit test */ +TEST_F(FFFTestSuite, test_fake_with_function_pointer) +{ + int cb_timeout_called = 0; + int result = 0; + + void cb_timeout(int argument) + { + cb_timeout_called++; + } + + int timer_start_custom_fake(timer_handle handle, + long delay, + void (*cb_function) (int arg), + int arg) + { + if (cb_function) cb_function(arg); + return timer_start_fake.return_val; + } + + /* given the custom fake for timer_start */ + timer_start_fake.return_val = 33; + timer_start_fake.custom_fake = timer_start_custom_fake; + + /* when timer_start is called + * (actually you would call your own function-under-test + * that would then call the fake function) + */ + result = timer_start(10, 100, cb_timeout, 55); + + /* then the timer_start fake must have been called correctly */ + ASSERT_EQ(result, 33); + ASSERT_EQ(timer_start_fake.call_count, 1); + ASSERT_EQ(timer_start_fake.arg0_val, 10); + ASSERT_EQ(timer_start_fake.arg1_val, 100); + ASSERT_EQ(timer_start_fake.arg2_val, cb_timeout); /* callback provided by unit tester */ + ASSERT_EQ(timer_start_fake.arg3_val, 55); + + /* and ofcourse our custom fake correctly calls the registered callback */ + ASSERT_EQ(cb_timeout_called, 1); +} +``` + +## Find out more... + +Look under the examlples directory for full length examples in both C and C++. +There is also a test suite for the framework under the test directory. + +------------------------- + +## Benefits +So whats the point? + + * To make it easy to create fake functions for testing C code. + * It is simple - just include a header file and you are good to go. + * To work in both C and C++ test environments + + +## Under the hood: + * The fff.h header file is generated by a ruby script + * There are tests under src/test + * There is an example for testing an embedded UI and a hardware driver under src/examples + + +## Cheat Sheet + + + + + + + + + + + + + + + + + + + + + +
MacroDescriptionExample
FAKE_VOID_FUNC(fn [,arg_types*]);Define a fake function named fn returning void with n argumentsFAKE_VOID_FUNC(DISPLAY_output_message, const char*);
FAKE_VALUE_FUNC(return_type, fn [,arg_types*]);Define a fake function returning a value with type return_type taking n argumentsFAKE_VALUE_FUNC(int, DISPLAY_get_line_insert_index);
RESET_FAKE(fn);Reset the state of fake function called fnRESET_FAKE(DISPLAY_init);
\ No newline at end of file diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/buildandtest b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/buildandtest new file mode 100644 index 00000000..b7fecb6b --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/buildandtest @@ -0,0 +1,15 @@ +#!/bin/bash +set -e + +cat LICENSE > fff.h +ruby fakegen.rb >> fff.h +make clean +make all +build/fff_test_c +build/fff_test_cpp --gtest_output=xml:build/test_results.xml +build/ui_test_ansic +build/ui_test_cpp --gtest_output=xml:build/example_results.xml +build/fff_test_glob_c +build/fff_test_glob_cpp --gtest_output=xml:build/test_global_results.xml +build/driver_testing --gtest_output=xml:build/driver_testing.xml +build/driver_testing_fff --gtest_output=xml:build/driver_testing_fff.xml diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/Makefile b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/Makefile new file mode 100644 index 00000000..f352de31 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/Makefile @@ -0,0 +1,7 @@ +all: + cd embedded_ui; $(MAKE) all + cd driver_testing; $(MAKE) all + +clean: + cd embedded_ui; $(MAKE) clean + cd driver_testing; $(MAKE) clean diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/Makefile b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/Makefile new file mode 100644 index 00000000..e32faafd --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/Makefile @@ -0,0 +1,64 @@ +$(VERBOSE).SILENT: + +BUILD_DIR = ../../build +TEMPLATE_PROGNAME = $(BUILD_DIR)/template +CPP_PROGNAME_NOFFF = $(BUILD_DIR)/driver_testing +CPP_PROGNAME_FFF = $(BUILD_DIR)/driver_testing_fff +CC = gcc +CC += -c +CPP = g++ +CPP += -c +LD = g++ + +GTEST_OBJS = $(BUILD_DIR)/gtest-all.o $(BUILD_DIR)/gtest-main.o +C_OBJFILES = $(BUILD_DIR)/driver.o +TEMPLATE_OBJFILES = $(BUILD_DIR)/test_suite_template.o +FFF_OBJFILES = $(BUILD_DIR)/driver.test.fff.o $(GTEST_OBJS) +NOFFF_OBJFILES = $(BUILD_DIR)/driver.test.o $(GTEST_OBJS) +CPP_LIBS = -lpthread + + +all: $(CPP_PROGNAME_NOFFF) $(CPP_PROGNAME_FFF) $(TEMPLATE_PROGNAME) + +.PHONY: clean + +clean: + @echo "Cleaning object files" + @echo " rm -f $(BUILD_DIR)/*.o" + rm -f $(BUILD_DIR)/*.o + @echo "Cleaning backups" + @echo " rm -f *~" + rm -f *~ + @echo "Removing programs" + @echo " rm -f $(CPP_PROGNAME_NOFFF) $(CPP_PROGNAME_FFF) $(TEMPLATE_PROGNAME)" + rm -f $(CPP_PROGNAME_NOFFF) $(CPP_PROGNAME_FFF) $(TEMPLATE_PROGNAME) + + +$(BUILD_DIR)/%.o: %.c + @echo "Compiling "$@ + @echo " CC "$< + $(CC) -o $@ $< -DTESTING + +$(BUILD_DIR)/%.o: %.cpp + @echo "Compiling "$@ + @echo " CPP "$< + $(CPP) -DGTEST_USE_OWN_TR1_TUPLE=1 -I../.. -o $@ $< -DTESTING + +$(TEMPLATE_PROGNAME): $(TEMPLATE_OBJFILES) + @echo "Linking "$@ + @echo " LD -o "ctemplate" "$(TEMPLATE_OBJFILES) + $(LD) -o $(TEMPLATE_PROGNAME) $(TEMPLATE_OBJFILES) + +$(CPP_PROGNAME_FFF): $(FFF_OBJFILES) $(C_OBJFILES) + @echo "Linking "$@ + @echo " LD -o "$(CPP_PROGNAME_FFF)" "$(FFF_OBJFILES) + $(LD) -o $(CPP_PROGNAME_FFF) $(FFF_OBJFILES) $(C_OBJFILES) $(CPP_LIBS) + +$(CPP_PROGNAME_NOFFF): $(NOFFF_OBJFILES) $(C_OBJFILES) + @echo "Linking "$@ + @echo " LD -o "$(CPP_PROGNAME_NOFFF)" "$(NOFFF_OBJFILES) + $(LD) -o $(CPP_PROGNAME_NOFFF) $(NOFFF_OBJFILES) $(C_OBJFILES) $(CPP_LIBS) + +nothing: + @echo "Nothing to do; quitting :(" + @echo "HINT: Try make all" diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.c b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.c new file mode 100644 index 00000000..9454ba6f --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.c @@ -0,0 +1,24 @@ + + +#include "hardware_abstraction.h" +#include "registers.h" + +void driver_write(uint8_t val) +{ + IO_MEM_WR8(DRIVER_OUTPUT_REGISTER, val); +} + +uint8_t driver_read() +{ + return IO_MEM_RD8(DRIVER_INPUT_REGISTER); +} + +void driver_init_device() +{ + uint8_t hw_version = IO_MEM_RD8(HARDWARE_VERSION_REGISTER); + if(HARDWARE_REV_B == hw_version) + { + IO_MEM_WR8(DRIVER_PERIPHERAL_ENABLE_REG, 1); + } + IO_MEM_WR8(DRIVER_PERIPHERAL_INITIALIZE_REG, 1); +} diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.h new file mode 100644 index 00000000..b7406d41 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.h @@ -0,0 +1,11 @@ + +#ifndef DRIVER +#define DRIVER + +#include + +void driver_write(uint8_t val); +uint8_t driver_read(); +void driver_init_device(); + +#endif /*include guard*/ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.test.cpp b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.test.cpp new file mode 100644 index 00000000..2df07027 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.test.cpp @@ -0,0 +1,50 @@ +extern "C" +{ +#include "driver.h" +#include "registers.h" +} +#include "../../fff.h" +#include + + +extern "C" +{ + static uint8_t readVal; + static int readCalled; + static uint32_t readRegister; + uint8_t IO_MEM_RD8(uint32_t reg) + { + readRegister = reg; + readCalled++; + return readVal; + } + + static uint32_t writeRegister; + static uint8_t writeVal; + static int writeCalled; + void IO_MEM_WR8(uint32_t reg, uint8_t val) + { + writeRegister = reg; + writeVal = val; + writeCalled++; + } +} + +TEST(Driver, When_writing_Then_writes_data_to_DRIVER_OUTPUT_REGISTER) +{ + driver_write(0x34); + ASSERT_EQ(1u, writeCalled); + ASSERT_EQ(0x34u, writeVal); + ASSERT_EQ(DRIVER_OUTPUT_REGISTER, writeRegister); +} + + +TEST(Driver, When_reading_data_Then_reads_from_DRIVER_INPUT_REGISTER) +{ + readVal = 0x55; + uint8_t returnedValue = driver_read(); + ASSERT_EQ(1u, readCalled); + ASSERT_EQ(0x55u, returnedValue); + ASSERT_EQ(readRegister, DRIVER_INPUT_REGISTER); +} + diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.test.fff.cpp b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.test.fff.cpp new file mode 100644 index 00000000..d8aeb06f --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/driver.test.fff.cpp @@ -0,0 +1,62 @@ +extern "C"{ + #include "driver.h" + #include "registers.h" +} +#include "../../fff.h" +#include + +DEFINE_FFF_GLOBALS; + +FAKE_VOID_FUNC(IO_MEM_WR8, uint32_t, uint8_t); +FAKE_VALUE_FUNC(uint8_t, IO_MEM_RD8, uint32_t); + +class DriverTestFFF : public testing::Test +{ +public: + void SetUp() + { + RESET_FAKE(IO_MEM_WR8); + RESET_FAKE(IO_MEM_RD8); + FFF_RESET_HISTORY(); + } + +}; + +TEST_F(DriverTestFFF, When_writing_Then_writes_data_to_DRIVER_OUTPUT_REGISTER) +{ + driver_write(0x34); + ASSERT_EQ(1u, IO_MEM_WR8_fake.call_count); + ASSERT_EQ(0x34u, IO_MEM_WR8_fake.arg1_val); + ASSERT_EQ(DRIVER_OUTPUT_REGISTER, IO_MEM_WR8_fake.arg0_val); +} + + +TEST_F(DriverTestFFF, When_reading_data_Then_reads_from_DRIVER_INPUT_REGISTER) +{ + IO_MEM_RD8_fake.return_val = 0x55; + uint8_t returnedValue = driver_read(); + ASSERT_EQ(1u, IO_MEM_RD8_fake.call_count); + ASSERT_EQ(0x55u, returnedValue); + ASSERT_EQ(IO_MEM_RD8_fake.arg0_val, DRIVER_INPUT_REGISTER); +} + +TEST_F(DriverTestFFF, Given_revisionB_device_When_initialize_Then_enable_peripheral_before_initializing_it) +{ + // Given + IO_MEM_RD8_fake.return_val = HARDWARE_REV_B; + // When + driver_init_device(); + + //Then + // Gets the hardware revision + ASSERT_EQ((void*) IO_MEM_RD8, fff.call_history[0]); + ASSERT_EQ(HARDWARE_VERSION_REGISTER, IO_MEM_RD8_fake.arg0_history[0]); + // Enables Peripheral + ASSERT_EQ((void*) IO_MEM_WR8, fff.call_history[1]); + ASSERT_EQ(DRIVER_PERIPHERAL_ENABLE_REG, IO_MEM_WR8_fake.arg0_history[0]); + ASSERT_EQ(1, IO_MEM_WR8_fake.arg1_history[0]); + // Initializes Peripheral + ASSERT_EQ((void*) IO_MEM_WR8, fff.call_history[2]); + ASSERT_EQ(DRIVER_PERIPHERAL_INITIALIZE_REG,IO_MEM_WR8_fake.arg0_history[1]); + ASSERT_EQ(1, IO_MEM_WR8_fake.arg1_history[1]); +} diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/hardware_abstraction.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/hardware_abstraction.h new file mode 100644 index 00000000..affa92ed --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/hardware_abstraction.h @@ -0,0 +1,15 @@ +#ifndef HARDWARE_ABSTRACTION +#define HARDWARE_ABSTRACTION + +#include + +#ifndef TESTING +#define IO_MEM_RD8(ADDR) (*((volatile uint8_t *)(ADDR))) +#define IO_MEM_WR8(ADDR, VAL_8) (*((volatile uint8_t *)(ADDR)) = (VAL_8)) +#else +/* In testing use fake functions to record calls to IO memory */ +uint8_t IO_MEM_RD8(uint32_t reg); +void IO_MEM_WR8(uint32_t reg, uint8_t val); +#endif + +#endif /* Include guard */ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/registers.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/registers.h new file mode 100644 index 00000000..5c9e5a9c --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/driver_testing/registers.h @@ -0,0 +1,13 @@ +#ifndef REGISTERS_H_ +#define REGISTERS_H_ + +#define DRIVER_OUTPUT_REGISTER 0xFFAAu +#define DRIVER_INPUT_REGISTER 0XFFABu +#define DRIVER_PERIPHERAL_ENABLE_REG 0xFFACu +#define DRIVER_PERIPHERAL_INITIALIZE_REG 0xFFACu + +#define HARDWARE_VERSION_REGISTER 0xFF00u +#define HARDWARE_REV_A 0x00u +#define HARDWARE_REV_B 0x01u + +#endif /* REGISTERS_H_ */ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/DISPLAY.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/DISPLAY.h new file mode 100644 index 00000000..45ca62e7 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/DISPLAY.h @@ -0,0 +1,17 @@ +/* + * DISPLAY.h + * + * Created on: Dec 17, 2010 + * Author: mlong + */ + +#ifndef DISPLAY_H_ +#define DISPLAY_H_ + +void DISPLAY_init(); +void DISPLAY_clear(); +unsigned int DISPLAY_get_line_capacity(); +unsigned int DISPLAY_get_line_insert_index(); +void DISPLAY_output(char * message); + +#endif /* DISPLAY_H_ */ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/Kata.txt b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/Kata.txt new file mode 100644 index 00000000..b466c364 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/Kata.txt @@ -0,0 +1,25 @@ + +Problem Definition +------------------ +The task is to write a user interface module for an embedded device. + +Interrupts: + * The user interface is responsible for initializing the display. + * The user interface will register an interrupt handler for GPIO input 2 (a + push button). + * It will be possible to register a callback function for button presses. + * When there is no callback function set the irq handler will increment a + missed irq counter. + * When the interrupt occurs the handler will schedule or execute the button + press callback if there is one registered. +Output: + * Tasks can write messages to the user interface to be output on the display. + * The display is line oriented; when the last line of the display is written + the user interface is responsible for clearing the display. + * The display is 26 characters wide. Any string longer than that must be + truncated before being sent to the display. The string must be null + terminated and thus maximum 27 bytes long. + + * BONUS: Have the display be scrolling, i.e. when the display is full, the + previous lines must be shifted up one and the new line written in the bottom + line. diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/Makefile b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/Makefile new file mode 100644 index 00000000..654beecc --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/Makefile @@ -0,0 +1,67 @@ +$(VERBOSE).SILENT: + +BUILD_DIR = ../../build +TEMPLATE_PROGNAME = $(BUILD_DIR)/template +C_PROGNAME = $(BUILD_DIR)/ui_test_ansic +CPP_PROGNAME = $(BUILD_DIR)/ui_test_cpp +CC = gcc +CC += -c +CPP = g++ +CPP += -c +LD = g++ + +GTEST_OBJS = $(BUILD_DIR)/gtest-all.o $(BUILD_DIR)/gtest-main.o +C_OBJFILES = $(BUILD_DIR)/UI_test_ansic.o $(BUILD_DIR)/UI.o +TEMPLATE_OBJFILES = $(BUILD_DIR)/test_suite_template.o +CPP_OBJFILES = $(BUILD_DIR)/UI_test_cpp.o $(BUILD_DIR)/UI.o $(GTEST_OBJS) +CPP_LIBS = -lpthread + + +all: $(C_PROGNAME) $(CPP_PROGNAME) $(TEMPLATE_PROGNAME) + +.PHONY: clean + +clean: + @echo "Cleaning object files" + @echo " rm -f $(BUILD_DIR)/*.o" + rm -f $(BUILD_DIR)/*.o + @echo "Cleaning backups" + @echo " rm -f *~" + rm -f *~ + @echo "Removing programs" + @echo " rm -f "$(C_PROGNAME) + rm -f $(C_PROGNAME) + @echo " rm -f "$(CPP_PROGNAME) $(TEMPLATE_PROGNAME) + rm -f $(CPP_PROGNAME) $(TEMPLATE_PROGNAME) + + +$(BUILD_DIR)/%.o: %.c + @echo "Compiling "$@ + @echo " CC "$< + $(CC) -o $@ $< + +$(BUILD_DIR)/%.o: %.cpp + @echo "Compiling "$@ + @echo " CPP "$< + $(CPP) -DGTEST_USE_OWN_TR1_TUPLE=1 -I../.. -o $@ $< + +$(TEMPLATE_PROGNAME): $(TEMPLATE_OBJFILES) + @echo "Linking "$@ + @echo " LD -o "ctemplate" "$(TEMPLATE_OBJFILES) + $(LD) -o $(TEMPLATE_PROGNAME) $(TEMPLATE_OBJFILES) + +$(C_PROGNAME): $(C_OBJFILES) + @echo "Linking "$@ + @echo " LD -o "$(C_PROGNAME)" "$(C_OBJFILES) + $(LD) -o $(C_PROGNAME) $(C_OBJFILES) + +$(CPP_PROGNAME): $(CPP_OBJFILES) $(C_OBJFILES) + @echo "Linking "$@ + @echo " LD -o "$(CPP_PROGNAME)" "$(CPP_OBJFILES) + $(LD) -o $(CPP_PROGNAME) $(CPP_OBJFILES) $(CPP_LIBS) + + + +nothing: + @echo "Nothing to do; quitting :(" + @echo "HINT: Try make all" diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/SYSTEM.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/SYSTEM.h new file mode 100644 index 00000000..080144fc --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/SYSTEM.h @@ -0,0 +1,21 @@ +/* + * DISPLAY.h + * + * Created on: Dec 17, 2010 + * Author: mlong + */ + +#ifndef SYSTEM_H_ +#define SYSTEM_H_ + +typedef void (*irq_func_t)(void); + +#define IRQ_GPIO_0 0x70 +#define IRQ_GPIO_1 0x71 +#define IRQ_GPIO_2 0x72 +#define IRQ_GPIO_3 0x73 + + +void SYSTEM_register_irq(irq_func_t, unsigned int irq); + +#endif /* SYSTEM_H_ */ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI.c b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI.c new file mode 100644 index 00000000..8ce996e6 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI.c @@ -0,0 +1,48 @@ +#include "UI.h" +#include "DISPLAY.h" +#include "SYSTEM.h" +#include + +static unsigned int missed_irq_counter; +button_cbk_t button_cbk; + + +void UI_init() +{ + DISPLAY_init(); + SYSTEM_register_irq(UI_button_irq_handler, IRQ_GPIO_2); + button_cbk = 0; + missed_irq_counter = 0; +} + +unsigned int UI_get_missed_irqs() +{ + return missed_irq_counter; +} + +void UI_button_irq_handler() +{ + if(button_cbk) + { + button_cbk(); + } + else + { + missed_irq_counter++; + } +} + +void UI_register_button_cbk(button_cbk_t cbk) +{ + button_cbk = cbk; +} + +void UI_write_line(char *line) +{ + static char out[27]; + strncpy(out, line, 26); + out[26] = '\0'; + if(DISPLAY_get_line_capacity() == DISPLAY_get_line_insert_index()) + DISPLAY_clear(); + DISPLAY_output(out); +} diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI.h new file mode 100644 index 00000000..8a3fb5c5 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI.h @@ -0,0 +1,12 @@ +#ifndef UI_H_ +#define UI_H_ + +typedef void (*button_cbk_t)(void); + +void UI_init(); +unsigned int UI_get_missed_irqs(); +void UI_button_irq_handler(); +void UI_register_button_cbk(button_cbk_t cbk); +void UI_write_line(char *line); + +#endif /* UI_H_ */ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI_test_ansic.c b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI_test_ansic.c new file mode 100644 index 00000000..f98e4098 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI_test_ansic.c @@ -0,0 +1,183 @@ +#include "UI.h" +#include "../../fff.h" +#include "SYSTEM.h" +#include "DISPLAY.h" + +#include +#include +#include + +/* Test Framework :-) */ +void setup(); +#define TEST_F(SUITE, NAME) void NAME() +#define RUN_TEST(SUITE, TESTNAME) printf(" Running %s.%s: \n", #SUITE, #TESTNAME); setup(); TESTNAME(); printf(" SUCCESS\n"); + +DEFINE_FFF_GLOBALS; + +/* SYSTEM.h */ +FAKE_VOID_FUNC2(SYSTEM_register_irq, irq_func_t, unsigned int); +/* DISPLAY.h */ +FAKE_VOID_FUNC(DISPLAY_init); +FAKE_VOID_FUNC(DISPLAY_clear); +FAKE_VOID_FUNC(DISPLAY_output, char *); +FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_capacity); +FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_insert_index); + +FAKE_VOID_FUNC0(button_press_cbk); + + + +/* Initialializers called for every test */ +void setup() +{ + RESET_FAKE(SYSTEM_register_irq); + + RESET_FAKE(DISPLAY_init) + RESET_FAKE(DISPLAY_clear) + RESET_FAKE(DISPLAY_output) + RESET_FAKE(DISPLAY_get_line_capacity) + RESET_FAKE(DISPLAY_get_line_insert_index); + + RESET_FAKE(button_press_cbk); + + FFF_RESET_HISTORY(); + + DISPLAY_get_line_capacity_fake.return_val = 2; +} + +/* Tests go here */ +TEST_F(UITests, init_will_initialise_display) +{ + UI_init(); + assert(DISPLAY_init_fake.call_count == 1); +} + +TEST_F(UITests, init_will_register_interrupt_gpio2) +{ + UI_init(); + assert(SYSTEM_register_irq_fake.call_count == 1); + assert(SYSTEM_register_irq_fake.arg0_val == UI_button_irq_handler); + assert(SYSTEM_register_irq_fake.arg1_val == IRQ_GPIO_2); +} + +TEST_F(UITests, when_no_irq_then_missed_irq_counter_zero) +{ + assert(UI_get_missed_irqs() == 0); +} + +TEST_F(UITests, when_one_irq_and_no_handler_then_missed_irq_counter_one) +{ + UI_button_irq_handler(); + assert(UI_get_missed_irqs() == 1); +} + +TEST_F(UITests, when_one_irq_and_valid_callback_then_missed_irq_counter_zero) +{ + UI_init(); + UI_register_button_cbk(button_press_cbk); + UI_button_irq_handler(); + assert(UI_get_missed_irqs() == 0); +} + +TEST_F(UITests, when_one_irq_and_valid_callback_then_callback_called) +{ + UI_register_button_cbk(button_press_cbk); + UI_button_irq_handler(); + assert(button_press_cbk_fake.call_count == 1); +} + +TEST_F(UITests, write_line_outputs_lines_to_display) +{ + char msg[] = "helloworld"; + UI_write_line(msg); + assert(DISPLAY_output_fake.call_count == 1); + assert(strncmp(DISPLAY_output_fake.arg0_val, msg, 26) == 0); +} + +TEST_F(UITests, when_no_empty_lines_write_line_clears_screen_and_outputs_lines_to_display) +{ + DISPLAY_get_line_insert_index_fake.return_val = 2; + char msg[] = "helloworld"; + + UI_write_line(msg); + + assert(DISPLAY_clear_fake.call_count == 1); + assert(DISPLAY_output_fake.call_count == 1); + // Check the order of the calls: Don't care about the first two: + // DISPLAY_get_line_capacity and DISPLAY_get_line_insert_index + assert(fff.call_history_idx == 4); + assert(fff.call_history[2] == (void *) DISPLAY_clear); + assert(fff.call_history[3] == (void *) DISPLAY_output); +} + +TEST_F(UITests, when_empty_lines_write_line_doesnt_clear_screen) +{ + // given + DISPLAY_get_line_insert_index_fake.return_val = 1; + char msg[] = "helloworld"; + // when + UI_write_line(msg); + // then + assert(DISPLAY_clear_fake.call_count == 0); +} + +TEST_F(UITests, when_string_longer_than_26_then_truncated_string_output) +{ + // given + char input[] = "abcdefghijklmnopqrstuvwxyz0123456789"; + char expected[] = "abcdefghijklmnopqrstuvwxyz"; + // when + UI_write_line(input); + // then + assert(strncmp(expected, DISPLAY_output_fake.arg0_val, 37) == 0); +} + +TEST_F(UITests, when_outputting_to_full_display_then_previous_inserted) +{ + // given + DISPLAY_get_line_insert_index_fake.return_val = 1; + char oldest[] = "oldest"; + char newest[] = "newest"; + // when + UI_write_line(oldest); + UI_write_line(newest); + // then + + assert(DISPLAY_output_fake.call_count == 2); + + // fills last line + assert(strncmp(oldest, DISPLAY_output_fake.arg0_history[0], 37) == 0); + //clears + assert(DISPLAY_clear_fake.call_count == 1); + // inserts old line at first + assert(strncmp(oldest, DISPLAY_output_fake.arg0_history[1], 37) == 0); + // then inserts new line + assert(strncmp(newest, DISPLAY_output_fake.arg0_history[2], 37) == 0); +} + +int main() +{ + setbuf(stdout, NULL); + fprintf(stdout, "-------------\n"); + fprintf(stdout, "Running Tests\n"); + fprintf(stdout, "-------------\n\n"); + fflush(0); + + /* Run tests */ + RUN_TEST(UITests, init_will_initialise_display); + RUN_TEST(UITests, init_will_register_interrupt_gpio2); + RUN_TEST(UITests, when_no_irq_then_missed_irq_counter_zero); + RUN_TEST(UITests, when_one_irq_and_no_handler_then_missed_irq_counter_one); + RUN_TEST(UITests, when_one_irq_and_valid_callback_then_missed_irq_counter_zero); + RUN_TEST(UITests, when_one_irq_and_valid_callback_then_callback_called); + RUN_TEST(UITests, write_line_outputs_lines_to_display); + RUN_TEST(UITests, when_no_empty_lines_write_line_clears_screen_and_outputs_lines_to_display); + RUN_TEST(UITests, when_empty_lines_write_line_doesnt_clear_screen); + RUN_TEST(UITests, when_string_longer_than_26_then_truncated_string_output); + + printf("\n-------------\n"); + printf("Complete\n"); + printf("-------------\n\n"); + + return 0; +} diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI_test_cpp.cpp b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI_test_cpp.cpp new file mode 100644 index 00000000..ecd9deff --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/UI_test_cpp.cpp @@ -0,0 +1,136 @@ +extern "C"{ +#include "UI.h" +#include "SYSTEM.h" +#include "DISPLAY.h" +} +#include + + +#include "../../fff.h" +DEFINE_FFF_GLOBALS; + +/* SYSTEM.h */ +FAKE_VOID_FUNC(SYSTEM_register_irq, irq_func_t, unsigned int); +/* DISPLAY.h */ +FAKE_VOID_FUNC(DISPLAY_init); +FAKE_VOID_FUNC(DISPLAY_clear); +FAKE_VOID_FUNC(DISPLAY_output, char *); +FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_capacity); +FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_insert_index); + +FAKE_VOID_FUNC(button_press_cbk); + + +class UITests : public testing::Test +{ +public: + + void SetUp() + { + // Register resets + RESET_FAKE(SYSTEM_register_irq); + + RESET_FAKE(DISPLAY_init) + RESET_FAKE(DISPLAY_clear) + RESET_FAKE(DISPLAY_output) + RESET_FAKE(DISPLAY_get_line_capacity) + RESET_FAKE(DISPLAY_get_line_insert_index); + + RESET_FAKE(button_press_cbk); + + FFF_RESET_HISTORY(); + // non default init + DISPLAY_get_line_capacity_fake.return_val = 2; + } +}; + + + +/* Tests go here */ +TEST_F(UITests, init_will_initialise_display) +{ + UI_init(); + ASSERT_EQ(DISPLAY_init_fake.call_count, 1); +} + +TEST_F(UITests, init_will_register_interrupt_gpio2) +{ + UI_init(); + ASSERT_EQ(SYSTEM_register_irq_fake.call_count, 1); + ASSERT_EQ((void *)SYSTEM_register_irq_fake.arg0_val, (void *)UI_button_irq_handler); + ASSERT_EQ(SYSTEM_register_irq_fake.arg1_val, IRQ_GPIO_2); +} + +TEST_F(UITests, when_no_irq_then_missed_irq_counter_zero) +{ + ASSERT_EQ(UI_get_missed_irqs(), 0); +} + +TEST_F(UITests, when_one_irq_and_no_handler_then_missed_irq_counter_one) +{ + UI_button_irq_handler(); + ASSERT_EQ(UI_get_missed_irqs(), 1); +} + +TEST_F(UITests, when_one_irq_and_valid_callback_then_missed_irq_counter_zero) +{ + UI_init(); + UI_register_button_cbk(button_press_cbk); + UI_button_irq_handler(); + ASSERT_EQ(UI_get_missed_irqs(), 0); +} + +TEST_F(UITests, when_one_irq_and_valid_callback_then_callback_called) +{ + UI_register_button_cbk(button_press_cbk); + UI_button_irq_handler(); + ASSERT_EQ(button_press_cbk_fake.call_count, 1); +} + +TEST_F(UITests, write_line_outputs_lines_to_display) +{ + char msg[] = "helloworld"; + UI_write_line(msg); + ASSERT_EQ(DISPLAY_output_fake.call_count, 1); + ASSERT_EQ(strncmp(DISPLAY_output_fake.arg0_val, msg, 26), 0); +} + +TEST_F(UITests, when_no_empty_lines_write_line_clears_screen_and_outputs_lines_to_display) +{ + DISPLAY_get_line_insert_index_fake.return_val = 2; + char msg[] = "helloworld"; + + UI_write_line(msg); + + ASSERT_EQ(DISPLAY_clear_fake.call_count, 1); + ASSERT_EQ(DISPLAY_output_fake.call_count, 1); + // Check the order of the calls: Don't care about the first two: + // DISPLAY_get_line_capacity and DISPLAY_get_line_insert_index + ASSERT_EQ(fff.call_history_idx, 4); + ASSERT_EQ(fff.call_history[2], (void *) DISPLAY_clear); + ASSERT_EQ(fff.call_history[3], (void *) DISPLAY_output); +} + +TEST_F(UITests, when_empty_lines_write_line_doesnt_clear_screen) +{ + // given + DISPLAY_get_line_insert_index_fake.return_val = 1; + char msg[] = "helloworld"; + // when + UI_write_line(msg); + // then + ASSERT_EQ(DISPLAY_clear_fake.call_count, 0); +} + +TEST_F(UITests, when_string_longer_than_26_then_truncated_string_output) +{ + // given + char input[] = "abcdefghijklmnopqrstuvwxyz0123456789"; + char expected[] = "abcdefghijklmnopqrstuvwxyz"; + // when + UI_write_line(input); + // then + ASSERT_EQ(strncmp(expected, DISPLAY_output_fake.arg0_val, 37), 0); +} + + diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/test_suite_template.c b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/test_suite_template.c new file mode 100644 index 00000000..00df5bb2 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/examples/embedded_ui/test_suite_template.c @@ -0,0 +1,34 @@ +#include "../../test/c_test_framework.h" + +/* Initialializers called for every test */ +void setup() +{ + +} + +/* Tests go here */ +TEST_F(GreeterTests, hello_world) +{ + assert(1 == 0); +} + + + +int main() +{ + setbuf(stderr, NULL); + fprintf(stdout, "-------------\n"); + fprintf(stdout, "Running Tests\n"); + fprintf(stdout, "-------------\n\n"); + fflush(0); + + /* Run tests */ + RUN_TEST(GreeterTests, hello_world); + + + printf("\n-------------\n"); + printf("Complete\n"); + printf("-------------\n\n"); + + return 0; +} diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/fakegen.rb b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/fakegen.rb new file mode 100644 index 00000000..96a02eac --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/fakegen.rb @@ -0,0 +1,420 @@ + +# fakegen.rb +# A simple code generator to create some C macros for defining test fake functions + + +$cpp_output = true +$MAX_ARGS = 20 +$DEFAULT_ARG_HISTORY = 50 +$MAX_CALL_HISTORY = 50 + +def output_constants + putd "#define FFF_MAX_ARGS (#{$MAX_ARGS}u)" + putd "#ifndef FFF_ARG_HISTORY_LEN" + putd " #define FFF_ARG_HISTORY_LEN (#{$DEFAULT_ARG_HISTORY}u)" + putd "#endif" + putd "#ifndef FFF_CALL_HISTORY_LEN" + putd " #define FFF_CALL_HISTORY_LEN (#{$MAX_CALL_HISTORY}u)" + putd "#endif" +end + + + + + +# ------ Helper macros to use internally ------ # +def output_internal_helper_macros + putd "/* -- INTERNAL HELPER MACROS -- */" + + define_return_sequence_helper + define_reset_fake_macro + define_declare_arg_helper + define_declare_all_func_common_helper + define_save_arg_helper + define_room_for_more_history + define_save_arg_history_helper + define_history_dropped_helper + define_value_function_variables_helper + define_increment_call_count_helper + define_return_fake_result_helper + define_extern_c_helper + define_reset_fake_helper + + putd "/* -- END INTERNAL HELPER MACROS -- */" + putd "" +end + +def define_return_sequence_helper + putd "#define SET_RETURN_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \\" + putd " FUNCNAME##_fake.return_val_seq = ARRAY_POINTER; \\" + putd " FUNCNAME##_fake.return_val_seq_len = ARRAY_LEN;" +end + +def define_reset_fake_macro + putd "" + putd "/* Defining a function to reset a fake function */" + putd "#define RESET_FAKE(FUNCNAME) { \\" + putd " FUNCNAME##_reset(); \\" + putd "} \\" + putd "" +end + +def define_declare_arg_helper + putd "" + putd "#define DECLARE_ARG(type, n, FUNCNAME) \\" + putd " type arg##n##_val; \\" + putd " type arg##n##_history[FFF_ARG_HISTORY_LEN];" +end + +def define_declare_all_func_common_helper + putd "" + putd "#define DECLARE_ALL_FUNC_COMMON \\" + putd " unsigned int call_count; \\" + putd " unsigned int arg_history_len;\\" + putd " unsigned int arg_histories_dropped; \\" +end + +def define_save_arg_helper + putd "" + putd "#define SAVE_ARG(FUNCNAME, n) \\" + putd " memcpy((void*)&FUNCNAME##_fake.arg##n##_val, (void*)&arg##n, sizeof(arg##n));" +end + +def define_room_for_more_history + putd "" + putd "#define ROOM_FOR_MORE_HISTORY(FUNCNAME) \\" + putd " FUNCNAME##_fake.call_count < FFF_ARG_HISTORY_LEN" +end + +def define_save_arg_history_helper + putd "" + putd "#define SAVE_ARG_HISTORY(FUNCNAME, ARGN) \\" + putd " memcpy((void*)&FUNCNAME##_fake.arg##ARGN##_history[FUNCNAME##_fake.call_count], (void*)&arg##ARGN, sizeof(arg##ARGN));" +end + +def define_history_dropped_helper + putd "" + putd "#define HISTORY_DROPPED(FUNCNAME) \\" + putd " FUNCNAME##_fake.arg_histories_dropped++" +end + +def define_value_function_variables_helper + putd "" + putd "#define DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \\" + putd " RETURN_TYPE return_val; \\" + putd " int return_val_seq_len; \\" + putd " int return_val_seq_idx; \\" + putd " RETURN_TYPE * return_val_seq; \\" +end + +def define_increment_call_count_helper + putd "" + putd "#define INCREMENT_CALL_COUNT(FUNCNAME) \\" + putd " FUNCNAME##_fake.call_count++" +end + +def define_return_fake_result_helper + putd "" + putd "#define RETURN_FAKE_RESULT(FUNCNAME) \\" + putd " if (FUNCNAME##_fake.return_val_seq_len){ /* then its a sequence */ \\" + putd " if(FUNCNAME##_fake.return_val_seq_idx < FUNCNAME##_fake.return_val_seq_len) { \\" + putd " return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx++]; \\" + putd " } \\" + putd " return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]; /* return last element */ \\" + putd " } \\" + putd " return FUNCNAME##_fake.return_val; \\" +end + +def define_extern_c_helper + putd "" + putd "#ifdef __cplusplus" + putd " #define FFF_EXTERN_C extern \"C\"{" + putd " #define FFF_END_EXTERN_C } " + putd "#else /* ansi c */" + putd " #define FFF_EXTERN_C " + putd " #define FFF_END_EXTERN_C " + putd "#endif /* cpp/ansi c */" +end + +def define_reset_fake_helper + putd "" + putd "#define DEFINE_RESET_FUNCTION(FUNCNAME) \\" + putd " void FUNCNAME##_reset(){ \\" + putd " memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake)); \\" + putd " FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN;\\" + putd " }" +end +# ------ End Helper macros ------ # + +#fakegen helpers to print at levels of indentation +$current_depth = 0 +def putd(str) + $current_depth.times {|not_used| print " "} + puts str +end + +def pushd + $current_depth = $current_depth + 4 +end + +def popd + $current_depth = $current_depth - 4 +end + +def output_macro(arg_count, has_varargs, is_value_function) + + vararg_name = has_varargs ? "_VARARG" : "" + fake_macro_name = is_value_function ? "FAKE_VALUE_FUNC#{arg_count}#{vararg_name}" : "FAKE_VOID_FUNC#{arg_count}#{vararg_name}" + declare_macro_name = "DECLARE_#{fake_macro_name}" + define_macro_name = "DEFINE_#{fake_macro_name}" + saved_arg_count = arg_count - (has_varargs ? 1 : 0) + return_type = is_value_function ? "RETURN_TYPE" : "" + + putd "" + output_macro_header(declare_macro_name, saved_arg_count, has_varargs, return_type) + pushd + extern_c { # define argument capture variables + output_variables(saved_arg_count, has_varargs, is_value_function) + } + popd + + putd "" + output_macro_header(define_macro_name, saved_arg_count, has_varargs, return_type) + pushd + extern_c { + putd "FUNCNAME##_Fake FUNCNAME##_fake;\\" + putd function_signature(saved_arg_count, has_varargs, is_value_function) + "{ \\" + pushd + output_function_body(saved_arg_count, has_varargs, is_value_function) + popd + putd "} \\" + putd "DEFINE_RESET_FUNCTION(FUNCNAME) \\" + } + popd + + putd "" + + output_macro_header(fake_macro_name, saved_arg_count, has_varargs, return_type) + pushd + putd macro_signature_for(declare_macro_name, saved_arg_count, has_varargs, return_type) + putd macro_signature_for(define_macro_name, saved_arg_count, has_varargs, return_type) + putd "" + popd +end + +def output_macro_header(macro_name, arg_count, has_varargs, return_type) + output_macro_name(macro_name, arg_count, has_varargs, return_type) +end + +# #define #macro_name(RETURN_TYPE, FUNCNAME, ARG0,...) +def output_macro_name(macro_name, arg_count, has_varargs, return_type) + putd "#define " + macro_signature_for(macro_name, arg_count, has_varargs, return_type) +end + +# #macro_name(RETURN_TYPE, FUNCNAME, ARG0,...) +def macro_signature_for(macro_name, arg_count, has_varargs, return_type) + parameter_list = "#{macro_name}(" + if return_type != "" + parameter_list += return_type + parameter_list += ", " + end + parameter_list += "FUNCNAME" + + arg_count.times { |i| parameter_list += ", ARG#{i}_TYPE" } + + parameter_list += ", ..." if has_varargs + + parameter_list += ") \\" + + parameter_list +end + +def output_argument_capture_variables(argN) + putd " DECLARE_ARG(ARG#{argN}_TYPE, #{argN}, FUNCNAME) \\" +end + +def output_variables(arg_count, has_varargs, is_value_function) + in_struct{ + arg_count.times { |argN| + putd "DECLARE_ARG(ARG#{argN}_TYPE, #{argN}, FUNCNAME) \\" + } + putd "DECLARE_ALL_FUNC_COMMON \\" + putd "DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \\" unless not is_value_function + output_custom_function_signature(arg_count, has_varargs, is_value_function) + } + putd "extern FUNCNAME##_Fake FUNCNAME##_fake;\\" + putd "void FUNCNAME##_reset(); \\" +end + +#example: ARG0_TYPE arg0, ARG1_TYPE arg1 +def arg_val_list(args_count) + arguments = [] + args_count.times { |i| arguments << "ARG#{i}_TYPE arg#{i}" } + arguments.join(", ") +end + +#example: arg0, arg1 +def arg_list(args_count) + arguments = [] + args_count.times { |i| arguments << "arg#{i}" } + arguments.join(", ") +end + +# RETURN_TYPE (*custom_fake)(ARG0_TYPE arg0);\ +# void (*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2);\ +def output_custom_function_signature(arg_count, has_varargs, is_value_function) + return_type = is_value_function ? "RETURN_TYPE" : "void" + signature = "(*custom_fake)(#{arg_val_list(arg_count)}); \\" + putd return_type + signature +end + +# example: RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1) +def function_signature(arg_count, has_varargs, is_value_function) + return_type = is_value_function ? "RETURN_TYPE" : "void" + varargs = has_varargs ? ", ..." : "" + "#{return_type} FUNCNAME(#{arg_val_list(arg_count)}#{varargs})" +end + +def output_function_body(arg_count, has_varargs, is_value_function) + arg_count.times { |i| putd "SAVE_ARG(FUNCNAME, #{i}); \\" } + putd "if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\\" + arg_count.times { |i| putd " SAVE_ARG_HISTORY(FUNCNAME, #{i}); \\" } + putd "}\\" + putd "else{\\" + putd " HISTORY_DROPPED(FUNCNAME);\\" + putd "}\\" + putd "INCREMENT_CALL_COUNT(FUNCNAME); \\" + putd "REGISTER_CALL(FUNCNAME); \\" + + return_type = is_value_function ? "return" : "" + putd "if (FUNCNAME##_fake.custom_fake) #{return_type} FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)}); \\" + + putd "RETURN_FAKE_RESULT(FUNCNAME) \\" if is_value_function +end + +def output_reset_function(arg_count, is_value_function) + putd "void FUNCNAME##_reset(){ \\" + putd " memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake)); \\" + putd " FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN;\\" + putd "} \\" +end + +def define_fff_globals + putd "typedef struct { " + putd " void * call_history[FFF_CALL_HISTORY_LEN];" + putd " unsigned int call_history_idx;" + putd "} fff_globals_t;" + putd "" + putd "FFF_EXTERN_C \\" + putd "extern fff_globals_t fff;" + putd "FFF_END_EXTERN_C \\" + putd "" + putd "#define DEFINE_FFF_GLOBALS \\" + putd " FFF_EXTERN_C \\" + putd " fff_globals_t fff; \\" + putd " FFF_END_EXTERN_C" + putd "" + putd "#define FFF_RESET_HISTORY() fff.call_history_idx = 0;" + putd "" + putd "#define REGISTER_CALL(function) \\" + putd " if(fff.call_history_idx < FFF_CALL_HISTORY_LEN) \\" + putd " fff.call_history[fff.call_history_idx++] = (void *)function;" +end + +def extern_c + putd "FFF_EXTERN_C \\" + pushd + yield + popd + putd "FFF_END_EXTERN_C \\" +end + +def in_struct + putd "typedef struct FUNCNAME##_Fake { \\" + pushd + yield + popd + putd "} FUNCNAME##_Fake;\\" +end + +def include_guard + putd "#ifndef FAKE_FUNCTIONS" + putd "#define FAKE_FUNCTIONS" + putd "" + + yield + + putd "" + putd "#endif /* FAKE_FUNCTIONS */" +end + +def output_macro_counting_shortcuts + putd <<-MACRO_COUNTING + +#define PP_NARG_MINUS2(...) \ + PP_NARG_MINUS2_(__VA_ARGS__, PP_RSEQ_N_MINUS2()) + +#define PP_NARG_MINUS2_(...) \ + PP_ARG_MINUS2_N(__VA_ARGS__) + +#define PP_ARG_MINUS2_N(returnVal, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, N, ...) N + +#define PP_RSEQ_N_MINUS2() \ + 19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 + + +#define FAKE_VALUE_FUNC(...) \ + FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define FUNC_VALUE_(N,...) \ + FUNC_VALUE_N(N,__VA_ARGS__) + +#define FUNC_VALUE_N(N,...) \ + FAKE_VALUE_FUNC ## N(__VA_ARGS__) + + + +#define PP_NARG_MINUS1(...) \ + PP_NARG_MINUS1_(__VA_ARGS__, PP_RSEQ_N_MINUS1()) + +#define PP_NARG_MINUS1_(...) \ + PP_ARG_MINUS1_N(__VA_ARGS__) + +#define PP_ARG_MINUS1_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N + +#define PP_RSEQ_N_MINUS1() \ + 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 + +#define FAKE_VOID_FUNC(...) \ + FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define FUNC_VOID_(N,...) \ + FUNC_VOID_N(N,__VA_ARGS__) + +#define FUNC_VOID_N(N,...) \ + FAKE_VOID_FUNC ## N(__VA_ARGS__) + + MACRO_COUNTING +end + +def output_c_and_cpp + + include_guard { + output_constants + output_internal_helper_macros + yield + output_macro_counting_shortcuts + } +end + +# lets generate!! +output_c_and_cpp{ + define_fff_globals + # Create fake generators for 0..MAX_ARGS + num_fake_generators = $MAX_ARGS + 1 + num_fake_generators.times {|arg_count| output_macro(arg_count, false, false)} + num_fake_generators.times {|arg_count| output_macro(arg_count, false, true)} + # generate the varargs variants + (2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, false)} + (2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, true)} +} diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/fff.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/fff.h new file mode 100644 index 00000000..19b0d7f4 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/fff.h @@ -0,0 +1,5112 @@ +/* +LICENSE + +The MIT License (MIT) + +Copyright (c) 2010 Michael Long + +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. +*/#ifndef FAKE_FUNCTIONS +#define FAKE_FUNCTIONS + +#define FFF_MAX_ARGS (20u) +#ifndef FFF_ARG_HISTORY_LEN + #define FFF_ARG_HISTORY_LEN (50u) +#endif +#ifndef FFF_CALL_HISTORY_LEN + #define FFF_CALL_HISTORY_LEN (50u) +#endif +/* -- INTERNAL HELPER MACROS -- */ +#define SET_RETURN_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \ + FUNCNAME##_fake.return_val_seq = ARRAY_POINTER; \ + FUNCNAME##_fake.return_val_seq_len = ARRAY_LEN; + +/* Defining a function to reset a fake function */ +#define RESET_FAKE(FUNCNAME) { \ + FUNCNAME##_reset(); \ +} \ + + +#define DECLARE_ARG(type, n, FUNCNAME) \ + type arg##n##_val; \ + type arg##n##_history[FFF_ARG_HISTORY_LEN]; + +#define DECLARE_ALL_FUNC_COMMON \ + unsigned int call_count; \ + unsigned int arg_history_len;\ + unsigned int arg_histories_dropped; \ + +#define SAVE_ARG(FUNCNAME, n) \ + memcpy((void*)&FUNCNAME##_fake.arg##n##_val, (void*)&arg##n, sizeof(arg##n)); + +#define ROOM_FOR_MORE_HISTORY(FUNCNAME) \ + FUNCNAME##_fake.call_count < FFF_ARG_HISTORY_LEN + +#define SAVE_ARG_HISTORY(FUNCNAME, ARGN) \ + memcpy((void*)&FUNCNAME##_fake.arg##ARGN##_history[FUNCNAME##_fake.call_count], (void*)&arg##ARGN, sizeof(arg##ARGN)); + +#define HISTORY_DROPPED(FUNCNAME) \ + FUNCNAME##_fake.arg_histories_dropped++ + +#define DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE return_val; \ + int return_val_seq_len; \ + int return_val_seq_idx; \ + RETURN_TYPE * return_val_seq; \ + +#define INCREMENT_CALL_COUNT(FUNCNAME) \ + FUNCNAME##_fake.call_count++ + +#define RETURN_FAKE_RESULT(FUNCNAME) \ + if (FUNCNAME##_fake.return_val_seq_len){ /* then its a sequence */ \ + if(FUNCNAME##_fake.return_val_seq_idx < FUNCNAME##_fake.return_val_seq_len) { \ + return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx++]; \ + } \ + return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]; /* return last element */ \ + } \ + return FUNCNAME##_fake.return_val; \ + +#ifdef __cplusplus + #define FFF_EXTERN_C extern "C"{ + #define FFF_END_EXTERN_C } +#else /* ansi c */ + #define FFF_EXTERN_C + #define FFF_END_EXTERN_C +#endif /* cpp/ansi c */ + +#define DEFINE_RESET_FUNCTION(FUNCNAME) \ + void FUNCNAME##_reset(){ \ + memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake)); \ + FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN;\ + } +/* -- END INTERNAL HELPER MACROS -- */ + +typedef struct { + void * call_history[FFF_CALL_HISTORY_LEN]; + unsigned int call_history_idx; +} fff_globals_t; + +FFF_EXTERN_C \ +extern fff_globals_t fff; +FFF_END_EXTERN_C \ + +#define DEFINE_FFF_GLOBALS \ + FFF_EXTERN_C \ + fff_globals_t fff; \ + FFF_END_EXTERN_C + +#define FFF_RESET_HISTORY() fff.call_history_idx = 0; + +#define REGISTER_CALL(function) \ + if(fff.call_history_idx < FFF_CALL_HISTORY_LEN) \ + fff.call_history[fff.call_history_idx++] = (void *)function; + +#define DECLARE_FAKE_VOID_FUNC0(FUNCNAME) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC0(FUNCNAME) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(){ \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC0(FUNCNAME) \ + DECLARE_FAKE_VOID_FUNC0(FUNCNAME) \ + DEFINE_FAKE_VOID_FUNC0(FUNCNAME) \ + + +#define DECLARE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0){ \ + SAVE_ARG(FUNCNAME, 0); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + DECLARE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + DEFINE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + DECLARE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + DEFINE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + DECLARE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + DEFINE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + DECLARE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + DEFINE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + DECLARE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + DEFINE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + DECLARE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + DEFINE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + DECLARE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + DEFINE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + DECLARE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + DEFINE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + DECLARE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + DEFINE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + DECLARE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + DEFINE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + DECLARE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + DEFINE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + DECLARE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + DEFINE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + DECLARE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + DEFINE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + DECLARE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + DEFINE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + DECLARE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + DEFINE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + DECLARE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + DEFINE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + DECLARE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + DEFINE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + DECLARE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + DEFINE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + DECLARE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + DEFINE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ARG(ARG19_TYPE, 19, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + SAVE_ARG(FUNCNAME, 19); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + SAVE_ARG_HISTORY(FUNCNAME, 19); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + DECLARE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + DEFINE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(){ \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + DECLARE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + DEFINE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + + +#define DECLARE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0){ \ + SAVE_ARG(FUNCNAME, 0); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + DECLARE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + DEFINE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + DECLARE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + DEFINE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + DECLARE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + DEFINE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + DECLARE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + DEFINE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + DECLARE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + DEFINE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + DECLARE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + DEFINE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + DECLARE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + DEFINE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + DECLARE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + DEFINE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + DECLARE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + DEFINE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + DECLARE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + DEFINE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + DECLARE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + DEFINE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + DECLARE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + DEFINE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + DECLARE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + DEFINE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + DECLARE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + DEFINE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + DECLARE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + DEFINE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + DECLARE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + DEFINE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + DECLARE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + DEFINE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + DECLARE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + DEFINE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + DECLARE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + DEFINE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ARG(ARG19_TYPE, 19, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + SAVE_ARG(FUNCNAME, 19); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + SAVE_ARG_HISTORY(FUNCNAME, 19); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + DECLARE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + DEFINE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + FFF_EXTERN_C \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \ + } FUNCNAME##_Fake;\ + extern FUNCNAME##_Fake FUNCNAME##_fake;\ + void FUNCNAME##_reset(); \ + FFF_END_EXTERN_C \ + +#define DEFINE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + FFF_EXTERN_C \ + FUNCNAME##_Fake FUNCNAME##_fake;\ + RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + }\ + else{\ + HISTORY_DROPPED(FUNCNAME);\ + }\ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + FFF_END_EXTERN_C \ + +#define FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + + +#define PP_NARG_MINUS2(...) PP_NARG_MINUS2_(__VA_ARGS__, PP_RSEQ_N_MINUS2()) + +#define PP_NARG_MINUS2_(...) PP_ARG_MINUS2_N(__VA_ARGS__) + +#define PP_ARG_MINUS2_N(returnVal, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, N, ...) N + +#define PP_RSEQ_N_MINUS2() 19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 + + +#define FAKE_VALUE_FUNC(...) FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define FUNC_VALUE_(N,...) FUNC_VALUE_N(N,__VA_ARGS__) + +#define FUNC_VALUE_N(N,...) FAKE_VALUE_FUNC ## N(__VA_ARGS__) + + + +#define PP_NARG_MINUS1(...) PP_NARG_MINUS1_(__VA_ARGS__, PP_RSEQ_N_MINUS1()) + +#define PP_NARG_MINUS1_(...) PP_ARG_MINUS1_N(__VA_ARGS__) + +#define PP_ARG_MINUS1_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N + +#define PP_RSEQ_N_MINUS1() 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 + +#define FAKE_VOID_FUNC(...) FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define FUNC_VOID_(N,...) FUNC_VOID_N(N,__VA_ARGS__) + +#define FUNC_VOID_N(N,...) FAKE_VOID_FUNC ## N(__VA_ARGS__) + + +#endif /* FAKE_FUNCTIONS */ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/Makefile b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/Makefile new file mode 100644 index 00000000..efcfa0b8 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/Makefile @@ -0,0 +1,22 @@ + +BUILD_DIR = ../build +LIBS := -lpthread +CPP_OBJS=$(BUILD_DIR)/gtest-all.o $(BUILD_DIR)/gtest-main.o + +SOURCES=gtest-all.cc gtest-main.cc + + +# Each subdirectory must supply rules for building sources it contributes +$(BUILD_DIR)/%.o: %.cc + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + g++ -I../ -O0 -g3 -Wall -DGTEST_USE_OWN_TR1_TUPLE=1 -c -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + +all: $(CPP_OBJS) + +clean: + -$(RM) $(CPP_OBJS) + -@echo ' ' + diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/gtest-all.cc b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/gtest-all.cc new file mode 100644 index 00000000..5ced66a9 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/gtest-all.cc @@ -0,0 +1,9118 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: mheule@google.com (Markus Heule) +// +// Google C++ Testing Framework (Google Test) +// +// Sometimes it's desirable to build Google Test by compiling a single file. +// This file serves this purpose. + +// This line ensures that gtest.h can be compiled on its own, even +// when it's fused. +#include "gtest/gtest.h" + +// The following lines pull in the real gtest *.cc files. +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) + +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// Utilities for testing Google Test itself and code that uses Google Test +// (e.g. frameworks built on top of Google Test). + +#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + + +namespace testing { + +// This helper class can be used to mock out Google Test failure reporting +// so that we can test Google Test or code that builds on Google Test. +// +// An object of this class appends a TestPartResult object to the +// TestPartResultArray object given in the constructor whenever a Google Test +// failure is reported. It can either intercept only failures that are +// generated in the same thread that created this object or it can intercept +// all generated failures. The scope of this mock object can be controlled with +// the second argument to the two arguments constructor. +class GTEST_API_ ScopedFakeTestPartResultReporter + : public TestPartResultReporterInterface { + public: + // The two possible mocking modes of this object. + enum InterceptMode { + INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. + INTERCEPT_ALL_THREADS // Intercepts all failures. + }; + + // The c'tor sets this object as the test part result reporter used + // by Google Test. The 'result' parameter specifies where to report the + // results. This reporter will only catch failures generated in the current + // thread. DEPRECATED + explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); + + // Same as above, but you can choose the interception scope of this object. + ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, + TestPartResultArray* result); + + // The d'tor restores the previous test part result reporter. + virtual ~ScopedFakeTestPartResultReporter(); + + // Appends the TestPartResult object to the TestPartResultArray + // received in the constructor. + // + // This method is from the TestPartResultReporterInterface + // interface. + virtual void ReportTestPartResult(const TestPartResult& result); + private: + void Init(); + + const InterceptMode intercept_mode_; + TestPartResultReporterInterface* old_reporter_; + TestPartResultArray* const result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); +}; + +namespace internal { + +// A helper class for implementing EXPECT_FATAL_FAILURE() and +// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +class GTEST_API_ SingleFailureChecker { + public: + // The constructor remembers the arguments. + SingleFailureChecker(const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr); + ~SingleFailureChecker(); + private: + const TestPartResultArray* const results_; + const TestPartResult::Type type_; + const string substr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); +}; + +} // namespace internal + +} // namespace testing + +// A set of macros for testing Google Test assertions or code that's expected +// to generate Google Test fatal failures. It verifies that the given +// statement will cause exactly one fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_FATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - 'statement' cannot reference local non-static variables or +// non-static members of the current object. +// - 'statement' cannot return a value. +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. The AcceptsMacroThatExpandsToUnprotectedComma test in +// gtest_unittest.cc will fail to compile if we do that. +#define EXPECT_FATAL_FAILURE(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ALL_THREADS, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +// A macro for testing Google Test assertions or code that's expected to +// generate Google Test non-fatal failures. It asserts that the given +// statement will cause exactly one non-fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// 'statement' is allowed to reference local variables and members of +// the current object. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. If we do that, the code won't compile when the user gives +// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that +// expands to code containing an unprotected comma. The +// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc +// catches that. +// +// For the same reason, we have to write +// if (::testing::internal::AlwaysTrue()) { statement; } +// instead of +// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) +// to avoid an MSVC warning on unreachable code. +#define EXPECT_NONFATAL_FAILURE(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\ + >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include // NOLINT +#include +#include + +#if GTEST_OS_LINUX + +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +# include // NOLINT +# include // NOLINT +# include // NOLINT +// Declares vsnprintf(). This header is not available on Windows. +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include + +#elif GTEST_OS_SYMBIAN +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +#elif GTEST_OS_ZOS +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +// On z/OS we additionally need strings.h for strcasecmp. +# include // NOLINT + +#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. + +# include // NOLINT + +#elif GTEST_OS_WINDOWS // We are on Windows proper. + +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT + +# if GTEST_OS_WINDOWS_MINGW +// MinGW has gettimeofday() but not _ftime64(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +// TODO(kenton@google.com): There are other ways to get the time on +// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW +// supports these. consider using them instead. +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT +# endif // GTEST_OS_WINDOWS_MINGW + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT + +#else + +// Assume other platforms have gettimeofday(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT +# include // NOLINT + +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Utility functions and classes used by the Google C++ testing framework. +// +// Author: wan@google.com (Zhanyong Wan) +// +// This file contains purely Google Test's internal implementation. Please +// DO NOT #INCLUDE IT IN A USER PROGRAM. + +#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ +#define GTEST_SRC_GTEST_INTERNAL_INL_H_ + +// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is +// part of Google Test's implementation; otherwise it's undefined. +#if !GTEST_IMPLEMENTATION_ +// A user is trying to include this from his code - just say no. +# error "gtest-internal-inl.h is part of Google Test's internal implementation." +# error "It must not be included except by Google Test itself." +#endif // GTEST_IMPLEMENTATION_ + +#ifndef _WIN32_WCE +# include +#endif // !_WIN32_WCE +#include +#include // For strtoll/_strtoul64/malloc/free. +#include // For memmove. + +#include +#include +#include + + +#if GTEST_OS_WINDOWS +# include // NOLINT +#endif // GTEST_OS_WINDOWS + + +namespace testing { + +// Declares the flags. +// +// We don't want the users to modify this flag in the code, but want +// Google Test's own unit tests to be able to access it. Therefore we +// declare it here as opposed to in gtest.h. +GTEST_DECLARE_bool_(death_test_use_fork); + +namespace internal { + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest; + +// Names of the flags (needed for parsing Google Test flags). +const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests"; +const char kBreakOnFailureFlag[] = "break_on_failure"; +const char kCatchExceptionsFlag[] = "catch_exceptions"; +const char kColorFlag[] = "color"; +const char kFilterFlag[] = "filter"; +const char kListTestsFlag[] = "list_tests"; +const char kOutputFlag[] = "output"; +const char kPrintTimeFlag[] = "print_time"; +const char kRandomSeedFlag[] = "random_seed"; +const char kRepeatFlag[] = "repeat"; +const char kShuffleFlag[] = "shuffle"; +const char kStackTraceDepthFlag[] = "stack_trace_depth"; +const char kStreamResultToFlag[] = "stream_result_to"; +const char kThrowOnFailureFlag[] = "throw_on_failure"; + +// A valid random seed must be in [1, kMaxRandomSeed]. +const int kMaxRandomSeed = 99999; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +GTEST_API_ extern bool g_help_flag; + +// Returns the current time in milliseconds. +GTEST_API_ TimeInMillis GetTimeInMillis(); + +// Returns true iff Google Test should use colors in the output. +GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); + +// Formats the given time in milliseconds as seconds. +GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); + +// Parses a string for an Int32 flag, in the form of "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +GTEST_API_ bool ParseInt32Flag( + const char* str, const char* flag, Int32* value); + +// Returns a random seed in range [1, kMaxRandomSeed] based on the +// given --gtest_random_seed flag value. +inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { + const unsigned int raw_seed = (random_seed_flag == 0) ? + static_cast(GetTimeInMillis()) : + static_cast(random_seed_flag); + + // Normalizes the actual seed to range [1, kMaxRandomSeed] such that + // it's easy to type. + const int normalized_seed = + static_cast((raw_seed - 1U) % + static_cast(kMaxRandomSeed)) + 1; + return normalized_seed; +} + +// Returns the first valid random seed after 'seed'. The behavior is +// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is +// considered to be 1. +inline int GetNextRandomSeed(int seed) { + GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) + << "Invalid random seed " << seed << " - must be in [1, " + << kMaxRandomSeed << "]."; + const int next_seed = seed + 1; + return (next_seed > kMaxRandomSeed) ? 1 : next_seed; +} + +// This class saves the values of all Google Test flags in its c'tor, and +// restores them in its d'tor. +class GTestFlagSaver { + public: + // The c'tor. + GTestFlagSaver() { + also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); + break_on_failure_ = GTEST_FLAG(break_on_failure); + catch_exceptions_ = GTEST_FLAG(catch_exceptions); + color_ = GTEST_FLAG(color); + death_test_style_ = GTEST_FLAG(death_test_style); + death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); + filter_ = GTEST_FLAG(filter); + internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); + list_tests_ = GTEST_FLAG(list_tests); + output_ = GTEST_FLAG(output); + print_time_ = GTEST_FLAG(print_time); + random_seed_ = GTEST_FLAG(random_seed); + repeat_ = GTEST_FLAG(repeat); + shuffle_ = GTEST_FLAG(shuffle); + stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); + stream_result_to_ = GTEST_FLAG(stream_result_to); + throw_on_failure_ = GTEST_FLAG(throw_on_failure); + } + + // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. + ~GTestFlagSaver() { + GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; + GTEST_FLAG(break_on_failure) = break_on_failure_; + GTEST_FLAG(catch_exceptions) = catch_exceptions_; + GTEST_FLAG(color) = color_; + GTEST_FLAG(death_test_style) = death_test_style_; + GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; + GTEST_FLAG(filter) = filter_; + GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; + GTEST_FLAG(list_tests) = list_tests_; + GTEST_FLAG(output) = output_; + GTEST_FLAG(print_time) = print_time_; + GTEST_FLAG(random_seed) = random_seed_; + GTEST_FLAG(repeat) = repeat_; + GTEST_FLAG(shuffle) = shuffle_; + GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; + GTEST_FLAG(stream_result_to) = stream_result_to_; + GTEST_FLAG(throw_on_failure) = throw_on_failure_; + } + private: + // Fields for saving the original values of flags. + bool also_run_disabled_tests_; + bool break_on_failure_; + bool catch_exceptions_; + String color_; + String death_test_style_; + bool death_test_use_fork_; + String filter_; + String internal_run_death_test_; + bool list_tests_; + String output_; + bool print_time_; + bool pretty_; + internal::Int32 random_seed_; + internal::Int32 repeat_; + bool shuffle_; + internal::Int32 stack_trace_depth_; + String stream_result_to_; + bool throw_on_failure_; +} GTEST_ATTRIBUTE_UNUSED_; + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// The output buffer str must containt at least 32 characters. +// The function returns the address of the output buffer. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. +GTEST_API_ char* CodePointToUtf8(UInt32 code_point, char* str); + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +GTEST_API_ String WideStringToUtf8(const wchar_t* str, int num_chars); + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded(); + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (e.g., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +GTEST_API_ bool ShouldShard(const char* total_shards_str, + const char* shard_index_str, + bool in_subprocess_for_death_test); + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error and +// and aborts. +GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +GTEST_API_ bool ShouldRunTestOnShard( + int total_shards, int shard_index, int test_id); + +// STL container utilities. + +// Returns the number of elements in the given container that satisfy +// the given predicate. +template +inline int CountIf(const Container& c, Predicate predicate) { + // Implemented as an explicit loop since std::count_if() in libCstd on + // Solaris has a non-standard signature. + int count = 0; + for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) { + if (predicate(*it)) + ++count; + } + return count; +} + +// Applies a function/functor to each element in the container. +template +void ForEach(const Container& c, Functor functor) { + std::for_each(c.begin(), c.end(), functor); +} + +// Returns the i-th element of the vector, or default_value if i is not +// in range [0, v.size()). +template +inline E GetElementOr(const std::vector& v, int i, E default_value) { + return (i < 0 || i >= static_cast(v.size())) ? default_value : v[i]; +} + +// Performs an in-place shuffle of a range of the vector's elements. +// 'begin' and 'end' are element indices as an STL-style range; +// i.e. [begin, end) are shuffled, where 'end' == size() means to +// shuffle to the end of the vector. +template +void ShuffleRange(internal::Random* random, int begin, int end, + std::vector* v) { + const int size = static_cast(v->size()); + GTEST_CHECK_(0 <= begin && begin <= size) + << "Invalid shuffle range start " << begin << ": must be in range [0, " + << size << "]."; + GTEST_CHECK_(begin <= end && end <= size) + << "Invalid shuffle range finish " << end << ": must be in range [" + << begin << ", " << size << "]."; + + // Fisher-Yates shuffle, from + // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + for (int range_width = end - begin; range_width >= 2; range_width--) { + const int last_in_range = begin + range_width - 1; + const int selected = begin + random->Generate(range_width); + std::swap((*v)[selected], (*v)[last_in_range]); + } +} + +// Performs an in-place shuffle of the vector's elements. +template +inline void Shuffle(internal::Random* random, std::vector* v) { + ShuffleRange(random, 0, static_cast(v->size()), v); +} + +// A function for deleting an object. Handy for being used as a +// functor. +template +static void Delete(T* x) { + delete x; +} + +// A predicate that checks the key of a TestProperty against a known key. +// +// TestPropertyKeyIs is copyable. +class TestPropertyKeyIs { + public: + // Constructor. + // + // TestPropertyKeyIs has NO default constructor. + explicit TestPropertyKeyIs(const char* key) + : key_(key) {} + + // Returns true iff the test name of test property matches on key_. + bool operator()(const TestProperty& test_property) const { + return String(test_property.key()).Compare(key_) == 0; + } + + private: + String key_; +}; + +// Class UnitTestOptions. +// +// This class contains functions for processing options the user +// specifies when running the tests. It has only static members. +// +// In most cases, the user can specify an option using either an +// environment variable or a command line flag. E.g. you can set the +// test filter using either GTEST_FILTER or --gtest_filter. If both +// the variable and the flag are present, the latter overrides the +// former. +class GTEST_API_ UnitTestOptions { + public: + // Functions for processing the gtest_output flag. + + // Returns the output format, or "" for normal printed output. + static String GetOutputFormat(); + + // Returns the absolute path of the requested output file, or the + // default (test_detail.xml in the original working directory) if + // none was explicitly specified. + static String GetAbsolutePathToOutputFile(); + + // Functions for processing the gtest_filter flag. + + // Returns true iff the wildcard pattern matches the string. The + // first ':' or '\0' character in pattern marks the end of it. + // + // This recursive algorithm isn't very efficient, but is clear and + // works well enough for matching test names, which are short. + static bool PatternMatchesString(const char *pattern, const char *str); + + // Returns true iff the user-specified filter matches the test case + // name and the test name. + static bool FilterMatchesTest(const String &test_case_name, + const String &test_name); + +#if GTEST_OS_WINDOWS + // Function for supporting the gtest_catch_exception flag. + + // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the + // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. + // This function is useful as an __except condition. + static int GTestShouldProcessSEH(DWORD exception_code); +#endif // GTEST_OS_WINDOWS + + // Returns true if "name" matches the ':' separated list of glob-style + // filters in "filter". + static bool MatchesFilter(const String& name, const char* filter); +}; + +// Returns the current application's name, removing directory path if that +// is present. Used by UnitTestOptions::GetOutputFile. +GTEST_API_ FilePath GetCurrentExecutableName(); + +// The role interface for getting the OS stack trace as a string. +class OsStackTraceGetterInterface { + public: + OsStackTraceGetterInterface() {} + virtual ~OsStackTraceGetterInterface() {} + + // Returns the current OS stack trace as a String. Parameters: + // + // max_depth - the maximum number of stack frames to be included + // in the trace. + // skip_count - the number of top frames to be skipped; doesn't count + // against max_depth. + virtual String CurrentStackTrace(int max_depth, int skip_count) = 0; + + // UponLeavingGTest() should be called immediately before Google Test calls + // user code. It saves some information about the current stack that + // CurrentStackTrace() will use to find and hide Google Test stack frames. + virtual void UponLeavingGTest() = 0; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); +}; + +// A working implementation of the OsStackTraceGetterInterface interface. +class OsStackTraceGetter : public OsStackTraceGetterInterface { + public: + OsStackTraceGetter() : caller_frame_(NULL) {} + virtual String CurrentStackTrace(int max_depth, int skip_count); + virtual void UponLeavingGTest(); + + // This string is inserted in place of stack frames that are part of + // Google Test's implementation. + static const char* const kElidedFramesMarker; + + private: + Mutex mutex_; // protects all internal state + + // We save the stack frame below the frame that calls user code. + // We do this because the address of the frame immediately below + // the user code changes between the call to UponLeavingGTest() + // and any calls to CurrentStackTrace() from within the user code. + void* caller_frame_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); +}; + +// Information about a Google Test trace point. +struct TraceInfo { + const char* file; + int line; + String message; +}; + +// This is the default global test part result reporter used in UnitTestImpl. +// This class should only be used by UnitTestImpl. +class DefaultGlobalTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. Reports the test part + // result in the current test. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); +}; + +// This is the default per thread test part result reporter used in +// UnitTestImpl. This class should only be used by UnitTestImpl. +class DefaultPerThreadTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. The implementation just + // delegates to the current global test part result reporter of *unit_test_. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); +}; + +// The private implementation of the UnitTest class. We don't protect +// the methods under a mutex, as this class is not accessible by a +// user and the UnitTest class that delegates work to this class does +// proper locking. +class GTEST_API_ UnitTestImpl { + public: + explicit UnitTestImpl(UnitTest* parent); + virtual ~UnitTestImpl(); + + // There are two different ways to register your own TestPartResultReporter. + // You can register your own repoter to listen either only for test results + // from the current thread or for results from all threads. + // By default, each per-thread test result repoter just passes a new + // TestPartResult to the global test result reporter, which registers the + // test part result for the currently running test. + + // Returns the global test part result reporter. + TestPartResultReporterInterface* GetGlobalTestPartResultReporter(); + + // Sets the global test part result reporter. + void SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter); + + // Returns the test part result reporter for the current thread. + TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread(); + + // Sets the test part result reporter for the current thread. + void SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter); + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const { return !Failed(); } + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const { + return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[i]; + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i) { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[index]; + } + + // Provides access to the event listener list. + TestEventListeners* listeners() { return &listeners_; } + + // Returns the TestResult for the test that's currently running, or + // the TestResult for the ad hoc test if no test is running. + TestResult* current_test_result(); + + // Returns the TestResult for the ad hoc test. + const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } + + // Sets the OS stack trace getter. + // + // Does nothing if the input and the current OS stack trace getter + // are the same; otherwise, deletes the old getter and makes the + // input the current getter. + void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter); + + // Returns the current OS stack trace getter if it is not NULL; + // otherwise, creates an OsStackTraceGetter, makes it the current + // getter, and returns it. + OsStackTraceGetterInterface* os_stack_trace_getter(); + + // Returns the current OS stack trace as a String. + // + // The maximum number of stack frames to be included is specified by + // the gtest_stack_trace_depth flag. The skip_count parameter + // specifies the number of top frames to be skipped, which doesn't + // count against the number of frames to be included. + // + // For example, if Foo() calls Bar(), which in turn calls + // CurrentOsStackTraceExceptTop(1), Foo() will be included in the + // trace but Bar() and CurrentOsStackTraceExceptTop() won't. + String CurrentOsStackTraceExceptTop(int skip_count); + + // Finds and returns a TestCase with the given name. If one doesn't + // exist, creates one and returns it. + // + // Arguments: + // + // test_case_name: name of the test case + // type_param: the name of the test's type parameter, or NULL if + // this is not a typed or a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase* GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Adds a TestInfo to the unit test. + // + // Arguments: + // + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + // test_info: the TestInfo object + void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + TestInfo* test_info) { + // In order to support thread-safe death tests, we need to + // remember the original working directory when the test program + // was first invoked. We cannot do this in RUN_ALL_TESTS(), as + // the user may have changed the current directory before calling + // RUN_ALL_TESTS(). Therefore we capture the current directory in + // AddTestInfo(), which is called to register a TEST or TEST_F + // before main() is reached. + if (original_working_dir_.IsEmpty()) { + original_working_dir_.Set(FilePath::GetCurrentDir()); + GTEST_CHECK_(!original_working_dir_.IsEmpty()) + << "Failed to get the current working directory."; + } + + GetTestCase(test_info->test_case_name(), + test_info->type_param(), + set_up_tc, + tear_down_tc)->AddTestInfo(test_info); + } + +#if GTEST_HAS_PARAM_TEST + // Returns ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { + return parameterized_test_registry_; + } +#endif // GTEST_HAS_PARAM_TEST + + // Sets the TestCase object for the test that's currently running. + void set_current_test_case(TestCase* a_current_test_case) { + current_test_case_ = a_current_test_case; + } + + // Sets the TestInfo object for the test that's currently running. If + // current_test_info is NULL, the assertion results will be stored in + // ad_hoc_test_result_. + void set_current_test_info(TestInfo* a_current_test_info) { + current_test_info_ = a_current_test_info; + } + + // Registers all parameterized tests defined using TEST_P and + // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter + // combination. This method can be called more then once; it has guards + // protecting from registering the tests more then once. If + // value-parameterized tests are disabled, RegisterParameterizedTests is + // present but does nothing. + void RegisterParameterizedTests(); + + // Runs all tests in this UnitTest object, prints the result, and + // returns true if all tests are successful. If any exception is + // thrown during a test, this test is considered to be failed, but + // the rest of the tests will still be run. + bool RunAllTests(); + + // Clears the results of all tests, except the ad hoc tests. + void ClearNonAdHocTestResult() { + ForEach(test_cases_, TestCase::ClearTestCaseResult); + } + + // Clears the results of ad-hoc test assertions. + void ClearAdHocTestResult() { + ad_hoc_test_result_.Clear(); + } + + enum ReactionToSharding { + HONOR_SHARDING_PROTOCOL, + IGNORE_SHARDING_PROTOCOL + }; + + // Matches the full name of each test against the user-specified + // filter to decide whether the test should run, then records the + // result in each TestCase and TestInfo object. + // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests + // based on sharding variables in the environment. + // Returns the number of tests that should run. + int FilterTests(ReactionToSharding shard_tests); + + // Prints the names of the tests matching the user-specified filter flag. + void ListTestsMatchingFilter(); + + const TestCase* current_test_case() const { return current_test_case_; } + TestInfo* current_test_info() { return current_test_info_; } + const TestInfo* current_test_info() const { return current_test_info_; } + + // Returns the vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector& environments() { return environments_; } + + // Getters for the per-thread Google Test trace stack. + std::vector& gtest_trace_stack() { + return *(gtest_trace_stack_.pointer()); + } + const std::vector& gtest_trace_stack() const { + return gtest_trace_stack_.get(); + } + +#if GTEST_HAS_DEATH_TEST + void InitDeathTestSubprocessControlInfo() { + internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); + } + // Returns a pointer to the parsed --gtest_internal_run_death_test + // flag, or NULL if that flag was not specified. + // This information is useful only in a death test child process. + // Must not be called before a call to InitGoogleTest. + const InternalRunDeathTestFlag* internal_run_death_test_flag() const { + return internal_run_death_test_flag_.get(); + } + + // Returns a pointer to the current death test factory. + internal::DeathTestFactory* death_test_factory() { + return death_test_factory_.get(); + } + + void SuppressTestEventsIfInSubprocess(); + + friend class ReplaceDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + + // Initializes the event listener performing XML output as specified by + // UnitTestOptions. Must not be called before InitGoogleTest. + void ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Initializes the event listener for streaming test results to a socket. + // Must not be called before InitGoogleTest. + void ConfigureStreamingOutput(); +#endif + + // Performs initialization dependent upon flag values obtained in + // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to + // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest + // this function is also called from RunAllTests. Since this function can be + // called more than once, it has to be idempotent. + void PostFlagParsingInit(); + + // Gets the random seed used at the start of the current test iteration. + int random_seed() const { return random_seed_; } + + // Gets the random number generator. + internal::Random* random() { return &random_; } + + // Shuffles all test cases, and the tests within each test case, + // making sure that death tests are still run first. + void ShuffleTests(); + + // Restores the test cases and tests to their order before the first shuffle. + void UnshuffleTests(); + + // Returns the value of GTEST_FLAG(catch_exceptions) at the moment + // UnitTest::Run() starts. + bool catch_exceptions() const { return catch_exceptions_; } + + private: + friend class ::testing::UnitTest; + + // Used by UnitTest::Run() to capture the state of + // GTEST_FLAG(catch_exceptions) at the moment it starts. + void set_catch_exceptions(bool value) { catch_exceptions_ = value; } + + // The UnitTest object that owns this implementation object. + UnitTest* const parent_; + + // The working directory when the first TEST() or TEST_F() was + // executed. + internal::FilePath original_working_dir_; + + // The default test part result reporters. + DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_; + DefaultPerThreadTestPartResultReporter + default_per_thread_test_part_result_reporter_; + + // Points to (but doesn't own) the global test part result reporter. + TestPartResultReporterInterface* global_test_part_result_repoter_; + + // Protects read and write access to global_test_part_result_reporter_. + internal::Mutex global_test_part_result_reporter_mutex_; + + // Points to (but doesn't own) the per-thread test part result reporter. + internal::ThreadLocal + per_thread_test_part_result_reporter_; + + // The vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector environments_; + + // The vector of TestCases in their original order. It owns the + // elements in the vector. + std::vector test_cases_; + + // Provides a level of indirection for the test case list to allow + // easy shuffling and restoring the test case order. The i-th + // element of this vector is the index of the i-th test case in the + // shuffled order. + std::vector test_case_indices_; + +#if GTEST_HAS_PARAM_TEST + // ParameterizedTestRegistry object used to register value-parameterized + // tests. + internal::ParameterizedTestCaseRegistry parameterized_test_registry_; + + // Indicates whether RegisterParameterizedTests() has been called already. + bool parameterized_tests_registered_; +#endif // GTEST_HAS_PARAM_TEST + + // Index of the last death test case registered. Initially -1. + int last_death_test_case_; + + // This points to the TestCase for the currently running test. It + // changes as Google Test goes through one test case after another. + // When no test is running, this is set to NULL and Google Test + // stores assertion results in ad_hoc_test_result_. Initially NULL. + TestCase* current_test_case_; + + // This points to the TestInfo for the currently running test. It + // changes as Google Test goes through one test after another. When + // no test is running, this is set to NULL and Google Test stores + // assertion results in ad_hoc_test_result_. Initially NULL. + TestInfo* current_test_info_; + + // Normally, a user only writes assertions inside a TEST or TEST_F, + // or inside a function called by a TEST or TEST_F. Since Google + // Test keeps track of which test is current running, it can + // associate such an assertion with the test it belongs to. + // + // If an assertion is encountered when no TEST or TEST_F is running, + // Google Test attributes the assertion result to an imaginary "ad hoc" + // test, and records the result in ad_hoc_test_result_. + TestResult ad_hoc_test_result_; + + // The list of event listeners that can be used to track events inside + // Google Test. + TestEventListeners listeners_; + + // The OS stack trace getter. Will be deleted when the UnitTest + // object is destructed. By default, an OsStackTraceGetter is used, + // but the user can set this field to use a custom getter if that is + // desired. + OsStackTraceGetterInterface* os_stack_trace_getter_; + + // True iff PostFlagParsingInit() has been called. + bool post_flag_parse_init_performed_; + + // The random number seed used at the beginning of the test run. + int random_seed_; + + // Our random number generator. + internal::Random random_; + + // How long the test took to run, in milliseconds. + TimeInMillis elapsed_time_; + +#if GTEST_HAS_DEATH_TEST + // The decomposed components of the gtest_internal_run_death_test flag, + // parsed when RUN_ALL_TESTS is called. + internal::scoped_ptr internal_run_death_test_flag_; + internal::scoped_ptr death_test_factory_; +#endif // GTEST_HAS_DEATH_TEST + + // A per-thread stack of traces created by the SCOPED_TRACE() macro. + internal::ThreadLocal > gtest_trace_stack_; + + // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests() + // starts. + bool catch_exceptions_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); +}; // class UnitTestImpl + +// Convenience function for accessing the global UnitTest +// implementation object. +inline UnitTestImpl* GetUnitTestImpl() { + return UnitTest::GetInstance()->impl(); +} + +#if GTEST_USES_SIMPLE_RE + +// Internal helper functions for implementing the simple regular +// expression matcher. +GTEST_API_ bool IsInSet(char ch, const char* str); +GTEST_API_ bool IsAsciiDigit(char ch); +GTEST_API_ bool IsAsciiPunct(char ch); +GTEST_API_ bool IsRepeat(char ch); +GTEST_API_ bool IsAsciiWhiteSpace(char ch); +GTEST_API_ bool IsAsciiWordChar(char ch); +GTEST_API_ bool IsValidEscape(char ch); +GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); +GTEST_API_ bool ValidateRegex(const char* regex); +GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); +GTEST_API_ bool MatchRepetitionAndRegexAtHead( + bool escaped, char ch, char repeat, const char* regex, const char* str); +GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); + +#endif // GTEST_USES_SIMPLE_RE + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); + +#if GTEST_HAS_DEATH_TEST + +// Returns the message describing the last system error, regardless of the +// platform. +GTEST_API_ String GetLastErrnoDescription(); + +# if GTEST_OS_WINDOWS +// Provides leak-safe Windows kernel handle ownership. +class AutoHandle { + public: + AutoHandle() : handle_(INVALID_HANDLE_VALUE) {} + explicit AutoHandle(HANDLE handle) : handle_(handle) {} + + ~AutoHandle() { Reset(); } + + HANDLE Get() const { return handle_; } + void Reset() { Reset(INVALID_HANDLE_VALUE); } + void Reset(HANDLE handle) { + if (handle != handle_) { + if (handle_ != INVALID_HANDLE_VALUE) + ::CloseHandle(handle_); + handle_ = handle; + } + } + + private: + HANDLE handle_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle); +}; +# endif // GTEST_OS_WINDOWS + +// Attempts to parse a string into a positive integer pointed to by the +// number parameter. Returns true if that is possible. +// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use +// it here. +template +bool ParseNaturalNumber(const ::std::string& str, Integer* number) { + // Fail fast if the given string does not begin with a digit; + // this bypasses strtoXXX's "optional leading whitespace and plus + // or minus sign" semantics, which are undesirable here. + if (str.empty() || !IsDigit(str[0])) { + return false; + } + errno = 0; + + char* end; + // BiggestConvertible is the largest integer type that system-provided + // string-to-number conversion routines can return. + +# if GTEST_OS_WINDOWS && !defined(__GNUC__) + + // MSVC and C++ Builder define __int64 instead of the standard long long. + typedef unsigned __int64 BiggestConvertible; + const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); + +# else + + typedef unsigned long long BiggestConvertible; // NOLINT + const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); + +# endif // GTEST_OS_WINDOWS && !defined(__GNUC__) + + const bool parse_success = *end == '\0' && errno == 0; + + // TODO(vladl@google.com): Convert this to compile time assertion when it is + // available. + GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); + + const Integer result = static_cast(parsed); + if (parse_success && static_cast(result) == parsed) { + *number = result; + return true; + } + return false; +} +#endif // GTEST_HAS_DEATH_TEST + +// TestResult contains some private methods that should be hidden from +// Google Test user but are required for testing. This class allow our tests +// to access them. +// +// This class is supplied only for the purpose of testing Google Test's own +// constructs. Do not use it in user tests, either directly or indirectly. +class TestResultAccessor { + public: + static void RecordProperty(TestResult* test_result, + const TestProperty& property) { + test_result->RecordProperty(property); + } + + static void ClearTestPartResults(TestResult* test_result) { + test_result->ClearTestPartResults(); + } + + static const std::vector& test_part_results( + const TestResult& test_result) { + return test_result.test_part_results(); + } +}; + +} // namespace internal +} // namespace testing + +#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ +#undef GTEST_IMPLEMENTATION_ + +#if GTEST_OS_WINDOWS +# define vsnprintf _vsnprintf +#endif // GTEST_OS_WINDOWS + +namespace testing { + +using internal::CountIf; +using internal::ForEach; +using internal::GetElementOr; +using internal::Shuffle; + +// Constants. + +// A test whose test case name or test name matches this filter is +// disabled and not run. +static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; + +// A test case whose name matches this filter is considered a death +// test case and will be run before test cases whose name doesn't +// match this filter. +static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*"; + +// A test filter that matches everything. +static const char kUniversalFilter[] = "*"; + +// The default output file for XML output. +static const char kDefaultOutputFile[] = "test_detail.xml"; + +// The environment variable name for the test shard index. +static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; +// The environment variable name for the total number of test shards. +static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; +// The environment variable name for the test shard status file. +static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; + +namespace internal { + +// The text used in failure messages to indicate the start of the +// stack trace. +const char kStackTraceMarker[] = "\nStack trace:\n"; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +bool g_help_flag = false; + +} // namespace internal + +GTEST_DEFINE_bool_( + also_run_disabled_tests, + internal::BoolFromGTestEnv("also_run_disabled_tests", false), + "Run disabled tests too, in addition to the tests normally being run."); + +GTEST_DEFINE_bool_( + break_on_failure, + internal::BoolFromGTestEnv("break_on_failure", false), + "True iff a failed assertion should be a debugger break-point."); + +GTEST_DEFINE_bool_( + catch_exceptions, + internal::BoolFromGTestEnv("catch_exceptions", true), + "True iff " GTEST_NAME_ + " should catch exceptions and treat them as test failures."); + +GTEST_DEFINE_string_( + color, + internal::StringFromGTestEnv("color", "auto"), + "Whether to use colors in the output. Valid values: yes, no, " + "and auto. 'auto' means to use colors if the output is " + "being sent to a terminal and the TERM environment variable " + "is set to xterm, xterm-color, xterm-256color, linux or cygwin."); + +GTEST_DEFINE_string_( + filter, + internal::StringFromGTestEnv("filter", kUniversalFilter), + "A colon-separated list of glob (not regex) patterns " + "for filtering the tests to run, optionally followed by a " + "'-' and a : separated list of negative patterns (tests to " + "exclude). A test is run if it matches one of the positive " + "patterns and does not match any of the negative patterns."); + +GTEST_DEFINE_bool_(list_tests, false, + "List all tests without running them."); + +GTEST_DEFINE_string_( + output, + internal::StringFromGTestEnv("output", ""), + "A format (currently must be \"xml\"), optionally followed " + "by a colon and an output file name or directory. A directory " + "is indicated by a trailing pathname separator. " + "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " + "If a directory is specified, output files will be created " + "within that directory, with file-names based on the test " + "executable's name and, if necessary, made unique by adding " + "digits."); + +GTEST_DEFINE_bool_( + print_time, + internal::BoolFromGTestEnv("print_time", true), + "True iff " GTEST_NAME_ + " should display elapsed time in text output."); + +GTEST_DEFINE_int32_( + random_seed, + internal::Int32FromGTestEnv("random_seed", 0), + "Random number seed to use when shuffling test orders. Must be in range " + "[1, 99999], or 0 to use a seed based on the current time."); + +GTEST_DEFINE_int32_( + repeat, + internal::Int32FromGTestEnv("repeat", 1), + "How many times to repeat each test. Specify a negative number " + "for repeating forever. Useful for shaking out flaky tests."); + +GTEST_DEFINE_bool_( + show_internal_stack_frames, false, + "True iff " GTEST_NAME_ " should include internal stack frames when " + "printing test failure stack traces."); + +GTEST_DEFINE_bool_( + shuffle, + internal::BoolFromGTestEnv("shuffle", false), + "True iff " GTEST_NAME_ + " should randomize tests' order on every run."); + +GTEST_DEFINE_int32_( + stack_trace_depth, + internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), + "The maximum number of stack frames to print when an " + "assertion fails. The valid range is 0 through 100, inclusive."); + +GTEST_DEFINE_string_( + stream_result_to, + internal::StringFromGTestEnv("stream_result_to", ""), + "This flag specifies the host name and the port number on which to stream " + "test results. Example: \"localhost:555\". The flag is effective only on " + "Linux."); + +GTEST_DEFINE_bool_( + throw_on_failure, + internal::BoolFromGTestEnv("throw_on_failure", false), + "When this flag is specified, a failed assertion will throw an exception " + "if exceptions are enabled or exit the program with a non-zero code " + "otherwise."); + +namespace internal { + +// Generates a random number from [0, range), using a Linear +// Congruential Generator (LCG). Crashes if 'range' is 0 or greater +// than kMaxRange. +UInt32 Random::Generate(UInt32 range) { + // These constants are the same as are used in glibc's rand(3). + state_ = (1103515245U*state_ + 12345U) % kMaxRange; + + GTEST_CHECK_(range > 0) + << "Cannot generate a number in the range [0, 0)."; + GTEST_CHECK_(range <= kMaxRange) + << "Generation of a number in [0, " << range << ") was requested, " + << "but this can only generate numbers in [0, " << kMaxRange << ")."; + + // Converting via modulus introduces a bit of downward bias, but + // it's simple, and a linear congruential generator isn't too good + // to begin with. + return state_ % range; +} + +// GTestIsInitialized() returns true iff the user has initialized +// Google Test. Useful for catching the user mistake of not initializing +// Google Test before calling RUN_ALL_TESTS(). +// +// A user must call testing::InitGoogleTest() to initialize Google +// Test. g_init_gtest_count is set to the number of times +// InitGoogleTest() has been called. We don't protect this variable +// under a mutex as it is only accessed in the main thread. +int g_init_gtest_count = 0; +static bool GTestIsInitialized() { return g_init_gtest_count != 0; } + +// Iterates over a vector of TestCases, keeping a running sum of the +// results of calling a given int-returning method on each. +// Returns the sum. +static int SumOverTestCaseList(const std::vector& case_list, + int (TestCase::*method)() const) { + int sum = 0; + for (size_t i = 0; i < case_list.size(); i++) { + sum += (case_list[i]->*method)(); + } + return sum; +} + +// Returns true iff the test case passed. +static bool TestCasePassed(const TestCase* test_case) { + return test_case->should_run() && test_case->Passed(); +} + +// Returns true iff the test case failed. +static bool TestCaseFailed(const TestCase* test_case) { + return test_case->should_run() && test_case->Failed(); +} + +// Returns true iff test_case contains at least one test that should +// run. +static bool ShouldRunTestCase(const TestCase* test_case) { + return test_case->should_run(); +} + +// AssertHelper constructor. +AssertHelper::AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message) + : data_(new AssertHelperData(type, file, line, message)) { +} + +AssertHelper::~AssertHelper() { + delete data_; +} + +// Message assignment, for assertion streaming support. +void AssertHelper::operator=(const Message& message) const { + UnitTest::GetInstance()-> + AddTestPartResult(data_->type, data_->file, data_->line, + AppendUserMessage(data_->message, message), + UnitTest::GetInstance()->impl() + ->CurrentOsStackTraceExceptTop(1) + // Skips the stack frame for this function itself. + ); // NOLINT +} + +// Mutex for linked pointers. +GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// Application pathname gotten in InitGoogleTest. +String g_executable_path; + +// Returns the current application's name, removing directory path if that +// is present. +FilePath GetCurrentExecutableName() { + FilePath result; + +#if GTEST_OS_WINDOWS + result.Set(FilePath(g_executable_path).RemoveExtension("exe")); +#else + result.Set(FilePath(g_executable_path)); +#endif // GTEST_OS_WINDOWS + + return result.RemoveDirectoryName(); +} + +// Functions for processing the gtest_output flag. + +// Returns the output format, or "" for normal printed output. +String UnitTestOptions::GetOutputFormat() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) return String(""); + + const char* const colon = strchr(gtest_output_flag, ':'); + return (colon == NULL) ? + String(gtest_output_flag) : + String(gtest_output_flag, colon - gtest_output_flag); +} + +// Returns the name of the requested output file, or the default if none +// was explicitly specified. +String UnitTestOptions::GetAbsolutePathToOutputFile() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) + return String(""); + + const char* const colon = strchr(gtest_output_flag, ':'); + if (colon == NULL) + return String(internal::FilePath::ConcatPaths( + internal::FilePath( + UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(kDefaultOutputFile)).ToString() ); + + internal::FilePath output_name(colon + 1); + if (!output_name.IsAbsolutePath()) + // TODO(wan@google.com): on Windows \some\path is not an absolute + // path (as its meaning depends on the current drive), yet the + // following logic for turning it into an absolute path is wrong. + // Fix it. + output_name = internal::FilePath::ConcatPaths( + internal::FilePath(UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(colon + 1)); + + if (!output_name.IsDirectory()) + return output_name.ToString(); + + internal::FilePath result(internal::FilePath::GenerateUniqueFileName( + output_name, internal::GetCurrentExecutableName(), + GetOutputFormat().c_str())); + return result.ToString(); +} + +// Returns true iff the wildcard pattern matches the string. The +// first ':' or '\0' character in pattern marks the end of it. +// +// This recursive algorithm isn't very efficient, but is clear and +// works well enough for matching test names, which are short. +bool UnitTestOptions::PatternMatchesString(const char *pattern, + const char *str) { + switch (*pattern) { + case '\0': + case ':': // Either ':' or '\0' marks the end of the pattern. + return *str == '\0'; + case '?': // Matches any single character. + return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); + case '*': // Matches any string (possibly empty) of characters. + return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || + PatternMatchesString(pattern + 1, str); + default: // Non-special character. Matches itself. + return *pattern == *str && + PatternMatchesString(pattern + 1, str + 1); + } +} + +bool UnitTestOptions::MatchesFilter(const String& name, const char* filter) { + const char *cur_pattern = filter; + for (;;) { + if (PatternMatchesString(cur_pattern, name.c_str())) { + return true; + } + + // Finds the next pattern in the filter. + cur_pattern = strchr(cur_pattern, ':'); + + // Returns if no more pattern can be found. + if (cur_pattern == NULL) { + return false; + } + + // Skips the pattern separater (the ':' character). + cur_pattern++; + } +} + +// TODO(keithray): move String function implementations to gtest-string.cc. + +// Returns true iff the user-specified filter matches the test case +// name and the test name. +bool UnitTestOptions::FilterMatchesTest(const String &test_case_name, + const String &test_name) { + const String& full_name = String::Format("%s.%s", + test_case_name.c_str(), + test_name.c_str()); + + // Split --gtest_filter at '-', if there is one, to separate into + // positive filter and negative filter portions + const char* const p = GTEST_FLAG(filter).c_str(); + const char* const dash = strchr(p, '-'); + String positive; + String negative; + if (dash == NULL) { + positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter + negative = String(""); + } else { + positive = String(p, dash - p); // Everything up to the dash + negative = String(dash+1); // Everything after the dash + if (positive.empty()) { + // Treat '-test1' as the same as '*-test1' + positive = kUniversalFilter; + } + } + + // A filter is a colon-separated list of patterns. It matches a + // test if any pattern in it matches the test. + return (MatchesFilter(full_name, positive.c_str()) && + !MatchesFilter(full_name, negative.c_str())); +} + +#if GTEST_HAS_SEH +// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the +// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. +// This function is useful as an __except condition. +int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { + // Google Test should handle a SEH exception if: + // 1. the user wants it to, AND + // 2. this is not a breakpoint exception, AND + // 3. this is not a C++ exception (VC++ implements them via SEH, + // apparently). + // + // SEH exception code for C++ exceptions. + // (see http://support.microsoft.com/kb/185294 for more information). + const DWORD kCxxExceptionCode = 0xe06d7363; + + bool should_handle = true; + + if (!GTEST_FLAG(catch_exceptions)) + should_handle = false; + else if (exception_code == EXCEPTION_BREAKPOINT) + should_handle = false; + else if (exception_code == kCxxExceptionCode) + should_handle = false; + + return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; +} +#endif // GTEST_HAS_SEH + +} // namespace internal + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. Intercepts only failures from the current thread. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + TestPartResultArray* result) + : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), + result_(result) { + Init(); +} + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + InterceptMode intercept_mode, TestPartResultArray* result) + : intercept_mode_(intercept_mode), + result_(result) { + Init(); +} + +void ScopedFakeTestPartResultReporter::Init() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + old_reporter_ = impl->GetGlobalTestPartResultReporter(); + impl->SetGlobalTestPartResultReporter(this); + } else { + old_reporter_ = impl->GetTestPartResultReporterForCurrentThread(); + impl->SetTestPartResultReporterForCurrentThread(this); + } +} + +// The d'tor restores the test part result reporter used by Google Test +// before. +ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + impl->SetGlobalTestPartResultReporter(old_reporter_); + } else { + impl->SetTestPartResultReporterForCurrentThread(old_reporter_); + } +} + +// Increments the test part result count and remembers the result. +// This method is from the TestPartResultReporterInterface interface. +void ScopedFakeTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + result_->Append(result); +} + +namespace internal { + +// Returns the type ID of ::testing::Test. We should always call this +// instead of GetTypeId< ::testing::Test>() to get the type ID of +// testing::Test. This is to work around a suspected linker bug when +// using Google Test as a framework on Mac OS X. The bug causes +// GetTypeId< ::testing::Test>() to return different values depending +// on whether the call is from the Google Test framework itself or +// from user test code. GetTestTypeId() is guaranteed to always +// return the same value, as it always calls GetTypeId<>() from the +// gtest.cc, which is within the Google Test framework. +TypeId GetTestTypeId() { + return GetTypeId(); +} + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); + +// This predicate-formatter checks that 'results' contains a test part +// failure of the given type and that the failure message contains the +// given substring. +AssertionResult HasOneFailure(const char* /* results_expr */, + const char* /* type_expr */, + const char* /* substr_expr */, + const TestPartResultArray& results, + TestPartResult::Type type, + const string& substr) { + const String expected(type == TestPartResult::kFatalFailure ? + "1 fatal failure" : + "1 non-fatal failure"); + Message msg; + if (results.size() != 1) { + msg << "Expected: " << expected << "\n" + << " Actual: " << results.size() << " failures"; + for (int i = 0; i < results.size(); i++) { + msg << "\n" << results.GetTestPartResult(i); + } + return AssertionFailure() << msg; + } + + const TestPartResult& r = results.GetTestPartResult(0); + if (r.type() != type) { + return AssertionFailure() << "Expected: " << expected << "\n" + << " Actual:\n" + << r; + } + + if (strstr(r.message(), substr.c_str()) == NULL) { + return AssertionFailure() << "Expected: " << expected << " containing \"" + << substr << "\"\n" + << " Actual:\n" + << r; + } + + return AssertionSuccess(); +} + +// The constructor of SingleFailureChecker remembers where to look up +// test part results, what type of failure we expect, and what +// substring the failure message should contain. +SingleFailureChecker:: SingleFailureChecker( + const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr) + : results_(results), + type_(type), + substr_(substr) {} + +// The destructor of SingleFailureChecker verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +SingleFailureChecker::~SingleFailureChecker() { + EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_); +} + +DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultGlobalTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->current_test_result()->AddTestPartResult(result); + unit_test_->listeners()->repeater()->OnTestPartResult(result); +} + +DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultPerThreadTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result); +} + +// Returns the global test part result reporter. +TestPartResultReporterInterface* +UnitTestImpl::GetGlobalTestPartResultReporter() { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + return global_test_part_result_repoter_; +} + +// Sets the global test part result reporter. +void UnitTestImpl::SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter) { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + global_test_part_result_repoter_ = reporter; +} + +// Returns the test part result reporter for the current thread. +TestPartResultReporterInterface* +UnitTestImpl::GetTestPartResultReporterForCurrentThread() { + return per_thread_test_part_result_reporter_.get(); +} + +// Sets the test part result reporter for the current thread. +void UnitTestImpl::SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter) { + per_thread_test_part_result_reporter_.set(reporter); +} + +// Gets the number of successful test cases. +int UnitTestImpl::successful_test_case_count() const { + return CountIf(test_cases_, TestCasePassed); +} + +// Gets the number of failed test cases. +int UnitTestImpl::failed_test_case_count() const { + return CountIf(test_cases_, TestCaseFailed); +} + +// Gets the number of all test cases. +int UnitTestImpl::total_test_case_count() const { + return static_cast(test_cases_.size()); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTestImpl::test_case_to_run_count() const { + return CountIf(test_cases_, ShouldRunTestCase); +} + +// Gets the number of successful tests. +int UnitTestImpl::successful_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count); +} + +// Gets the number of failed tests. +int UnitTestImpl::failed_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count); +} + +// Gets the number of disabled tests. +int UnitTestImpl::disabled_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count); +} + +// Gets the number of all tests. +int UnitTestImpl::total_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::total_test_count); +} + +// Gets the number of tests that should run. +int UnitTestImpl::test_to_run_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count); +} + +// Returns the current OS stack trace as a String. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// CurrentOsStackTraceExceptTop(1), Foo() will be included in the +// trace but Bar() and CurrentOsStackTraceExceptTop() won't. +String UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { + (void)skip_count; + return String(""); +} + +// Returns the current time in milliseconds. +TimeInMillis GetTimeInMillis() { +#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) + // Difference between 1970-01-01 and 1601-01-01 in milliseconds. + // http://analogous.blogspot.com/2005/04/epoch.html + const TimeInMillis kJavaEpochToWinFileTimeDelta = + static_cast(116444736UL) * 100000UL; + const DWORD kTenthMicrosInMilliSecond = 10000; + + SYSTEMTIME now_systime; + FILETIME now_filetime; + ULARGE_INTEGER now_int64; + // TODO(kenton@google.com): Shouldn't this just use + // GetSystemTimeAsFileTime()? + GetSystemTime(&now_systime); + if (SystemTimeToFileTime(&now_systime, &now_filetime)) { + now_int64.LowPart = now_filetime.dwLowDateTime; + now_int64.HighPart = now_filetime.dwHighDateTime; + now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) - + kJavaEpochToWinFileTimeDelta; + return now_int64.QuadPart; + } + return 0; +#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ + __timeb64 now; + +# ifdef _MSC_VER + + // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 + // (deprecated function) there. + // TODO(kenton@google.com): Use GetTickCount()? Or use + // SystemTimeToFileTime() +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996. + _ftime64(&now); +# pragma warning(pop) // Restores the warning state. +# else + + _ftime64(&now); + +# endif // _MSC_VER + + return static_cast(now.time) * 1000 + now.millitm; +#elif GTEST_HAS_GETTIMEOFDAY_ + struct timeval now; + gettimeofday(&now, NULL); + return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; +#else +# error "Don't know how to get the current time on your system." +#endif +} + +// Utilities + +// class String + +// Returns the input enclosed in double quotes if it's not NULL; +// otherwise returns "(null)". For example, "\"Hello\"" is returned +// for input "Hello". +// +// This is useful for printing a C string in the syntax of a literal. +// +// Known issue: escape sequences are not handled yet. +String String::ShowCStringQuoted(const char* c_str) { + return c_str ? String::Format("\"%s\"", c_str) : String("(null)"); +} + +// Copies at most length characters from str into a newly-allocated +// piece of memory of size length+1. The memory is allocated with new[]. +// A terminating null byte is written to the memory, and a pointer to it +// is returned. If str is NULL, NULL is returned. +static char* CloneString(const char* str, size_t length) { + if (str == NULL) { + return NULL; + } else { + char* const clone = new char[length + 1]; + posix::StrNCpy(clone, str, length); + clone[length] = '\0'; + return clone; + } +} + +// Clones a 0-terminated C string, allocating memory using new. The +// caller is responsible for deleting[] the return value. Returns the +// cloned string, or NULL if the input is NULL. +const char * String::CloneCString(const char* c_str) { + return (c_str == NULL) ? + NULL : CloneString(c_str, strlen(c_str)); +} + +#if GTEST_OS_WINDOWS_MOBILE +// Creates a UTF-16 wide string from the given ANSI string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the wide string, or NULL if the +// input is NULL. +LPCWSTR String::AnsiToUtf16(const char* ansi) { + if (!ansi) return NULL; + const int length = strlen(ansi); + const int unicode_length = + MultiByteToWideChar(CP_ACP, 0, ansi, length, + NULL, 0); + WCHAR* unicode = new WCHAR[unicode_length + 1]; + MultiByteToWideChar(CP_ACP, 0, ansi, length, + unicode, unicode_length); + unicode[unicode_length] = 0; + return unicode; +} + +// Creates an ANSI string from the given wide string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the ANSI string, or NULL if the +// input is NULL. +const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { + if (!utf16_str) return NULL; + const int ansi_length = + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + NULL, 0, NULL, NULL); + char* ansi = new char[ansi_length + 1]; + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + ansi, ansi_length, NULL, NULL); + ansi[ansi_length] = 0; + return ansi; +} + +#endif // GTEST_OS_WINDOWS_MOBILE + +// Compares two C strings. Returns true iff they have the same content. +// +// Unlike strcmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CStringEquals(const char * lhs, const char * rhs) { + if ( lhs == NULL ) return rhs == NULL; + + if ( rhs == NULL ) return false; + + return strcmp(lhs, rhs) == 0; +} + +#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +// Converts an array of wide chars to a narrow string using the UTF-8 +// encoding, and streams the result to the given Message object. +static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, + Message* msg) { + // TODO(wan): consider allowing a testing::String object to + // contain '\0'. This will make it behave more like std::string, + // and will allow ToUtf8String() to return the correct encoding + // for '\0' s.t. we can get rid of the conditional here (and in + // several other places). + for (size_t i = 0; i != length; ) { // NOLINT + if (wstr[i] != L'\0') { + *msg << WideStringToUtf8(wstr + i, static_cast(length - i)); + while (i != length && wstr[i] != L'\0') + i++; + } else { + *msg << '\0'; + i++; + } + } +} + +#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +} // namespace internal + +#if GTEST_HAS_STD_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::std::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +// AssertionResult constructors. +// Used in EXPECT_TRUE/FALSE(assertion_result). +AssertionResult::AssertionResult(const AssertionResult& other) + : success_(other.success_), + message_(other.message_.get() != NULL ? + new ::std::string(*other.message_) : + static_cast< ::std::string*>(NULL)) { +} + +// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. +AssertionResult AssertionResult::operator!() const { + AssertionResult negation(!success_); + if (message_.get() != NULL) + negation << *message_; + return negation; +} + +// Makes a successful assertion result. +AssertionResult AssertionSuccess() { + return AssertionResult(true); +} + +// Makes a failed assertion result. +AssertionResult AssertionFailure() { + return AssertionResult(false); +} + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << message. +AssertionResult AssertionFailure(const Message& message) { + return AssertionFailure() << message; +} + +namespace internal { + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const String& expected_value, + const String& actual_value, + bool ignoring_case) { + Message msg; + msg << "Value of: " << actual_expression; + if (actual_value != actual_expression) { + msg << "\n Actual: " << actual_value; + } + + msg << "\nExpected: " << expected_expression; + if (ignoring_case) { + msg << " (ignoring case)"; + } + if (expected_value != expected_expression) { + msg << "\nWhich is: " << expected_value; + } + + return AssertionFailure() << msg; +} + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +String GetBoolAssertionFailureMessage(const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value) { + const char* actual_message = assertion_result.message(); + Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} + +// Helper function for implementing ASSERT_NEAR. +AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error) { + const double diff = fabs(val1 - val2); + if (diff <= abs_error) return AssertionSuccess(); + + // TODO(wan): do not print the value of an expression if it's + // already a literal. + return AssertionFailure() + << "The difference between " << expr1 << " and " << expr2 + << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" + << expr1 << " evaluates to " << val1 << ",\n" + << expr2 << " evaluates to " << val2 << ", and\n" + << abs_error_expr << " evaluates to " << abs_error << "."; +} + + +// Helper template for implementing FloatLE() and DoubleLE(). +template +AssertionResult FloatingPointLE(const char* expr1, + const char* expr2, + RawType val1, + RawType val2) { + // Returns success if val1 is less than val2, + if (val1 < val2) { + return AssertionSuccess(); + } + + // or if val1 is almost equal to val2. + const FloatingPoint lhs(val1), rhs(val2); + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + // Note that the above two checks will both fail if either val1 or + // val2 is NaN, as the IEEE floating-point standard requires that + // any predicate involving a NaN must return false. + + ::std::stringstream val1_ss; + val1_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val1; + + ::std::stringstream val2_ss; + val2_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val2; + + return AssertionFailure() + << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n" + << " Actual: " << StringStreamToString(&val1_ss) << " vs " + << StringStreamToString(&val2_ss); +} + +} // namespace internal + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +namespace internal { + +// The helper function for {ASSERT|EXPECT}_EQ with int or enum +// arguments. +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + if (expected == actual) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here +// just to avoid copy-and-paste of similar code. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + BiggestInt val1, BiggestInt val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +} + +// Implements the helper function for {ASSERT|EXPECT}_NE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(NE, !=) +// Implements the helper function for {ASSERT|EXPECT}_LE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LE, <=) +// Implements the helper function for {ASSERT|EXPECT}_LT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LT, < ) +// Implements the helper function for {ASSERT|EXPECT}_GE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GE, >=) +// Implements the helper function for {ASSERT|EXPECT}_GT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GT, > ) + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + String::ShowCStringQuoted(expected), + String::ShowCStringQuoted(actual), + false); +} + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CaseInsensitiveCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + String::ShowCStringQuoted(expected), + String::ShowCStringQuoted(actual), + true); +} + +// The helper function for {ASSERT|EXPECT}_STRNE. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CaseInsensitiveCStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() + << "Expected: (" << s1_expression << ") != (" + << s2_expression << ") (ignoring case), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +} // namespace internal + +namespace { + +// Helper functions for implementing IsSubString() and IsNotSubstring(). + +// This group of overloaded functions return true iff needle is a +// substring of haystack. NULL is considered a substring of itself +// only. + +bool IsSubstringPred(const char* needle, const char* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return strstr(haystack, needle) != NULL; +} + +bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return wcsstr(haystack, needle) != NULL; +} + +// StringType here can be either ::std::string or ::std::wstring. +template +bool IsSubstringPred(const StringType& needle, + const StringType& haystack) { + return haystack.find(needle) != StringType::npos; +} + +// This function implements either IsSubstring() or IsNotSubstring(), +// depending on the value of the expected_to_be_substring parameter. +// StringType here can be const char*, const wchar_t*, ::std::string, +// or ::std::wstring. +template +AssertionResult IsSubstringImpl( + bool expected_to_be_substring, + const char* needle_expr, const char* haystack_expr, + const StringType& needle, const StringType& haystack) { + if (IsSubstringPred(needle, haystack) == expected_to_be_substring) + return AssertionSuccess(); + + const bool is_wide_string = sizeof(needle[0]) > 1; + const char* const begin_string_quote = is_wide_string ? "L\"" : "\""; + return AssertionFailure() + << "Value of: " << needle_expr << "\n" + << " Actual: " << begin_string_quote << needle << "\"\n" + << "Expected: " << (expected_to_be_substring ? "" : "not ") + << "a substring of " << haystack_expr << "\n" + << "Which is: " << begin_string_quote << haystack << "\""; +} + +} // namespace + +// IsSubstring() and IsNotSubstring() check whether needle is a +// substring of haystack (NULL is considered a substring of itself +// only), and return an appropriate error message when they fail. + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +#if GTEST_HAS_STD_WSTRING +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +#if GTEST_OS_WINDOWS + +namespace { + +// Helper function for IsHRESULT{SuccessFailure} predicates +AssertionResult HRESULTFailureHelper(const char* expr, + const char* expected, + long hr) { // NOLINT +# if GTEST_OS_WINDOWS_MOBILE + + // Windows CE doesn't support FormatMessage. + const char error_text[] = ""; + +# else + + // Looks up the human-readable system message for the HRESULT code + // and since we're not passing any params to FormatMessage, we don't + // want inserts expanded. + const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + const DWORD kBufSize = 4096; // String::Format can't exceed this length. + // Gets the system's human readable message string for this HRESULT. + char error_text[kBufSize] = { '\0' }; + DWORD message_length = ::FormatMessageA(kFlags, + 0, // no source, we're asking system + hr, // the error + 0, // no line width restrictions + error_text, // output buffer + kBufSize, // buf size + NULL); // no arguments for inserts + // Trims tailing white space (FormatMessage leaves a trailing cr-lf) + for (; message_length && IsSpace(error_text[message_length - 1]); + --message_length) { + error_text[message_length - 1] = '\0'; + } + +# endif // GTEST_OS_WINDOWS_MOBILE + + const String error_hex(String::Format("0x%08X ", hr)); + return ::testing::AssertionFailure() + << "Expected: " << expr << " " << expected << ".\n" + << " Actual: " << error_hex << error_text << "\n"; +} + +} // namespace + +AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT + if (SUCCEEDED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "succeeds", hr); +} + +AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT + if (FAILED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "fails", hr); +} + +#endif // GTEST_OS_WINDOWS + +// Utility functions for encoding Unicode text (wide strings) in +// UTF-8. + +// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 +// like this: +// +// Code-point length Encoding +// 0 - 7 bits 0xxxxxxx +// 8 - 11 bits 110xxxxx 10xxxxxx +// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx +// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +// The maximum code-point a one-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint1 = (static_cast(1) << 7) - 1; + +// The maximum code-point a two-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint2 = (static_cast(1) << (5 + 6)) - 1; + +// The maximum code-point a three-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint3 = (static_cast(1) << (4 + 2*6)) - 1; + +// The maximum code-point a four-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint4 = (static_cast(1) << (3 + 3*6)) - 1; + +// Chops off the n lowest bits from a bit pattern. Returns the n +// lowest bits. As a side effect, the original bit pattern will be +// shifted to the right by n bits. +inline UInt32 ChopLowBits(UInt32* bits, int n) { + const UInt32 low_bits = *bits & ((static_cast(1) << n) - 1); + *bits >>= n; + return low_bits; +} + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// The output buffer str must containt at least 32 characters. +// The function returns the address of the output buffer. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. +char* CodePointToUtf8(UInt32 code_point, char* str) { + if (code_point <= kMaxCodePoint1) { + str[1] = '\0'; + str[0] = static_cast(code_point); // 0xxxxxxx + } else if (code_point <= kMaxCodePoint2) { + str[2] = '\0'; + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xC0 | code_point); // 110xxxxx + } else if (code_point <= kMaxCodePoint3) { + str[3] = '\0'; + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xE0 | code_point); // 1110xxxx + } else if (code_point <= kMaxCodePoint4) { + str[4] = '\0'; + str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xF0 | code_point); // 11110xxx + } else { + // The longest string String::Format can produce when invoked + // with these parameters is 28 character long (not including + // the terminating nul character). We are asking for 32 character + // buffer just in case. This is also enough for strncpy to + // null-terminate the destination string. + posix::StrNCpy( + str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), 32); + str[31] = '\0'; // Makes sure no change in the format to strncpy leaves + // the result unterminated. + } + return str; +} + +// The following two functions only make sense if the the system +// uses UTF-16 for wide string encoding. All supported systems +// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16. + +// Determines if the arguments constitute UTF-16 surrogate pair +// and thus should be combined into a single Unicode code point +// using CreateCodePointFromUtf16SurrogatePair. +inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { + return sizeof(wchar_t) == 2 && + (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; +} + +// Creates a Unicode code point from UTF16 surrogate pair. +inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, + wchar_t second) { + const UInt32 mask = (1 << 10) - 1; + return (sizeof(wchar_t) == 2) ? + (((first & mask) << 10) | (second & mask)) + 0x10000 : + // This function should not be called when the condition is + // false, but we provide a sensible default in case it is. + static_cast(first); +} + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +String WideStringToUtf8(const wchar_t* str, int num_chars) { + if (num_chars == -1) + num_chars = static_cast(wcslen(str)); + + ::std::stringstream stream; + for (int i = 0; i < num_chars; ++i) { + UInt32 unicode_code_point; + + if (str[i] == L'\0') { + break; + } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) { + unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i], + str[i + 1]); + i++; + } else { + unicode_code_point = static_cast(str[i]); + } + + char buffer[32]; // CodePointToUtf8 requires a buffer this big. + stream << CodePointToUtf8(unicode_code_point, buffer); + } + return StringStreamToString(&stream); +} + +// Converts a wide C string to a String using the UTF-8 encoding. +// NULL will be converted to "(null)". +String String::ShowWideCString(const wchar_t * wide_c_str) { + if (wide_c_str == NULL) return String("(null)"); + + return String(internal::WideStringToUtf8(wide_c_str, -1).c_str()); +} + +// Similar to ShowWideCString(), except that this function encloses +// the converted string in double quotes. +String String::ShowWideCStringQuoted(const wchar_t* wide_c_str) { + if (wide_c_str == NULL) return String("(null)"); + + return String::Format("L\"%s\"", + String::ShowWideCString(wide_c_str).c_str()); +} + +// Compares two wide C strings. Returns true iff they have the same +// content. +// +// Unlike wcscmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + + return wcscmp(lhs, rhs) == 0; +} + +// Helper function for *_STREQ on wide strings. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual) { + if (String::WideCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + String::ShowWideCStringQuoted(expected), + String::ShowWideCStringQuoted(actual), + false); +} + +// Helper function for *_STRNE on wide strings. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2) { + if (!String::WideCStringEquals(s1, s2)) { + return AssertionSuccess(); + } + + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: " + << String::ShowWideCStringQuoted(s1) + << " vs " << String::ShowWideCStringQuoted(s2); +} + +// Compares two C strings, ignoring case. Returns true iff they have +// the same content. +// +// Unlike strcasecmp(), this function can handle NULL argument(s). A +// NULL C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { + if (lhs == NULL) + return rhs == NULL; + if (rhs == NULL) + return false; + return posix::StrCaseCmp(lhs, rhs) == 0; +} + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. +bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + +#if GTEST_OS_WINDOWS + return _wcsicmp(lhs, rhs) == 0; +#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID + return wcscasecmp(lhs, rhs) == 0; +#else + // Android, Mac OS X and Cygwin don't define wcscasecmp. + // Other unknown OSes may not define it either. + wint_t left, right; + do { + left = towlower(*lhs++); + right = towlower(*rhs++); + } while (left && left == right); + return left == right; +#endif // OS selector +} + +// Compares this with another String. +// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0 +// if this is greater than rhs. +int String::Compare(const String & rhs) const { + const char* const lhs_c_str = c_str(); + const char* const rhs_c_str = rhs.c_str(); + + if (lhs_c_str == NULL) { + return rhs_c_str == NULL ? 0 : -1; // NULL < anything except NULL + } else if (rhs_c_str == NULL) { + return 1; + } + + const size_t shorter_str_len = + length() <= rhs.length() ? length() : rhs.length(); + for (size_t i = 0; i != shorter_str_len; i++) { + if (lhs_c_str[i] < rhs_c_str[i]) { + return -1; + } else if (lhs_c_str[i] > rhs_c_str[i]) { + return 1; + } + } + return (length() < rhs.length()) ? -1 : + (length() > rhs.length()) ? 1 : 0; +} + +// Returns true iff this String ends with the given suffix. *Any* +// String is considered to end with a NULL or empty suffix. +bool String::EndsWith(const char* suffix) const { + if (suffix == NULL || CStringEquals(suffix, "")) return true; + + if (c_str() == NULL) return false; + + const size_t this_len = strlen(c_str()); + const size_t suffix_len = strlen(suffix); + return (this_len >= suffix_len) && + CStringEquals(c_str() + this_len - suffix_len, suffix); +} + +// Returns true iff this String ends with the given suffix, ignoring case. +// Any String is considered to end with a NULL or empty suffix. +bool String::EndsWithCaseInsensitive(const char* suffix) const { + if (suffix == NULL || CStringEquals(suffix, "")) return true; + + if (c_str() == NULL) return false; + + const size_t this_len = strlen(c_str()); + const size_t suffix_len = strlen(suffix); + return (this_len >= suffix_len) && + CaseInsensitiveCStringEquals(c_str() + this_len - suffix_len, suffix); +} + +// Formats a list of arguments to a String, using the same format +// spec string as for printf. +// +// We do not use the StringPrintf class as it is not universally +// available. +// +// The result is limited to 4096 characters (including the tailing 0). +// If 4096 characters are not enough to format the input, or if +// there's an error, "" is +// returned. +String String::Format(const char * format, ...) { + va_list args; + va_start(args, format); + + char buffer[4096]; + const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]); + + // MSVC 8 deprecates vsnprintf(), so we want to suppress warning + // 4996 (deprecated function) there. +#ifdef _MSC_VER // We are using MSVC. +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996. + + const int size = vsnprintf(buffer, kBufferSize, format, args); + +# pragma warning(pop) // Restores the warning state. +#else // We are not using MSVC. + const int size = vsnprintf(buffer, kBufferSize, format, args); +#endif // _MSC_VER + va_end(args); + + // vsnprintf()'s behavior is not portable. When the buffer is not + // big enough, it returns a negative value in MSVC, and returns the + // needed buffer size on Linux. When there is an output error, it + // always returns a negative value. For simplicity, we lump the two + // error cases together. + if (size < 0 || size >= kBufferSize) { + return String(""); + } else { + return String(buffer, size); + } +} + +// Converts the buffer in a stringstream to a String, converting NUL +// bytes to "\\0" along the way. +String StringStreamToString(::std::stringstream* ss) { + const ::std::string& str = ss->str(); + const char* const start = str.c_str(); + const char* const end = start + str.length(); + + // We need to use a helper stringstream to do this transformation + // because String doesn't support push_back(). + ::std::stringstream helper; + for (const char* ch = start; ch != end; ++ch) { + if (*ch == '\0') { + helper << "\\0"; // Replaces NUL with "\\0"; + } else { + helper.put(*ch); + } + } + + return String(helper.str().c_str()); +} + +// Appends the user-supplied message to the Google-Test-generated message. +String AppendUserMessage(const String& gtest_msg, + const Message& user_msg) { + // Appends the user message if it's non-empty. + const String user_msg_string = user_msg.GetString(); + if (user_msg_string.empty()) { + return gtest_msg; + } + + Message msg; + msg << gtest_msg << "\n" << user_msg_string; + + return msg.GetString(); +} + +} // namespace internal + +// class TestResult + +// Creates an empty TestResult. +TestResult::TestResult() + : death_test_count_(0), + elapsed_time_(0) { +} + +// D'tor. +TestResult::~TestResult() { +} + +// Returns the i-th test part result among all the results. i can +// range from 0 to total_part_count() - 1. If i is not in that range, +// aborts the program. +const TestPartResult& TestResult::GetTestPartResult(int i) const { + if (i < 0 || i >= total_part_count()) + internal::posix::Abort(); + return test_part_results_.at(i); +} + +// Returns the i-th test property. i can range from 0 to +// test_property_count() - 1. If i is not in that range, aborts the +// program. +const TestProperty& TestResult::GetTestProperty(int i) const { + if (i < 0 || i >= test_property_count()) + internal::posix::Abort(); + return test_properties_.at(i); +} + +// Clears the test part results. +void TestResult::ClearTestPartResults() { + test_part_results_.clear(); +} + +// Adds a test part result to the list. +void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { + test_part_results_.push_back(test_part_result); +} + +// Adds a test property to the list. If a property with the same key as the +// supplied property is already represented, the value of this test_property +// replaces the old value for that key. +void TestResult::RecordProperty(const TestProperty& test_property) { + if (!ValidateTestProperty(test_property)) { + return; + } + internal::MutexLock lock(&test_properites_mutex_); + const std::vector::iterator property_with_matching_key = + std::find_if(test_properties_.begin(), test_properties_.end(), + internal::TestPropertyKeyIs(test_property.key())); + if (property_with_matching_key == test_properties_.end()) { + test_properties_.push_back(test_property); + return; + } + property_with_matching_key->SetValue(test_property.value()); +} + +// Adds a failure if the key is a reserved attribute of Google Test +// testcase tags. Returns true if the property is valid. +bool TestResult::ValidateTestProperty(const TestProperty& test_property) { + internal::String key(test_property.key()); + if (key == "name" || key == "status" || key == "time" || key == "classname") { + ADD_FAILURE() + << "Reserved key used in RecordProperty(): " + << key + << " ('name', 'status', 'time', and 'classname' are reserved by " + << GTEST_NAME_ << ")"; + return false; + } + return true; +} + +// Clears the object. +void TestResult::Clear() { + test_part_results_.clear(); + test_properties_.clear(); + death_test_count_ = 0; + elapsed_time_ = 0; +} + +// Returns true iff the test failed. +bool TestResult::Failed() const { + for (int i = 0; i < total_part_count(); ++i) { + if (GetTestPartResult(i).failed()) + return true; + } + return false; +} + +// Returns true iff the test part fatally failed. +static bool TestPartFatallyFailed(const TestPartResult& result) { + return result.fatally_failed(); +} + +// Returns true iff the test fatally failed. +bool TestResult::HasFatalFailure() const { + return CountIf(test_part_results_, TestPartFatallyFailed) > 0; +} + +// Returns true iff the test part non-fatally failed. +static bool TestPartNonfatallyFailed(const TestPartResult& result) { + return result.nonfatally_failed(); +} + +// Returns true iff the test has a non-fatal failure. +bool TestResult::HasNonfatalFailure() const { + return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; +} + +// Gets the number of all test parts. This is the sum of the number +// of successful test parts and the number of failed test parts. +int TestResult::total_part_count() const { + return static_cast(test_part_results_.size()); +} + +// Returns the number of the test properties. +int TestResult::test_property_count() const { + return static_cast(test_properties_.size()); +} + +// class Test + +// Creates a Test object. + +// The c'tor saves the values of all Google Test flags. +Test::Test() + : gtest_flag_saver_(new internal::GTestFlagSaver) { +} + +// The d'tor restores the values of all Google Test flags. +Test::~Test() { + delete gtest_flag_saver_; +} + +// Sets up the test fixture. +// +// A sub-class may override this. +void Test::SetUp() { +} + +// Tears down the test fixture. +// +// A sub-class may override this. +void Test::TearDown() { +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const char* key, const char* value) { + UnitTest::GetInstance()->RecordPropertyForCurrentTest(key, value); +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const char* key, int value) { + Message value_message; + value_message << value; + RecordProperty(key, value_message.GetString().c_str()); +} + +namespace internal { + +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const String& message) { + // This function is a friend of UnitTest and as such has access to + // AddTestPartResult. + UnitTest::GetInstance()->AddTestPartResult( + result_type, + NULL, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. + message, + String()); // No stack trace, either. +} + +} // namespace internal + +// Google Test requires all tests in the same test case to use the same test +// fixture class. This function checks if the current test has the +// same fixture class as the first test in the current test case. If +// yes, it returns true; otherwise it generates a Google Test failure and +// returns false. +bool Test::HasSameFixtureClass() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + const TestCase* const test_case = impl->current_test_case(); + + // Info about the first test in the current test case. + const TestInfo* const first_test_info = test_case->test_info_list()[0]; + const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; + const char* const first_test_name = first_test_info->name(); + + // Info about the current test. + const TestInfo* const this_test_info = impl->current_test_info(); + const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_; + const char* const this_test_name = this_test_info->name(); + + if (this_fixture_id != first_fixture_id) { + // Is the first test defined using TEST? + const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); + // Is this test defined using TEST? + const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); + + if (first_is_TEST || this_is_TEST) { + // The user mixed TEST and TEST_F in this test case - we'll tell + // him/her how to fix it. + + // Gets the name of the TEST and the name of the TEST_F. Note + // that first_is_TEST and this_is_TEST cannot both be true, as + // the fixture IDs are different for the two tests. + const char* const TEST_name = + first_is_TEST ? first_test_name : this_test_name; + const char* const TEST_F_name = + first_is_TEST ? this_test_name : first_test_name; + + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class, so mixing TEST_F and TEST in the same test case is\n" + << "illegal. In test case " << this_test_info->test_case_name() + << ",\n" + << "test " << TEST_F_name << " is defined using TEST_F but\n" + << "test " << TEST_name << " is defined using TEST. You probably\n" + << "want to change the TEST to TEST_F or move it to another test\n" + << "case."; + } else { + // The user defined two fixture classes with the same name in + // two namespaces - we'll tell him/her how to fix it. + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " + << this_test_info->test_case_name() << ",\n" + << "you defined test " << first_test_name + << " and test " << this_test_name << "\n" + << "using two different test fixture classes. This can happen if\n" + << "the two classes are from different namespaces or translation\n" + << "units and have the same name. You should probably rename one\n" + << "of the classes to put the tests into different test cases."; + } + return false; + } + + return true; +} + +#if GTEST_HAS_SEH + +// Adds an "exception thrown" fatal failure to the current test. This +// function returns its result via an output parameter pointer because VC++ +// prohibits creation of objects with destructors on stack in functions +// using __try (see error C2712). +static internal::String* FormatSehExceptionMessage(DWORD exception_code, + const char* location) { + Message message; + message << "SEH exception with code 0x" << std::setbase(16) << + exception_code << std::setbase(10) << " thrown in " << location << "."; + + return new internal::String(message.GetString()); +} + +#endif // GTEST_HAS_SEH + +#if GTEST_HAS_EXCEPTIONS + +// Adds an "exception thrown" fatal failure to the current test. +static internal::String FormatCxxExceptionMessage(const char* description, + const char* location) { + Message message; + if (description != NULL) { + message << "C++ exception with description \"" << description << "\""; + } else { + message << "Unknown C++ exception"; + } + message << " thrown in " << location << "."; + + return message.GetString(); +} + +static internal::String PrintTestPartResultToString( + const TestPartResult& test_part_result); + +// A failed Google Test assertion will throw an exception of this type when +// GTEST_FLAG(throw_on_failure) is true (if exceptions are enabled). We +// derive it from std::runtime_error, which is for errors presumably +// detectable only at run time. Since std::runtime_error inherits from +// std::exception, many testing frameworks know how to extract and print the +// message inside it. +class GoogleTestFailureException : public ::std::runtime_error { + public: + explicit GoogleTestFailureException(const TestPartResult& failure) + : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} +}; +#endif // GTEST_HAS_EXCEPTIONS + +namespace internal { +// We put these helper functions in the internal namespace as IBM's xlC +// compiler rejects the code if they were declared static. + +// Runs the given method and handles SEH exceptions it throws, when +// SEH is supported; returns the 0-value for type Result in case of an +// SEH exception. (Microsoft compilers cannot handle SEH and C++ +// exceptions in the same function. Therefore, we provide a separate +// wrapper function for handling SEH exceptions.) +template +Result HandleSehExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { +#if GTEST_HAS_SEH + __try { + return (object->*method)(); + } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT + GetExceptionCode())) { + // We create the exception message on the heap because VC++ prohibits + // creation of objects with destructors on stack in functions using __try + // (see error C2712). + internal::String* exception_message = FormatSehExceptionMessage( + GetExceptionCode(), location); + internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, + *exception_message); + delete exception_message; + return static_cast(0); + } +#else + (void)location; + return (object->*method)(); +#endif // GTEST_HAS_SEH +} + +// Runs the given method and catches and reports C++ and/or SEH-style +// exceptions, if they are supported; returns the 0-value for type +// Result in case of an SEH exception. +template +Result HandleExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { + // NOTE: The user code can affect the way in which Google Test handles + // exceptions by setting GTEST_FLAG(catch_exceptions), but only before + // RUN_ALL_TESTS() starts. It is technically possible to check the flag + // after the exception is caught and either report or re-throw the + // exception based on the flag's value: + // + // try { + // // Perform the test method. + // } catch (...) { + // if (GTEST_FLAG(catch_exceptions)) + // // Report the exception as failure. + // else + // throw; // Re-throws the original exception. + // } + // + // However, the purpose of this flag is to allow the program to drop into + // the debugger when the exception is thrown. On most platforms, once the + // control enters the catch block, the exception origin information is + // lost and the debugger will stop the program at the point of the + // re-throw in this function -- instead of at the point of the original + // throw statement in the code under test. For this reason, we perform + // the check early, sacrificing the ability to affect Google Test's + // exception handling in the method where the exception is thrown. + if (internal::GetUnitTestImpl()->catch_exceptions()) { +#if GTEST_HAS_EXCEPTIONS + try { + return HandleSehExceptionsInMethodIfSupported(object, method, location); + } catch (const GoogleTestFailureException&) { // NOLINT + // This exception doesn't originate in code under test. It makes no + // sense to report it as a test failure. + throw; + } catch (const std::exception& e) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(e.what(), location)); + } catch (...) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(NULL, location)); + } + return static_cast(0); +#else + return HandleSehExceptionsInMethodIfSupported(object, method, location); +#endif // GTEST_HAS_EXCEPTIONS + } else { + return (object->*method)(); + } +} + +} // namespace internal + +// Runs the test and updates the test result. +void Test::Run() { + if (!HasSameFixtureClass()) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); + // We will run the test only if SetUp() was successful. + if (!HasFatalFailure()) { + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TestBody, "the test body"); + } + + // However, we want to clean up as much as possible. Hence we will + // always call TearDown(), even if SetUp() or the test body has + // failed. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TearDown, "TearDown()"); +} + +// Returns true iff the current test has a fatal failure. +bool Test::HasFatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); +} + +// Returns true iff the current test has a non-fatal failure. +bool Test::HasNonfatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()-> + HasNonfatalFailure(); +} + +// class TestInfo + +// Constructs a TestInfo object. It assumes ownership of the test factory +// object. +// TODO(vladl@google.com): Make a_test_case_name and a_name const string&'s +// to signify they cannot be NULLs. +TestInfo::TestInfo(const char* a_test_case_name, + const char* a_name, + const char* a_type_param, + const char* a_value_param, + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory) + : test_case_name_(a_test_case_name), + name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + value_param_(a_value_param ? new std::string(a_value_param) : NULL), + fixture_class_id_(fixture_class_id), + should_run_(false), + is_disabled_(false), + matches_filter_(false), + factory_(factory), + result_() {} + +// Destructs a TestInfo object. +TestInfo::~TestInfo() { delete factory_; } + +namespace internal { + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param: the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param: text representation of the test's value parameter, +// or NULL if this is not a value-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory) { + TestInfo* const test_info = + new TestInfo(test_case_name, name, type_param, value_param, + fixture_class_id, factory); + GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); + return test_info; +} + +#if GTEST_HAS_PARAM_TEST +void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line) { + Message errors; + errors + << "Attempted redefinition of test case " << test_case_name << ".\n" + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " << test_case_name << ", you tried\n" + << "to define a test using a fixture class different from the one\n" + << "used earlier. This can happen if the two fixture classes are\n" + << "from different namespaces and have the same name. You should\n" + << "probably rename one of the classes to put the tests into different\n" + << "test cases."; + + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors.GetString().c_str()); +} +#endif // GTEST_HAS_PARAM_TEST + +} // namespace internal + +namespace { + +// A predicate that checks the test name of a TestInfo against a known +// value. +// +// This is used for implementation of the TestCase class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestNameIs is copyable. +class TestNameIs { + public: + // Constructor. + // + // TestNameIs has NO default constructor. + explicit TestNameIs(const char* name) + : name_(name) {} + + // Returns true iff the test name of test_info matches name_. + bool operator()(const TestInfo * test_info) const { + return test_info && internal::String(test_info->name()).Compare(name_) == 0; + } + + private: + internal::String name_; +}; + +} // namespace + +namespace internal { + +// This method expands all parameterized tests registered with macros TEST_P +// and INSTANTIATE_TEST_CASE_P into regular tests and registers those. +// This will be done just once during the program runtime. +void UnitTestImpl::RegisterParameterizedTests() { +#if GTEST_HAS_PARAM_TEST + if (!parameterized_tests_registered_) { + parameterized_test_registry_.RegisterTests(); + parameterized_tests_registered_ = true; + } +#endif +} + +} // namespace internal + +// Creates the test object, runs it, records its result, and then +// deletes it. +void TestInfo::Run() { + if (!should_run_) return; + + // Tells UnitTest where to store test result. + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_info(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + // Notifies the unit test event listeners that a test is about to start. + repeater->OnTestStart(*this); + + const TimeInMillis start = internal::GetTimeInMillis(); + + impl->os_stack_trace_getter()->UponLeavingGTest(); + + // Creates the test object. + Test* const test = internal::HandleExceptionsInMethodIfSupported( + factory_, &internal::TestFactoryBase::CreateTest, + "the test fixture's constructor"); + + // Runs the test only if the test object was created and its + // constructor didn't generate a fatal failure. + if ((test != NULL) && !Test::HasFatalFailure()) { + // This doesn't throw as all user code that can throw are wrapped into + // exception handling code. + test->Run(); + } + + // Deletes the test object. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + test, &Test::DeleteSelf_, "the test fixture's destructor"); + + result_.set_elapsed_time(internal::GetTimeInMillis() - start); + + // Notifies the unit test event listener that a test has just finished. + repeater->OnTestEnd(*this); + + // Tells UnitTest to stop associating assertion results to this + // test. + impl->set_current_test_info(NULL); +} + +// class TestCase + +// Gets the number of successful tests in this test case. +int TestCase::successful_test_count() const { + return CountIf(test_info_list_, TestPassed); +} + +// Gets the number of failed tests in this test case. +int TestCase::failed_test_count() const { + return CountIf(test_info_list_, TestFailed); +} + +int TestCase::disabled_test_count() const { + return CountIf(test_info_list_, TestDisabled); +} + +// Get the number of tests in this test case that should run. +int TestCase::test_to_run_count() const { + return CountIf(test_info_list_, ShouldRunTest); +} + +// Gets the number of all tests. +int TestCase::total_test_count() const { + return static_cast(test_info_list_.size()); +} + +// Creates a TestCase with the given name. +// +// Arguments: +// +// name: name of the test case +// a_type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase::TestCase(const char* a_name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) + : name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + set_up_tc_(set_up_tc), + tear_down_tc_(tear_down_tc), + should_run_(false), + elapsed_time_(0) { +} + +// Destructor of TestCase. +TestCase::~TestCase() { + // Deletes every Test in the collection. + ForEach(test_info_list_, internal::Delete); +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +const TestInfo* TestCase::GetTestInfo(int i) const { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +TestInfo* TestCase::GetMutableTestInfo(int i) { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Adds a test to this test case. Will delete the test upon +// destruction of the TestCase object. +void TestCase::AddTestInfo(TestInfo * test_info) { + test_info_list_.push_back(test_info); + test_indices_.push_back(static_cast(test_indices_.size())); +} + +// Runs every test in this TestCase. +void TestCase::Run() { + if (!should_run_) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_case(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + repeater->OnTestCaseStart(*this); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); + + const internal::TimeInMillis start = internal::GetTimeInMillis(); + for (int i = 0; i < total_test_count(); i++) { + GetMutableTestInfo(i)->Run(); + } + elapsed_time_ = internal::GetTimeInMillis() - start; + + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); + + repeater->OnTestCaseEnd(*this); + impl->set_current_test_case(NULL); +} + +// Clears the results of all tests in this test case. +void TestCase::ClearResult() { + ForEach(test_info_list_, TestInfo::ClearTestResult); +} + +// Shuffles the tests in this test case. +void TestCase::ShuffleTests(internal::Random* random) { + Shuffle(random, &test_indices_); +} + +// Restores the test order to before the first shuffle. +void TestCase::UnshuffleTests() { + for (size_t i = 0; i < test_indices_.size(); i++) { + test_indices_[i] = static_cast(i); + } +} + +// Formats a countable noun. Depending on its quantity, either the +// singular form or the plural form is used. e.g. +// +// FormatCountableNoun(1, "formula", "formuli") returns "1 formula". +// FormatCountableNoun(5, "book", "books") returns "5 books". +static internal::String FormatCountableNoun(int count, + const char * singular_form, + const char * plural_form) { + return internal::String::Format("%d %s", count, + count == 1 ? singular_form : plural_form); +} + +// Formats the count of tests. +static internal::String FormatTestCount(int test_count) { + return FormatCountableNoun(test_count, "test", "tests"); +} + +// Formats the count of test cases. +static internal::String FormatTestCaseCount(int test_case_count) { + return FormatCountableNoun(test_case_count, "test case", "test cases"); +} + +// Converts a TestPartResult::Type enum to human-friendly string +// representation. Both kNonFatalFailure and kFatalFailure are translated +// to "Failure", as the user usually doesn't care about the difference +// between the two when viewing the test result. +static const char * TestPartResultTypeToString(TestPartResult::Type type) { + switch (type) { + case TestPartResult::kSuccess: + return "Success"; + + case TestPartResult::kNonFatalFailure: + case TestPartResult::kFatalFailure: +#ifdef _MSC_VER + return "error: "; +#else + return "Failure\n"; +#endif + default: + return "Unknown result type"; + } +} + +// Prints a TestPartResult to a String. +static internal::String PrintTestPartResultToString( + const TestPartResult& test_part_result) { + return (Message() + << internal::FormatFileLocation(test_part_result.file_name(), + test_part_result.line_number()) + << " " << TestPartResultTypeToString(test_part_result.type()) + << test_part_result.message()).GetString(); +} + +// Prints a TestPartResult. +static void PrintTestPartResult(const TestPartResult& test_part_result) { + const internal::String& result = + PrintTestPartResultToString(test_part_result); + printf("%s\n", result.c_str()); + fflush(stdout); + // If the test program runs in Visual Studio or a debugger, the + // following statements add the test part result message to the Output + // window such that the user can double-click on it to jump to the + // corresponding source code location; otherwise they do nothing. +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + // We don't call OutputDebugString*() on Windows Mobile, as printing + // to stdout is done by OutputDebugString() there already - we don't + // want the same message printed twice. + ::OutputDebugStringA(result.c_str()); + ::OutputDebugStringA("\n"); +#endif +} + +// class PrettyUnitTestResultPrinter + +namespace internal { + +enum GTestColor { + COLOR_DEFAULT, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW +}; + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns the character attribute for the given color. +WORD GetColorAttribute(GTestColor color) { + switch (color) { + case COLOR_RED: return FOREGROUND_RED; + case COLOR_GREEN: return FOREGROUND_GREEN; + case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; + default: return 0; + } +} + +#else + +// Returns the ANSI color code for the given color. COLOR_DEFAULT is +// an invalid input. +const char* GetAnsiColorCode(GTestColor color) { + switch (color) { + case COLOR_RED: return "1"; + case COLOR_GREEN: return "2"; + case COLOR_YELLOW: return "3"; + default: return NULL; + }; +} + +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns true iff Google Test should use colors in the output. +bool ShouldUseColor(bool stdout_is_tty) { + const char* const gtest_color = GTEST_FLAG(color).c_str(); + + if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { +#if GTEST_OS_WINDOWS + // On Windows the TERM variable is usually not set, but the + // console there does support colors. + return stdout_is_tty; +#else + // On non-Windows platforms, we rely on the TERM variable. + const char* const term = posix::GetEnv("TERM"); + const bool term_supports_color = + String::CStringEquals(term, "xterm") || + String::CStringEquals(term, "xterm-color") || + String::CStringEquals(term, "xterm-256color") || + String::CStringEquals(term, "screen") || + String::CStringEquals(term, "linux") || + String::CStringEquals(term, "cygwin"); + return stdout_is_tty && term_supports_color; +#endif // GTEST_OS_WINDOWS + } + + return String::CaseInsensitiveCStringEquals(gtest_color, "yes") || + String::CaseInsensitiveCStringEquals(gtest_color, "true") || + String::CaseInsensitiveCStringEquals(gtest_color, "t") || + String::CStringEquals(gtest_color, "1"); + // We take "yes", "true", "t", and "1" as meaning "yes". If the + // value is neither one of these nor "auto", we treat it as "no" to + // be conservative. +} + +// Helpers for printing colored strings to stdout. Note that on Windows, we +// cannot simply emit special characters and have the terminal change colors. +// This routine must actually emit the characters rather than return a string +// that would be colored when printed, as can be done on Linux. +void ColoredPrintf(GTestColor color, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + const bool use_color = false; +#else + static const bool in_color_mode = + ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); + const bool use_color = in_color_mode && (color != COLOR_DEFAULT); +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + // The '!= 0' comparison is necessary to satisfy MSVC 7.1. + + if (!use_color) { + vprintf(fmt, args); + va_end(args); + return; + } + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + + // Gets the current text color. + CONSOLE_SCREEN_BUFFER_INFO buffer_info; + GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); + const WORD old_color_attrs = buffer_info.wAttributes; + + // We need to flush the stream buffers into the console before each + // SetConsoleTextAttribute call lest it affect the text that is already + // printed but has not yet reached the console. + fflush(stdout); + SetConsoleTextAttribute(stdout_handle, + GetColorAttribute(color) | FOREGROUND_INTENSITY); + vprintf(fmt, args); + + fflush(stdout); + // Restores the text color. + SetConsoleTextAttribute(stdout_handle, old_color_attrs); +#else + printf("\033[0;3%sm", GetAnsiColorCode(color)); + vprintf(fmt, args); + printf("\033[m"); // Resets the terminal to default. +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + va_end(args); +} + +void PrintFullTestCommentIfPresent(const TestInfo& test_info) { + const char* const type_param = test_info.type_param(); + const char* const value_param = test_info.value_param(); + + if (type_param != NULL || value_param != NULL) { + printf(", where "); + if (type_param != NULL) { + printf("TypeParam = %s", type_param); + if (value_param != NULL) + printf(" and "); + } + if (value_param != NULL) { + printf("GetParam() = %s", value_param); + } + } +} + +// This class implements the TestEventListener interface. +// +// Class PrettyUnitTestResultPrinter is copyable. +class PrettyUnitTestResultPrinter : public TestEventListener { + public: + PrettyUnitTestResultPrinter() {} + static void PrintTestName(const char * test_case, const char * test) { + printf("%s.%s", test_case, test); + } + + // The following methods override what's in the TestEventListener class. + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + + private: + static void PrintFailedTests(const UnitTest& unit_test); + + internal::String test_case_name_; +}; + + // Fired before each iteration of tests starts. +void PrettyUnitTestResultPrinter::OnTestIterationStart( + const UnitTest& unit_test, int iteration) { + if (GTEST_FLAG(repeat) != 1) + printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); + + const char* const filter = GTEST_FLAG(filter).c_str(); + + // Prints the filter if it's not *. This reminds the user that some + // tests may be skipped. + if (!internal::String::CStringEquals(filter, kUniversalFilter)) { + ColoredPrintf(COLOR_YELLOW, + "Note: %s filter = %s\n", GTEST_NAME_, filter); + } + + if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { + const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1); + ColoredPrintf(COLOR_YELLOW, + "Note: This is test shard %d of %s.\n", + static_cast(shard_index) + 1, + internal::posix::GetEnv(kTestTotalShards)); + } + + if (GTEST_FLAG(shuffle)) { + ColoredPrintf(COLOR_YELLOW, + "Note: Randomizing tests' orders with a seed of %d .\n", + unit_test.random_seed()); + } + + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("Running %s from %s.\n", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment set-up.\n"); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { + test_case_name_ = test_case.name(); + const internal::String counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s", counts.c_str(), test_case_name_.c_str()); + if (test_case.type_param() == NULL) { + printf("\n"); + } else { + printf(", where TypeParam = %s\n", test_case.type_param()); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { + ColoredPrintf(COLOR_GREEN, "[ RUN ] "); + PrintTestName(test_case_name_.c_str(), test_info.name()); + printf("\n"); + fflush(stdout); +} + +// Called after an assertion failure. +void PrettyUnitTestResultPrinter::OnTestPartResult( + const TestPartResult& result) { + // If the test part succeeded, we don't need to do anything. + if (result.type() == TestPartResult::kSuccess) + return; + + // Print failure message from the assertion (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { + if (test_info.result()->Passed()) { + ColoredPrintf(COLOR_GREEN, "[ OK ] "); + } else { + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + } + PrintTestName(test_case_name_.c_str(), test_info.name()); + if (test_info.result()->Failed()) + PrintFullTestCommentIfPresent(test_info); + + if (GTEST_FLAG(print_time)) { + printf(" (%s ms)\n", internal::StreamableToString( + test_info.result()->elapsed_time()).c_str()); + } else { + printf("\n"); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { + if (!GTEST_FLAG(print_time)) return; + + test_case_name_ = test_case.name(); + const internal::String counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s (%s ms total)\n\n", + counts.c_str(), test_case_name_.c_str(), + internal::StreamableToString(test_case.elapsed_time()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment tear-down\n"); + fflush(stdout); +} + +// Internal helper for printing the list of failed tests. +void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { + const int failed_test_count = unit_test.failed_test_count(); + if (failed_test_count == 0) { + return; + } + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + const TestCase& test_case = *unit_test.GetTestCase(i); + if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { + continue; + } + for (int j = 0; j < test_case.total_test_count(); ++j) { + const TestInfo& test_info = *test_case.GetTestInfo(j); + if (!test_info.should_run() || test_info.result()->Passed()) { + continue; + } + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s.%s", test_case.name(), test_info.name()); + PrintFullTestCommentIfPresent(test_info); + printf("\n"); + } + } +} + +void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("%s from %s ran.", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + if (GTEST_FLAG(print_time)) { + printf(" (%s ms total)", + internal::StreamableToString(unit_test.elapsed_time()).c_str()); + } + printf("\n"); + ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); + + int num_failures = unit_test.failed_test_count(); + if (!unit_test.Passed()) { + const int failed_test_count = unit_test.failed_test_count(); + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); + PrintFailedTests(unit_test); + printf("\n%2d FAILED %s\n", num_failures, + num_failures == 1 ? "TEST" : "TESTS"); + } + + int num_disabled = unit_test.disabled_test_count(); + if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { + if (!num_failures) { + printf("\n"); // Add a spacer if no FAILURE banner is displayed. + } + ColoredPrintf(COLOR_YELLOW, + " YOU HAVE %d DISABLED %s\n\n", + num_disabled, + num_disabled == 1 ? "TEST" : "TESTS"); + } + // Ensure that Google Test output is printed before, e.g., heapchecker output. + fflush(stdout); +} + +// End PrettyUnitTestResultPrinter + +// class TestEventRepeater +// +// This class forwards events to other event listeners. +class TestEventRepeater : public TestEventListener { + public: + TestEventRepeater() : forwarding_enabled_(true) {} + virtual ~TestEventRepeater(); + void Append(TestEventListener *listener); + TestEventListener* Release(TestEventListener* listener); + + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled() const { return forwarding_enabled_; } + void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } + + virtual void OnTestProgramStart(const UnitTest& unit_test); + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& unit_test); + + private: + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled_; + // The list of listeners that receive events. + std::vector listeners_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); +}; + +TestEventRepeater::~TestEventRepeater() { + ForEach(listeners_, Delete); +} + +void TestEventRepeater::Append(TestEventListener *listener) { + listeners_.push_back(listener); +} + +// TODO(vladl@google.com): Factor the search functionality into Vector::Find. +TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { + for (size_t i = 0; i < listeners_.size(); ++i) { + if (listeners_[i] == listener) { + listeners_.erase(listeners_.begin() + i); + return listener; + } + } + + return NULL; +} + +// Since most methods are very similar, use macros to reduce boilerplate. +// This defines a member that forwards the call to all listeners. +#define GTEST_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = 0; i < listeners_.size(); i++) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} +// This defines a member that forwards the call to all listeners in reverse +// order. +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} + +GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) +GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) +GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) +GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) +GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) +GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) +GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) +GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) + +#undef GTEST_REPEATER_METHOD_ +#undef GTEST_REVERSE_REPEATER_METHOD_ + +void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (size_t i = 0; i < listeners_.size(); i++) { + listeners_[i]->OnTestIterationStart(unit_test, iteration); + } + } +} + +void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { + listeners_[i]->OnTestIterationEnd(unit_test, iteration); + } + } +} + +// End TestEventRepeater + +// This class generates an XML output file. +class XmlUnitTestResultPrinter : public EmptyTestEventListener { + public: + explicit XmlUnitTestResultPrinter(const char* output_file); + + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + + private: + // Is c a whitespace character that is normalized to a space character + // when it appears in an XML attribute value? + static bool IsNormalizableWhitespace(char c) { + return c == 0x9 || c == 0xA || c == 0xD; + } + + // May c appear in a well-formed XML document? + static bool IsValidXmlCharacter(char c) { + return IsNormalizableWhitespace(c) || c >= 0x20; + } + + // Returns an XML-escaped copy of the input string str. If + // is_attribute is true, the text is meant to appear as an attribute + // value, and normalizable whitespace is preserved by replacing it + // with character references. + static String EscapeXml(const char* str, bool is_attribute); + + // Returns the given string with all characters invalid in XML removed. + static string RemoveInvalidXmlCharacters(const string& str); + + // Convenience wrapper around EscapeXml when str is an attribute value. + static String EscapeXmlAttribute(const char* str) { + return EscapeXml(str, true); + } + + // Convenience wrapper around EscapeXml when str is not an attribute value. + static String EscapeXmlText(const char* str) { return EscapeXml(str, false); } + + // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. + static void OutputXmlCDataSection(::std::ostream* stream, const char* data); + + // Streams an XML representation of a TestInfo object. + static void OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info); + + // Prints an XML representation of a TestCase object + static void PrintXmlTestCase(FILE* out, const TestCase& test_case); + + // Prints an XML summary of unit_test to output stream out. + static void PrintXmlUnitTest(FILE* out, const UnitTest& unit_test); + + // Produces a string representing the test properties in a result as space + // delimited XML attributes based on the property key="value" pairs. + // When the String is not empty, it includes a space at the beginning, + // to delimit this attribute from prior attributes. + static String TestPropertiesAsXmlAttributes(const TestResult& result); + + // The output file. + const String output_file_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); +}; + +// Creates a new XmlUnitTestResultPrinter. +XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) + : output_file_(output_file) { + if (output_file_.c_str() == NULL || output_file_.empty()) { + fprintf(stderr, "XML output file may not be null\n"); + fflush(stderr); + exit(EXIT_FAILURE); + } +} + +// Called after the unit test ends. +void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + FILE* xmlout = NULL; + FilePath output_file(output_file_); + FilePath output_dir(output_file.RemoveFileName()); + + if (output_dir.CreateDirectoriesRecursively()) { + xmlout = posix::FOpen(output_file_.c_str(), "w"); + } + if (xmlout == NULL) { + // TODO(wan): report the reason of the failure. + // + // We don't do it for now as: + // + // 1. There is no urgent need for it. + // 2. It's a bit involved to make the errno variable thread-safe on + // all three operating systems (Linux, Windows, and Mac OS). + // 3. To interpret the meaning of errno in a thread-safe way, + // we need the strerror_r() function, which is not available on + // Windows. + fprintf(stderr, + "Unable to open file \"%s\"\n", + output_file_.c_str()); + fflush(stderr); + exit(EXIT_FAILURE); + } + PrintXmlUnitTest(xmlout, unit_test); + fclose(xmlout); +} + +// Returns an XML-escaped copy of the input string str. If is_attribute +// is true, the text is meant to appear as an attribute value, and +// normalizable whitespace is preserved by replacing it with character +// references. +// +// Invalid XML characters in str, if any, are stripped from the output. +// It is expected that most, if not all, of the text processed by this +// module will consist of ordinary English text. +// If this module is ever modified to produce version 1.1 XML output, +// most invalid characters can be retained using character references. +// TODO(wan): It might be nice to have a minimally invasive, human-readable +// escaping scheme for invalid characters, rather than dropping them. +String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) { + Message m; + + if (str != NULL) { + for (const char* src = str; *src; ++src) { + switch (*src) { + case '<': + m << "<"; + break; + case '>': + m << ">"; + break; + case '&': + m << "&"; + break; + case '\'': + if (is_attribute) + m << "'"; + else + m << '\''; + break; + case '"': + if (is_attribute) + m << """; + else + m << '"'; + break; + default: + if (IsValidXmlCharacter(*src)) { + if (is_attribute && IsNormalizableWhitespace(*src)) + m << String::Format("&#x%02X;", unsigned(*src)); + else + m << *src; + } + break; + } + } + } + + return m.GetString(); +} + +// Returns the given string with all characters invalid in XML removed. +// Currently invalid characters are dropped from the string. An +// alternative is to replace them with certain characters such as . or ?. +string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const string& str) { + string output; + output.reserve(str.size()); + for (string::const_iterator it = str.begin(); it != str.end(); ++it) + if (IsValidXmlCharacter(*it)) + output.push_back(*it); + + return output; +} + +// The following routines generate an XML representation of a UnitTest +// object. +// +// This is how Google Test concepts map to the DTD: +// +// <-- corresponds to a UnitTest object +// <-- corresponds to a TestCase object +// <-- corresponds to a TestInfo object +// ... +// ... +// ... +// <-- individual assertion failures +// +// +// + +// Formats the given time in milliseconds as seconds. +std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { + ::std::stringstream ss; + ss << ms/1000.0; + return ss.str(); +} + +// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. +void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, + const char* data) { + const char* segment = data; + *stream << ""); + if (next_segment != NULL) { + stream->write( + segment, static_cast(next_segment - segment)); + *stream << "]]>]]>"); + } else { + *stream << segment; + break; + } + } + *stream << "]]>"; +} + +// Prints an XML representation of a TestInfo object. +// TODO(wan): There is also value in printing properties with the plain printer. +void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info) { + const TestResult& result = *test_info.result(); + *stream << " \n"; + *stream << " "; + const string location = internal::FormatCompilerIndependentFileLocation( + part.file_name(), part.line_number()); + const string message = location + "\n" + part.message(); + OutputXmlCDataSection(stream, + RemoveInvalidXmlCharacters(message).c_str()); + *stream << "\n"; + } + } + + if (failures == 0) + *stream << " />\n"; + else + *stream << " \n"; +} + +// Prints an XML representation of a TestCase object +void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out, + const TestCase& test_case) { + fprintf(out, + " \n", + FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str()); + for (int i = 0; i < test_case.total_test_count(); ++i) { + ::std::stringstream stream; + OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i)); + fprintf(out, "%s", StringStreamToString(&stream).c_str()); + } + fprintf(out, " \n"); +} + +// Prints an XML summary of unit_test to output stream out. +void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out, + const UnitTest& unit_test) { + fprintf(out, "\n"); + fprintf(out, + "\n"); + for (int i = 0; i < unit_test.total_test_case_count(); ++i) + PrintXmlTestCase(out, *unit_test.GetTestCase(i)); + fprintf(out, "\n"); +} + +// Produces a string representing the test properties in a result as space +// delimited XML attributes based on the property key="value" pairs. +String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( + const TestResult& result) { + Message attributes; + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); + attributes << " " << property.key() << "=" + << "\"" << EscapeXmlAttribute(property.value()) << "\""; + } + return attributes.GetString(); +} + +// End XmlUnitTestResultPrinter + +#if GTEST_CAN_STREAM_RESULTS_ + +// Streams test results to the given port on the given host machine. +class StreamingListener : public EmptyTestEventListener { + public: + // Escapes '=', '&', '%', and '\n' characters in str as "%xx". + static string UrlEncode(const char* str); + + StreamingListener(const string& host, const string& port) + : sockfd_(-1), host_name_(host), port_num_(port) { + MakeConnection(); + Send("gtest_streaming_protocol_version=1.0\n"); + } + + virtual ~StreamingListener() { + if (sockfd_ != -1) + CloseConnection(); + } + + void OnTestProgramStart(const UnitTest& /* unit_test */) { + Send("event=TestProgramStart\n"); + } + + void OnTestProgramEnd(const UnitTest& unit_test) { + // Note that Google Test current only report elapsed time for each + // test iteration, not for the entire test program. + Send(String::Format("event=TestProgramEnd&passed=%d\n", + unit_test.Passed())); + + // Notify the streaming server to stop. + CloseConnection(); + } + + void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { + Send(String::Format("event=TestIterationStart&iteration=%d\n", + iteration)); + } + + void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { + Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n", + unit_test.Passed(), + StreamableToString(unit_test.elapsed_time()).c_str())); + } + + void OnTestCaseStart(const TestCase& test_case) { + Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name())); + } + + void OnTestCaseEnd(const TestCase& test_case) { + Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n", + test_case.Passed(), + StreamableToString(test_case.elapsed_time()).c_str())); + } + + void OnTestStart(const TestInfo& test_info) { + Send(String::Format("event=TestStart&name=%s\n", test_info.name())); + } + + void OnTestEnd(const TestInfo& test_info) { + Send(String::Format( + "event=TestEnd&passed=%d&elapsed_time=%sms\n", + (test_info.result())->Passed(), + StreamableToString((test_info.result())->elapsed_time()).c_str())); + } + + void OnTestPartResult(const TestPartResult& test_part_result) { + const char* file_name = test_part_result.file_name(); + if (file_name == NULL) + file_name = ""; + Send(String::Format("event=TestPartResult&file=%s&line=%d&message=", + UrlEncode(file_name).c_str(), + test_part_result.line_number())); + Send(UrlEncode(test_part_result.message()) + "\n"); + } + + private: + // Creates a client socket and connects to the server. + void MakeConnection(); + + // Closes the socket. + void CloseConnection() { + GTEST_CHECK_(sockfd_ != -1) + << "CloseConnection() can be called only when there is a connection."; + + close(sockfd_); + sockfd_ = -1; + } + + // Sends a string to the socket. + void Send(const string& message) { + GTEST_CHECK_(sockfd_ != -1) + << "Send() can be called only when there is a connection."; + + const int len = static_cast(message.length()); + if (write(sockfd_, message.c_str(), len) != len) { + GTEST_LOG_(WARNING) + << "stream_result_to: failed to stream to " + << host_name_ << ":" << port_num_; + } + } + + int sockfd_; // socket file descriptor + const string host_name_; + const string port_num_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); +}; // class StreamingListener + +// Checks if str contains '=', '&', '%' or '\n' characters. If yes, +// replaces them by "%xx" where xx is their hexadecimal value. For +// example, replaces "=" with "%3D". This algorithm is O(strlen(str)) +// in both time and space -- important as the input str may contain an +// arbitrarily long test failure message and stack trace. +string StreamingListener::UrlEncode(const char* str) { + string result; + result.reserve(strlen(str) + 1); + for (char ch = *str; ch != '\0'; ch = *++str) { + switch (ch) { + case '%': + case '=': + case '&': + case '\n': + result.append(String::Format("%%%02x", static_cast(ch))); + break; + default: + result.push_back(ch); + break; + } + } + return result; +} + +void StreamingListener::MakeConnection() { + GTEST_CHECK_(sockfd_ == -1) + << "MakeConnection() can't be called when there is already a connection."; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. + hints.ai_socktype = SOCK_STREAM; + addrinfo* servinfo = NULL; + + // Use the getaddrinfo() to get a linked list of IP addresses for + // the given host name. + const int error_num = getaddrinfo( + host_name_.c_str(), port_num_.c_str(), &hints, &servinfo); + if (error_num != 0) { + GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: " + << gai_strerror(error_num); + } + + // Loop through all the results and connect to the first we can. + for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL; + cur_addr = cur_addr->ai_next) { + sockfd_ = socket( + cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); + if (sockfd_ != -1) { + // Connect the client socket to the server socket. + if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) { + close(sockfd_); + sockfd_ = -1; + } + } + } + + freeaddrinfo(servinfo); // all done with this structure + + if (sockfd_ == -1) { + GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to " + << host_name_ << ":" << port_num_; + } +} + +// End of class Streaming Listener +#endif // GTEST_CAN_STREAM_RESULTS__ + +// Class ScopedTrace + +// Pushes the given source file location and message onto a per-thread +// trace stack maintained by Google Test. +// L < UnitTest::mutex_ +ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) { + TraceInfo trace; + trace.file = file; + trace.line = line; + trace.message = message.GetString(); + + UnitTest::GetInstance()->PushGTestTrace(trace); +} + +// Pops the info pushed by the c'tor. +// L < UnitTest::mutex_ +ScopedTrace::~ScopedTrace() { + UnitTest::GetInstance()->PopGTestTrace(); +} + + +// class OsStackTraceGetter + +// Returns the current OS stack trace as a String. Parameters: +// +// max_depth - the maximum number of stack frames to be included +// in the trace. +// skip_count - the number of top frames to be skipped; doesn't count +// against max_depth. +// +// L < mutex_ +// We use "L < mutex_" to denote that the function may acquire mutex_. +String OsStackTraceGetter::CurrentStackTrace(int, int) { + return String(""); +} + +// L < mutex_ +void OsStackTraceGetter::UponLeavingGTest() { +} + +const char* const +OsStackTraceGetter::kElidedFramesMarker = + "... " GTEST_NAME_ " internal frames ..."; + +} // namespace internal + +// class TestEventListeners + +TestEventListeners::TestEventListeners() + : repeater_(new internal::TestEventRepeater()), + default_result_printer_(NULL), + default_xml_generator_(NULL) { +} + +TestEventListeners::~TestEventListeners() { delete repeater_; } + +// Returns the standard listener responsible for the default console +// output. Can be removed from the listeners list to shut down default +// console output. Note that removing this object from the listener list +// with Release transfers its ownership to the user. +void TestEventListeners::Append(TestEventListener* listener) { + repeater_->Append(listener); +} + +// Removes the given event listener from the list and returns it. It then +// becomes the caller's responsibility to delete the listener. Returns +// NULL if the listener is not found in the list. +TestEventListener* TestEventListeners::Release(TestEventListener* listener) { + if (listener == default_result_printer_) + default_result_printer_ = NULL; + else if (listener == default_xml_generator_) + default_xml_generator_ = NULL; + return repeater_->Release(listener); +} + +// Returns repeater that broadcasts the TestEventListener events to all +// subscribers. +TestEventListener* TestEventListeners::repeater() { return repeater_; } + +// Sets the default_result_printer attribute to the provided listener. +// The listener is also added to the listener list and previous +// default_result_printer is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { + if (default_result_printer_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_result_printer_); + default_result_printer_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Sets the default_xml_generator attribute to the provided listener. The +// listener is also added to the listener list and previous +// default_xml_generator is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { + if (default_xml_generator_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_xml_generator_); + default_xml_generator_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Controls whether events will be forwarded by the repeater to the +// listeners in the list. +bool TestEventListeners::EventForwardingEnabled() const { + return repeater_->forwarding_enabled(); +} + +void TestEventListeners::SuppressEventForwarding() { + repeater_->set_forwarding_enabled(false); +} + +// class UnitTest + +// Gets the singleton UnitTest object. The first time this method is +// called, a UnitTest object is constructed and returned. Consecutive +// calls will return the same object. +// +// We don't protect this under mutex_ as a user is not supposed to +// call this before main() starts, from which point on the return +// value will never change. +UnitTest * UnitTest::GetInstance() { + // When compiled with MSVC 7.1 in optimized mode, destroying the + // UnitTest object upon exiting the program messes up the exit code, + // causing successful tests to appear failed. We have to use a + // different implementation in this case to bypass the compiler bug. + // This implementation makes the compiler happy, at the cost of + // leaking the UnitTest object. + + // CodeGear C++Builder insists on a public destructor for the + // default implementation. Use this implementation to keep good OO + // design with private destructor. + +#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) + static UnitTest* const instance = new UnitTest; + return instance; +#else + static UnitTest instance; + return &instance; +#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +} + +// Gets the number of successful test cases. +int UnitTest::successful_test_case_count() const { + return impl()->successful_test_case_count(); +} + +// Gets the number of failed test cases. +int UnitTest::failed_test_case_count() const { + return impl()->failed_test_case_count(); +} + +// Gets the number of all test cases. +int UnitTest::total_test_case_count() const { + return impl()->total_test_case_count(); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTest::test_case_to_run_count() const { + return impl()->test_case_to_run_count(); +} + +// Gets the number of successful tests. +int UnitTest::successful_test_count() const { + return impl()->successful_test_count(); +} + +// Gets the number of failed tests. +int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } + +// Gets the number of disabled tests. +int UnitTest::disabled_test_count() const { + return impl()->disabled_test_count(); +} + +// Gets the number of all tests. +int UnitTest::total_test_count() const { return impl()->total_test_count(); } + +// Gets the number of tests that should run. +int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } + +// Gets the elapsed time, in milliseconds. +internal::TimeInMillis UnitTest::elapsed_time() const { + return impl()->elapsed_time(); +} + +// Returns true iff the unit test passed (i.e. all test cases passed). +bool UnitTest::Passed() const { return impl()->Passed(); } + +// Returns true iff the unit test failed (i.e. some test case failed +// or something outside of all tests failed). +bool UnitTest::Failed() const { return impl()->Failed(); } + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +const TestCase* UnitTest::GetTestCase(int i) const { + return impl()->GetTestCase(i); +} + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +TestCase* UnitTest::GetMutableTestCase(int i) { + return impl()->GetMutableTestCase(i); +} + +// Returns the list of event listeners that can be used to track events +// inside Google Test. +TestEventListeners& UnitTest::listeners() { + return *impl()->listeners(); +} + +// Registers and returns a global test environment. When a test +// program is run, all global test environments will be set-up in the +// order they were registered. After all tests in the program have +// finished, all global test environments will be torn-down in the +// *reverse* order they were registered. +// +// The UnitTest object takes ownership of the given environment. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +Environment* UnitTest::AddEnvironment(Environment* env) { + if (env == NULL) { + return NULL; + } + + impl_->environments().push_back(env); + return env; +} + +// Adds a TestPartResult to the current TestResult object. All Google Test +// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call +// this to report their results. The user code should use the +// assertion macros instead of calling this directly. +// L < mutex_ +void UnitTest::AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const internal::String& message, + const internal::String& os_stack_trace) { + Message msg; + msg << message; + + internal::MutexLock lock(&mutex_); + if (impl_->gtest_trace_stack().size() > 0) { + msg << "\n" << GTEST_NAME_ << " trace:"; + + for (int i = static_cast(impl_->gtest_trace_stack().size()); + i > 0; --i) { + const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; + msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) + << " " << trace.message; + } + } + + if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) { + msg << internal::kStackTraceMarker << os_stack_trace; + } + + const TestPartResult result = + TestPartResult(result_type, file_name, line_number, + msg.GetString().c_str()); + impl_->GetTestPartResultReporterForCurrentThread()-> + ReportTestPartResult(result); + + if (result_type != TestPartResult::kSuccess) { + // gtest_break_on_failure takes precedence over + // gtest_throw_on_failure. This allows a user to set the latter + // in the code (perhaps in order to use Google Test assertions + // with another testing framework) and specify the former on the + // command line for debugging. + if (GTEST_FLAG(break_on_failure)) { +#if GTEST_OS_WINDOWS + // Using DebugBreak on Windows allows gtest to still break into a debugger + // when a failure happens and both the --gtest_break_on_failure and + // the --gtest_catch_exceptions flags are specified. + DebugBreak(); +#else + // Dereference NULL through a volatile pointer to prevent the compiler + // from removing. We use this rather than abort() or __builtin_trap() for + // portability: Symbian doesn't implement abort() well, and some debuggers + // don't correctly trap abort(). + *static_cast(NULL) = 1; +#endif // GTEST_OS_WINDOWS + } else if (GTEST_FLAG(throw_on_failure)) { +#if GTEST_HAS_EXCEPTIONS + throw GoogleTestFailureException(result); +#else + // We cannot call abort() as it generates a pop-up in debug mode + // that cannot be suppressed in VC 7.1 or below. + exit(1); +#endif + } + } +} + +// Creates and adds a property to the current TestResult. If a property matching +// the supplied value already exists, updates its value instead. +void UnitTest::RecordPropertyForCurrentTest(const char* key, + const char* value) { + const TestProperty test_property(key, value); + impl_->current_test_result()->RecordProperty(test_property); +} + +// Runs all tests in this UnitTest object and prints the result. +// Returns 0 if successful, or 1 otherwise. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +int UnitTest::Run() { + // Captures the value of GTEST_FLAG(catch_exceptions). This value will be + // used for the duration of the program. + impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); + +#if GTEST_HAS_SEH + const bool in_death_test_child_process = + internal::GTEST_FLAG(internal_run_death_test).length() > 0; + + // Either the user wants Google Test to catch exceptions thrown by the + // tests or this is executing in the context of death test child + // process. In either case the user does not want to see pop-up dialogs + // about crashes - they are expected. + if (impl()->catch_exceptions() || in_death_test_child_process) { + +# if !GTEST_OS_WINDOWS_MOBILE + // SetErrorMode doesn't exist on CE. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); +# endif // !GTEST_OS_WINDOWS_MOBILE + +# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE + // Death test children can be terminated with _abort(). On Windows, + // _abort() can show a dialog with a warning message. This forces the + // abort message to go to stderr instead. + _set_error_mode(_OUT_TO_STDERR); +# endif + +# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program. We need to suppress + // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement + // executed. Google Test will notify the user of any unexpected + // failure via stderr. + // + // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. + // Users of prior VC versions shall suffer the agony and pain of + // clicking through the countless debug dialogs. + // TODO(vladl@google.com): find a way to suppress the abort dialog() in the + // debug mode when compiled with VC 7.1 or lower. + if (!GTEST_FLAG(break_on_failure)) + _set_abort_behavior( + 0x0, // Clear the following flags: + _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. +# endif + + } +#endif // GTEST_HAS_SEH + + return internal::HandleExceptionsInMethodIfSupported( + impl(), + &internal::UnitTestImpl::RunAllTests, + "auxiliary test code (environments or event listeners)") ? 0 : 1; +} + +// Returns the working directory when the first TEST() or TEST_F() was +// executed. +const char* UnitTest::original_working_dir() const { + return impl_->original_working_dir_.c_str(); +} + +// Returns the TestCase object for the test that's currently running, +// or NULL if no test is running. +// L < mutex_ +const TestCase* UnitTest::current_test_case() const { + internal::MutexLock lock(&mutex_); + return impl_->current_test_case(); +} + +// Returns the TestInfo object for the test that's currently running, +// or NULL if no test is running. +// L < mutex_ +const TestInfo* UnitTest::current_test_info() const { + internal::MutexLock lock(&mutex_); + return impl_->current_test_info(); +} + +// Returns the random seed used at the start of the current test run. +int UnitTest::random_seed() const { return impl_->random_seed(); } + +#if GTEST_HAS_PARAM_TEST +// Returns ParameterizedTestCaseRegistry object used to keep track of +// value-parameterized tests and instantiate and register them. +// L < mutex_ +internal::ParameterizedTestCaseRegistry& + UnitTest::parameterized_test_registry() { + return impl_->parameterized_test_registry(); +} +#endif // GTEST_HAS_PARAM_TEST + +// Creates an empty UnitTest. +UnitTest::UnitTest() { + impl_ = new internal::UnitTestImpl(this); +} + +// Destructor of UnitTest. +UnitTest::~UnitTest() { + delete impl_; +} + +// Pushes a trace defined by SCOPED_TRACE() on to the per-thread +// Google Test trace stack. +// L < mutex_ +void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().push_back(trace); +} + +// Pops a trace from the per-thread Google Test trace stack. +// L < mutex_ +void UnitTest::PopGTestTrace() { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().pop_back(); +} + +namespace internal { + +UnitTestImpl::UnitTestImpl(UnitTest* parent) + : parent_(parent), +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4355) // Temporarily disables warning 4355 + // (using this in initializer). + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +# pragma warning(pop) // Restores the warning state again. +#else + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +#endif // _MSC_VER + global_test_part_result_repoter_( + &default_global_test_part_result_reporter_), + per_thread_test_part_result_reporter_( + &default_per_thread_test_part_result_reporter_), +#if GTEST_HAS_PARAM_TEST + parameterized_test_registry_(), + parameterized_tests_registered_(false), +#endif // GTEST_HAS_PARAM_TEST + last_death_test_case_(-1), + current_test_case_(NULL), + current_test_info_(NULL), + ad_hoc_test_result_(), + os_stack_trace_getter_(NULL), + post_flag_parse_init_performed_(false), + random_seed_(0), // Will be overridden by the flag before first use. + random_(0), // Will be reseeded before first use. + elapsed_time_(0), +#if GTEST_HAS_DEATH_TEST + internal_run_death_test_flag_(NULL), + death_test_factory_(new DefaultDeathTestFactory), +#endif + // Will be overridden by the flag before first use. + catch_exceptions_(false) { + listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); +} + +UnitTestImpl::~UnitTestImpl() { + // Deletes every TestCase. + ForEach(test_cases_, internal::Delete); + + // Deletes every Environment. + ForEach(environments_, internal::Delete); + + delete os_stack_trace_getter_; +} + +#if GTEST_HAS_DEATH_TEST +// Disables event forwarding if the control is currently in a death test +// subprocess. Must not be called before InitGoogleTest. +void UnitTestImpl::SuppressTestEventsIfInSubprocess() { + if (internal_run_death_test_flag_.get() != NULL) + listeners()->SuppressEventForwarding(); +} +#endif // GTEST_HAS_DEATH_TEST + +// Initializes event listeners performing XML output as specified by +// UnitTestOptions. Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureXmlOutput() { + const String& output_format = UnitTestOptions::GetOutputFormat(); + if (output_format == "xml") { + listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); + } else if (output_format != "") { + printf("WARNING: unrecognized output format \"%s\" ignored.\n", + output_format.c_str()); + fflush(stdout); + } +} + +#if GTEST_CAN_STREAM_RESULTS_ +// Initializes event listeners for streaming test results in String form. +// Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureStreamingOutput() { + const string& target = GTEST_FLAG(stream_result_to); + if (!target.empty()) { + const size_t pos = target.find(':'); + if (pos != string::npos) { + listeners()->Append(new StreamingListener(target.substr(0, pos), + target.substr(pos+1))); + } else { + printf("WARNING: unrecognized streaming target \"%s\" ignored.\n", + target.c_str()); + fflush(stdout); + } + } +} +#endif // GTEST_CAN_STREAM_RESULTS_ + +// Performs initialization dependent upon flag values obtained in +// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to +// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest +// this function is also called from RunAllTests. Since this function can be +// called more than once, it has to be idempotent. +void UnitTestImpl::PostFlagParsingInit() { + // Ensures that this function does not execute more than once. + if (!post_flag_parse_init_performed_) { + post_flag_parse_init_performed_ = true; + +#if GTEST_HAS_DEATH_TEST + InitDeathTestSubprocessControlInfo(); + SuppressTestEventsIfInSubprocess(); +#endif // GTEST_HAS_DEATH_TEST + + // Registers parameterized tests. This makes parameterized tests + // available to the UnitTest reflection API without running + // RUN_ALL_TESTS. + RegisterParameterizedTests(); + + // Configures listeners for XML output. This makes it possible for users + // to shut down the default XML output before invoking RUN_ALL_TESTS. + ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Configures listeners for streaming test results to the specified server. + ConfigureStreamingOutput(); +#endif // GTEST_CAN_STREAM_RESULTS_ + } +} + +// A predicate that checks the name of a TestCase against a known +// value. +// +// This is used for implementation of the UnitTest class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestCaseNameIs is copyable. +class TestCaseNameIs { + public: + // Constructor. + explicit TestCaseNameIs(const String& name) + : name_(name) {} + + // Returns true iff the name of test_case matches name_. + bool operator()(const TestCase* test_case) const { + return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0; + } + + private: + String name_; +}; + +// Finds and returns a TestCase with the given name. If one doesn't +// exist, creates one and returns it. It's the CALLER'S +// RESPONSIBILITY to ensure that this function is only called WHEN THE +// TESTS ARE NOT SHUFFLED. +// +// Arguments: +// +// test_case_name: name of the test case +// type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) { + // Can we find a TestCase with the given name? + const std::vector::const_iterator test_case = + std::find_if(test_cases_.begin(), test_cases_.end(), + TestCaseNameIs(test_case_name)); + + if (test_case != test_cases_.end()) + return *test_case; + + // No. Let's create one. + TestCase* const new_test_case = + new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc); + + // Is this a death test case? + if (internal::UnitTestOptions::MatchesFilter(String(test_case_name), + kDeathTestCaseFilter)) { + // Yes. Inserts the test case after the last death test case + // defined so far. This only works when the test cases haven't + // been shuffled. Otherwise we may end up running a death test + // after a non-death test. + ++last_death_test_case_; + test_cases_.insert(test_cases_.begin() + last_death_test_case_, + new_test_case); + } else { + // No. Appends to the end of the list. + test_cases_.push_back(new_test_case); + } + + test_case_indices_.push_back(static_cast(test_case_indices_.size())); + return new_test_case; +} + +// Helpers for setting up / tearing down the given environment. They +// are for use in the ForEach() function. +static void SetUpEnvironment(Environment* env) { env->SetUp(); } +static void TearDownEnvironment(Environment* env) { env->TearDown(); } + +// Runs all tests in this UnitTest object, prints the result, and +// returns true if all tests are successful. If any exception is +// thrown during a test, the test is considered to be failed, but the +// rest of the tests will still be run. +// +// When parameterized tests are enabled, it expands and registers +// parameterized tests first in RegisterParameterizedTests(). +// All other functions called from RunAllTests() may safely assume that +// parameterized tests are ready to be counted and run. +bool UnitTestImpl::RunAllTests() { + // Makes sure InitGoogleTest() was called. + if (!GTestIsInitialized()) { + printf("%s", + "\nThis test program did NOT call ::testing::InitGoogleTest " + "before calling RUN_ALL_TESTS(). Please fix it.\n"); + return false; + } + + // Do not run any test if the --help flag was specified. + if (g_help_flag) + return true; + + // Repeats the call to the post-flag parsing initialization in case the + // user didn't call InitGoogleTest. + PostFlagParsingInit(); + + // Even if sharding is not on, test runners may want to use the + // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding + // protocol. + internal::WriteToShardStatusFileIfNeeded(); + + // True iff we are in a subprocess for running a thread-safe-style + // death test. + bool in_subprocess_for_death_test = false; + +#if GTEST_HAS_DEATH_TEST + in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); +#endif // GTEST_HAS_DEATH_TEST + + const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, + in_subprocess_for_death_test); + + // Compares the full test names with the filter to decide which + // tests to run. + const bool has_tests_to_run = FilterTests(should_shard + ? HONOR_SHARDING_PROTOCOL + : IGNORE_SHARDING_PROTOCOL) > 0; + + // Lists the tests and exits if the --gtest_list_tests flag was specified. + if (GTEST_FLAG(list_tests)) { + // This must be called *after* FilterTests() has been called. + ListTestsMatchingFilter(); + return true; + } + + random_seed_ = GTEST_FLAG(shuffle) ? + GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; + + // True iff at least one test has failed. + bool failed = false; + + TestEventListener* repeater = listeners()->repeater(); + + repeater->OnTestProgramStart(*parent_); + + // How many times to repeat the tests? We don't want to repeat them + // when we are inside the subprocess of a death test. + const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); + // Repeats forever if the repeat count is negative. + const bool forever = repeat < 0; + for (int i = 0; forever || i != repeat; i++) { + // We want to preserve failures generated by ad-hoc test + // assertions executed before RUN_ALL_TESTS(). + ClearNonAdHocTestResult(); + + const TimeInMillis start = GetTimeInMillis(); + + // Shuffles test cases and tests if requested. + if (has_tests_to_run && GTEST_FLAG(shuffle)) { + random()->Reseed(random_seed_); + // This should be done before calling OnTestIterationStart(), + // such that a test event listener can see the actual test order + // in the event. + ShuffleTests(); + } + + // Tells the unit test event listeners that the tests are about to start. + repeater->OnTestIterationStart(*parent_, i); + + // Runs each test case if there is at least one test to run. + if (has_tests_to_run) { + // Sets up all environments beforehand. + repeater->OnEnvironmentsSetUpStart(*parent_); + ForEach(environments_, SetUpEnvironment); + repeater->OnEnvironmentsSetUpEnd(*parent_); + + // Runs the tests only if there was no fatal failure during global + // set-up. + if (!Test::HasFatalFailure()) { + for (int test_index = 0; test_index < total_test_case_count(); + test_index++) { + GetMutableTestCase(test_index)->Run(); + } + } + + // Tears down all environments in reverse order afterwards. + repeater->OnEnvironmentsTearDownStart(*parent_); + std::for_each(environments_.rbegin(), environments_.rend(), + TearDownEnvironment); + repeater->OnEnvironmentsTearDownEnd(*parent_); + } + + elapsed_time_ = GetTimeInMillis() - start; + + // Tells the unit test event listener that the tests have just finished. + repeater->OnTestIterationEnd(*parent_, i); + + // Gets the result and clears it. + if (!Passed()) { + failed = true; + } + + // Restores the original test order after the iteration. This + // allows the user to quickly repro a failure that happens in the + // N-th iteration without repeating the first (N - 1) iterations. + // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in + // case the user somehow changes the value of the flag somewhere + // (it's always safe to unshuffle the tests). + UnshuffleTests(); + + if (GTEST_FLAG(shuffle)) { + // Picks a new random seed for each iteration. + random_seed_ = GetNextRandomSeed(random_seed_); + } + } + + repeater->OnTestProgramEnd(*parent_); + + return !failed; +} + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded() { + const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); + if (test_shard_file != NULL) { + FILE* const file = posix::FOpen(test_shard_file, "w"); + if (file == NULL) { + ColoredPrintf(COLOR_RED, + "Could not write to the test shard status file \"%s\" " + "specified by the %s environment variable.\n", + test_shard_file, kTestShardStatusFile); + fflush(stdout); + exit(EXIT_FAILURE); + } + fclose(file); + } +} + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (i.e., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +bool ShouldShard(const char* total_shards_env, + const char* shard_index_env, + bool in_subprocess_for_death_test) { + if (in_subprocess_for_death_test) { + return false; + } + + const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); + const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); + + if (total_shards == -1 && shard_index == -1) { + return false; + } else if (total_shards == -1 && shard_index != -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestShardIndex << " = " << shard_index + << ", but have left " << kTestTotalShards << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (total_shards != -1 && shard_index == -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestTotalShards << " = " << total_shards + << ", but have left " << kTestShardIndex << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (shard_index < 0 || shard_index >= total_shards) { + const Message msg = Message() + << "Invalid environment variables: we require 0 <= " + << kTestShardIndex << " < " << kTestTotalShards + << ", but you have " << kTestShardIndex << "=" << shard_index + << ", " << kTestTotalShards << "=" << total_shards << ".\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } + + return total_shards > 1; +} + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error +// and aborts. +Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { + const char* str_val = posix::GetEnv(var); + if (str_val == NULL) { + return default_val; + } + + Int32 result; + if (!ParseInt32(Message() << "The value of environment variable " << var, + str_val, &result)) { + exit(EXIT_FAILURE); + } + return result; +} + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { + return (test_id % total_shards) == shard_index; +} + +// Compares the name of each test with the user-specified filter to +// decide whether the test should be run, then records the result in +// each TestCase and TestInfo object. +// If shard_tests == true, further filters tests based on sharding +// variables in the environment - see +// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. +// Returns the number of tests that should run. +int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { + const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestTotalShards, -1) : -1; + const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestShardIndex, -1) : -1; + + // num_runnable_tests are the number of tests that will + // run across all shards (i.e., match filter and are not disabled). + // num_selected_tests are the number of tests to be run on + // this shard. + int num_runnable_tests = 0; + int num_selected_tests = 0; + for (size_t i = 0; i < test_cases_.size(); i++) { + TestCase* const test_case = test_cases_[i]; + const String &test_case_name = test_case->name(); + test_case->set_should_run(false); + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + TestInfo* const test_info = test_case->test_info_list()[j]; + const String test_name(test_info->name()); + // A test is disabled if test case name or test name matches + // kDisableTestFilter. + const bool is_disabled = + internal::UnitTestOptions::MatchesFilter(test_case_name, + kDisableTestFilter) || + internal::UnitTestOptions::MatchesFilter(test_name, + kDisableTestFilter); + test_info->is_disabled_ = is_disabled; + + const bool matches_filter = + internal::UnitTestOptions::FilterMatchesTest(test_case_name, + test_name); + test_info->matches_filter_ = matches_filter; + + const bool is_runnable = + (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && + matches_filter; + + const bool is_selected = is_runnable && + (shard_tests == IGNORE_SHARDING_PROTOCOL || + ShouldRunTestOnShard(total_shards, shard_index, + num_runnable_tests)); + + num_runnable_tests += is_runnable; + num_selected_tests += is_selected; + + test_info->should_run_ = is_selected; + test_case->set_should_run(test_case->should_run() || is_selected); + } + } + return num_selected_tests; +} + +// Prints the names of the tests matching the user-specified filter flag. +void UnitTestImpl::ListTestsMatchingFilter() { + for (size_t i = 0; i < test_cases_.size(); i++) { + const TestCase* const test_case = test_cases_[i]; + bool printed_test_case_name = false; + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + const TestInfo* const test_info = + test_case->test_info_list()[j]; + if (test_info->matches_filter_) { + if (!printed_test_case_name) { + printed_test_case_name = true; + printf("%s.\n", test_case->name()); + } + printf(" %s\n", test_info->name()); + } + } + } + fflush(stdout); +} + +// Sets the OS stack trace getter. +// +// Does nothing if the input and the current OS stack trace getter are +// the same; otherwise, deletes the old getter and makes the input the +// current getter. +void UnitTestImpl::set_os_stack_trace_getter( + OsStackTraceGetterInterface* getter) { + if (os_stack_trace_getter_ != getter) { + delete os_stack_trace_getter_; + os_stack_trace_getter_ = getter; + } +} + +// Returns the current OS stack trace getter if it is not NULL; +// otherwise, creates an OsStackTraceGetter, makes it the current +// getter, and returns it. +OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { + if (os_stack_trace_getter_ == NULL) { + os_stack_trace_getter_ = new OsStackTraceGetter; + } + + return os_stack_trace_getter_; +} + +// Returns the TestResult for the test that's currently running, or +// the TestResult for the ad hoc test if no test is running. +TestResult* UnitTestImpl::current_test_result() { + return current_test_info_ ? + &(current_test_info_->result_) : &ad_hoc_test_result_; +} + +// Shuffles all test cases, and the tests within each test case, +// making sure that death tests are still run first. +void UnitTestImpl::ShuffleTests() { + // Shuffles the death test cases. + ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); + + // Shuffles the non-death test cases. + ShuffleRange(random(), last_death_test_case_ + 1, + static_cast(test_cases_.size()), &test_case_indices_); + + // Shuffles the tests inside each test case. + for (size_t i = 0; i < test_cases_.size(); i++) { + test_cases_[i]->ShuffleTests(random()); + } +} + +// Restores the test cases and tests to their order before the first shuffle. +void UnitTestImpl::UnshuffleTests() { + for (size_t i = 0; i < test_cases_.size(); i++) { + // Unshuffles the tests in each test case. + test_cases_[i]->UnshuffleTests(); + // Resets the index of each test case. + test_case_indices_[i] = static_cast(i); + } +} + +// Returns the current OS stack trace as a String. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +String GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, + int skip_count) { + // We pass skip_count + 1 to skip this wrapper function in addition + // to what the user really wants to skip. + return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); +} + +// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to +// suppress unreachable code warnings. +namespace { +class ClassUniqueToAlwaysTrue {}; +} + +bool IsTrue(bool condition) { return condition; } + +bool AlwaysTrue() { +#if GTEST_HAS_EXCEPTIONS + // This condition is always false so AlwaysTrue() never actually throws, + // but it makes the compiler think that it may throw. + if (IsTrue(false)) + throw ClassUniqueToAlwaysTrue(); +#endif // GTEST_HAS_EXCEPTIONS + return true; +} + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr) { + const size_t prefix_len = strlen(prefix); + if (strncmp(*pstr, prefix, prefix_len) == 0) { + *pstr += prefix_len; + return true; + } + return false; +} + +// Parses a string as a command line flag. The string should have +// the format "--flag=value". When def_optional is true, the "=value" +// part can be omitted. +// +// Returns the value of the flag, or NULL if the parsing failed. +const char* ParseFlagValue(const char* str, + const char* flag, + bool def_optional) { + // str and flag must not be NULL. + if (str == NULL || flag == NULL) return NULL; + + // The flag must start with "--" followed by GTEST_FLAG_PREFIX_. + const String flag_str = String::Format("--%s%s", GTEST_FLAG_PREFIX_, flag); + const size_t flag_len = flag_str.length(); + if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; + + // Skips the flag name. + const char* flag_end = str + flag_len; + + // When def_optional is true, it's OK to not have a "=value" part. + if (def_optional && (flag_end[0] == '\0')) { + return flag_end; + } + + // If def_optional is true and there are more characters after the + // flag name, or if def_optional is false, there must be a '=' after + // the flag name. + if (flag_end[0] != '=') return NULL; + + // Returns the string after "=". + return flag_end + 1; +} + +// Parses a string for a bool flag, in the form of either +// "--flag=value" or "--flag". +// +// In the former case, the value is taken as true as long as it does +// not start with '0', 'f', or 'F'. +// +// In the latter case, the value is taken as true. +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseBoolFlag(const char* str, const char* flag, bool* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, true); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Converts the string value to a bool. + *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); + return true; +} + +// Parses a string for an Int32 flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + return ParseInt32(Message() << "The value of flag --" << flag, + value_str, value); +} + +// Parses a string for a string flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseStringFlag(const char* str, const char* flag, String* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + *value = value_str; + return true; +} + +// Determines whether a string has a prefix that Google Test uses for its +// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. +// If Google Test detects that a command line flag has its prefix but is not +// recognized, it will print its help message. Flags starting with +// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test +// internal flags and do not trigger the help message. +static bool HasGoogleTestFlagPrefix(const char* str) { + return (SkipPrefix("--", &str) || + SkipPrefix("-", &str) || + SkipPrefix("/", &str)) && + !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && + (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || + SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); +} + +// Prints a string containing code-encoded text. The following escape +// sequences can be used in the string to control the text color: +// +// @@ prints a single '@' character. +// @R changes the color to red. +// @G changes the color to green. +// @Y changes the color to yellow. +// @D changes to the default terminal text color. +// +// TODO(wan@google.com): Write tests for this once we add stdout +// capturing to Google Test. +static void PrintColorEncoded(const char* str) { + GTestColor color = COLOR_DEFAULT; // The current color. + + // Conceptually, we split the string into segments divided by escape + // sequences. Then we print one segment at a time. At the end of + // each iteration, the str pointer advances to the beginning of the + // next segment. + for (;;) { + const char* p = strchr(str, '@'); + if (p == NULL) { + ColoredPrintf(color, "%s", str); + return; + } + + ColoredPrintf(color, "%s", String(str, p - str).c_str()); + + const char ch = p[1]; + str = p + 2; + if (ch == '@') { + ColoredPrintf(color, "@"); + } else if (ch == 'D') { + color = COLOR_DEFAULT; + } else if (ch == 'R') { + color = COLOR_RED; + } else if (ch == 'G') { + color = COLOR_GREEN; + } else if (ch == 'Y') { + color = COLOR_YELLOW; + } else { + --str; + } + } +} + +static const char kColorEncodedHelpMessage[] = +"This program contains tests written using " GTEST_NAME_ ". You can use the\n" +"following command line flags to control its behavior:\n" +"\n" +"Test Selection:\n" +" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" +" List the names of all tests instead of running them. The name of\n" +" TEST(Foo, Bar) is \"Foo.Bar\".\n" +" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" + "[@G-@YNEGATIVE_PATTERNS]@D\n" +" Run only the tests whose name matches one of the positive patterns but\n" +" none of the negative patterns. '?' matches any single character; '*'\n" +" matches any substring; ':' separates two patterns.\n" +" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" +" Run all disabled tests too.\n" +"\n" +"Test Execution:\n" +" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" +" Run the tests repeatedly; use a negative count to repeat forever.\n" +" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" +" Randomize tests' orders on every iteration.\n" +" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" +" Random number seed to use for shuffling test orders (between 1 and\n" +" 99999, or 0 to use a seed based on the current time).\n" +"\n" +"Test Output:\n" +" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" +" Enable/disable colored output. The default is @Gauto@D.\n" +" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" +" Don't print the elapsed time of each test.\n" +" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" + GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" +" Generate an XML report in the given directory or with the given file\n" +" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" +#if GTEST_CAN_STREAM_RESULTS_ +" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" +" Stream test results to the given server.\n" +#endif // GTEST_CAN_STREAM_RESULTS_ +"\n" +"Assertion Behavior:\n" +#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" +" Set the default death test style.\n" +#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" +" Turn assertion failures into debugger break-points.\n" +" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" +" Turn assertion failures into C++ exceptions.\n" +" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" +" Do not report exceptions as test failures. Instead, allow them\n" +" to crash the program or throw a pop-up (on Windows).\n" +"\n" +"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " + "the corresponding\n" +"environment variable of a flag (all letters in upper-case). For example, to\n" +"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ + "color=no@D or set\n" +"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" +"\n" +"For more information, please read the " GTEST_NAME_ " documentation at\n" +"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" +"(not one in your own code or tests), please report it to\n" +"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. The type parameter CharType can be +// instantiated to either char or wchar_t. +template +void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { + for (int i = 1; i < *argc; i++) { + const String arg_string = StreamableToString(argv[i]); + const char* const arg = arg_string.c_str(); + + using internal::ParseBoolFlag; + using internal::ParseInt32Flag; + using internal::ParseStringFlag; + + // Do we see a Google Test flag? + if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, + >EST_FLAG(also_run_disabled_tests)) || + ParseBoolFlag(arg, kBreakOnFailureFlag, + >EST_FLAG(break_on_failure)) || + ParseBoolFlag(arg, kCatchExceptionsFlag, + >EST_FLAG(catch_exceptions)) || + ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || + ParseStringFlag(arg, kDeathTestStyleFlag, + >EST_FLAG(death_test_style)) || + ParseBoolFlag(arg, kDeathTestUseFork, + >EST_FLAG(death_test_use_fork)) || + ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || + ParseStringFlag(arg, kInternalRunDeathTestFlag, + >EST_FLAG(internal_run_death_test)) || + ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || + ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || + ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || + ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || + ParseInt32Flag(arg, kStackTraceDepthFlag, + >EST_FLAG(stack_trace_depth)) || + ParseStringFlag(arg, kStreamResultToFlag, + >EST_FLAG(stream_result_to)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, + >EST_FLAG(throw_on_failure)) + ) { + // Yes. Shift the remainder of the argv list left by one. Note + // that argv has (*argc + 1) elements, the last one always being + // NULL. The following loop moves the trailing NULL element as + // well. + for (int j = i; j != *argc; j++) { + argv[j] = argv[j + 1]; + } + + // Decrements the argument count. + (*argc)--; + + // We also need to decrement the iterator as we just removed + // an element. + i--; + } else if (arg_string == "--help" || arg_string == "-h" || + arg_string == "-?" || arg_string == "/?" || + HasGoogleTestFlagPrefix(arg)) { + // Both help flag and unrecognized Google Test flags (excluding + // internal ones) trigger help display. + g_help_flag = true; + } + } + + if (g_help_flag) { + // We print the help here instead of in RUN_ALL_TESTS(), as the + // latter may not be called at all if the user is using Google + // Test with another testing framework. + PrintColorEncoded(kColorEncodedHelpMessage); + } +} + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +void ParseGoogleTestFlagsOnly(int* argc, char** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} +void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} + +// The internal implementation of InitGoogleTest(). +// +// The type parameter CharType can be instantiated to either char or +// wchar_t. +template +void InitGoogleTestImpl(int* argc, CharType** argv) { + g_init_gtest_count++; + + // We don't want to run the initialization code twice. + if (g_init_gtest_count != 1) return; + + if (*argc <= 0) return; + + internal::g_executable_path = internal::StreamableToString(argv[0]); + +#if GTEST_HAS_DEATH_TEST + + g_argvs.clear(); + for (int i = 0; i != *argc; i++) { + g_argvs.push_back(StreamableToString(argv[i])); + } + +#endif // GTEST_HAS_DEATH_TEST + + ParseGoogleTestFlagsOnly(argc, argv); + GetUnitTestImpl()->PostFlagParsingInit(); +} + +} // namespace internal + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +void InitGoogleTest(int* argc, char** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +void InitGoogleTest(int* argc, wchar_t** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +} // namespace testing +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev) +// +// This file implements death tests. + + +#if GTEST_HAS_DEATH_TEST + +# if GTEST_OS_MAC +# include +# endif // GTEST_OS_MAC + +# include +# include +# include +# include + +# if GTEST_OS_WINDOWS +# include +# else +# include +# include +# endif // GTEST_OS_WINDOWS + +#endif // GTEST_HAS_DEATH_TEST + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +// Constants. + +// The default death test style. +static const char kDefaultDeathTestStyle[] = "fast"; + +GTEST_DEFINE_string_( + death_test_style, + internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), + "Indicates how to run a death test in a forked child process: " + "\"threadsafe\" (child process re-executes the test binary " + "from the beginning, running only the specific death test) or " + "\"fast\" (child process runs the death test immediately " + "after forking)."); + +GTEST_DEFINE_bool_( + death_test_use_fork, + internal::BoolFromGTestEnv("death_test_use_fork", false), + "Instructs to use fork()/_exit() instead of clone() in death tests. " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " + "it sees an unsupported combination of clone() flags. " + "It is not recommended to use this flag w/o valgrind though it will " + "work in 99% of the cases. Once valgrind is fixed, this flag will " + "most likely be removed."); + +namespace internal { +GTEST_DEFINE_string_( + internal_run_death_test, "", + "Indicates the file, line number, temporal index of " + "the single death test to run, and a file descriptor to " + "which a success code may be sent, all separated by " + "colons. This flag is specified if and only if the current " + "process is a sub-process launched for running a thread-safe " + "death test. FOR INTERNAL USE ONLY."); +} // namespace internal + +#if GTEST_HAS_DEATH_TEST + +// ExitedWithCode constructor. +ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { +} + +// ExitedWithCode function-call operator. +bool ExitedWithCode::operator()(int exit_status) const { +# if GTEST_OS_WINDOWS + + return exit_status == exit_code_; + +# else + + return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; + +# endif // GTEST_OS_WINDOWS +} + +# if !GTEST_OS_WINDOWS +// KilledBySignal constructor. +KilledBySignal::KilledBySignal(int signum) : signum_(signum) { +} + +// KilledBySignal function-call operator. +bool KilledBySignal::operator()(int exit_status) const { + return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; +} +# endif // !GTEST_OS_WINDOWS + +namespace internal { + +// Utilities needed for death tests. + +// Generates a textual description of a given exit code, in the format +// specified by wait(2). +static String ExitSummary(int exit_code) { + Message m; + +# if GTEST_OS_WINDOWS + + m << "Exited with exit status " << exit_code; + +# else + + if (WIFEXITED(exit_code)) { + m << "Exited with exit status " << WEXITSTATUS(exit_code); + } else if (WIFSIGNALED(exit_code)) { + m << "Terminated by signal " << WTERMSIG(exit_code); + } +# ifdef WCOREDUMP + if (WCOREDUMP(exit_code)) { + m << " (core dumped)"; + } +# endif +# endif // GTEST_OS_WINDOWS + + return m.GetString(); +} + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +bool ExitedUnsuccessfully(int exit_status) { + return !ExitedWithCode(0)(exit_status); +} + +# if !GTEST_OS_WINDOWS +// Generates a textual failure message when a death test finds more than +// one thread running, or cannot determine the number of threads, prior +// to executing the given statement. It is the responsibility of the +// caller not to pass a thread_count of 1. +static String DeathTestThreadWarning(size_t thread_count) { + Message msg; + msg << "Death tests use fork(), which is unsafe particularly" + << " in a threaded context. For this test, " << GTEST_NAME_ << " "; + if (thread_count == 0) + msg << "couldn't detect the number of threads."; + else + msg << "detected " << thread_count << " threads."; + return msg.GetString(); +} +# endif // !GTEST_OS_WINDOWS + +// Flag characters for reporting a death test that did not die. +static const char kDeathTestLived = 'L'; +static const char kDeathTestReturned = 'R'; +static const char kDeathTestThrew = 'T'; +static const char kDeathTestInternalError = 'I'; + +// An enumeration describing all of the possible ways that a death test can +// conclude. DIED means that the process died while executing the test +// code; LIVED means that process lived beyond the end of the test code; +// RETURNED means that the test statement attempted to execute a return +// statement, which is not allowed; THREW means that the test statement +// returned control by throwing an exception. IN_PROGRESS means the test +// has not yet concluded. +// TODO(vladl@google.com): Unify names and possibly values for +// AbortReason, DeathTestOutcome, and flag characters above. +enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; + +// Routine for aborting the program which is safe to call from an +// exec-style death test child process, in which case the error +// message is propagated back to the parent process. Otherwise, the +// message is simply printed to stderr. In either case, the program +// then exits with status 1. +void DeathTestAbort(const String& message) { + // On a POSIX system, this function may be called from a threadsafe-style + // death test child process, which operates on a very small stack. Use + // the heap for any additional non-minuscule memory requirements. + const InternalRunDeathTestFlag* const flag = + GetUnitTestImpl()->internal_run_death_test_flag(); + if (flag != NULL) { + FILE* parent = posix::FDOpen(flag->write_fd(), "w"); + fputc(kDeathTestInternalError, parent); + fprintf(parent, "%s", message.c_str()); + fflush(parent); + _exit(1); + } else { + fprintf(stderr, "%s", message.c_str()); + fflush(stderr); + posix::Abort(); + } +} + +// A replacement for CHECK that calls DeathTestAbort if the assertion +// fails. +# define GTEST_DEATH_TEST_CHECK_(expression) \ + do { \ + if (!::testing::internal::IsTrue(expression)) { \ + DeathTestAbort(::testing::internal::String::Format( \ + "CHECK failed: File %s, line %d: %s", \ + __FILE__, __LINE__, #expression)); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for +// evaluating any system call that fulfills two conditions: it must return +// -1 on failure, and set errno to EINTR when it is interrupted and +// should be tried again. The macro expands to a loop that repeatedly +// evaluates the expression as long as it evaluates to -1 and sets +// errno to EINTR. If the expression evaluates to -1 but errno is +// something other than EINTR, DeathTestAbort is called. +# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ + do { \ + int gtest_retval; \ + do { \ + gtest_retval = (expression); \ + } while (gtest_retval == -1 && errno == EINTR); \ + if (gtest_retval == -1) { \ + DeathTestAbort(::testing::internal::String::Format( \ + "CHECK failed: File %s, line %d: %s != -1", \ + __FILE__, __LINE__, #expression)); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// Returns the message describing the last system error in errno. +String GetLastErrnoDescription() { + return String(errno == 0 ? "" : posix::StrError(errno)); +} + +// This is called from a death test parent process to read a failure +// message from the death test child process and log it with the FATAL +// severity. On Windows, the message is read from a pipe handle. On other +// platforms, it is read from a file descriptor. +static void FailFromInternalError(int fd) { + Message error; + char buffer[256]; + int num_read; + + do { + while ((num_read = posix::Read(fd, buffer, 255)) > 0) { + buffer[num_read] = '\0'; + error << buffer; + } + } while (num_read == -1 && errno == EINTR); + + if (num_read == 0) { + GTEST_LOG_(FATAL) << error.GetString(); + } else { + const int last_error = errno; + GTEST_LOG_(FATAL) << "Error while reading death test internal: " + << GetLastErrnoDescription() << " [" << last_error << "]"; + } +} + +// Death test constructor. Increments the running death test count +// for the current test. +DeathTest::DeathTest() { + TestInfo* const info = GetUnitTestImpl()->current_test_info(); + if (info == NULL) { + DeathTestAbort("Cannot run a death test outside of a TEST or " + "TEST_F construct"); + } +} + +// Creates and returns a death test by dispatching to the current +// death test factory. +bool DeathTest::Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) { + return GetUnitTestImpl()->death_test_factory()->Create( + statement, regex, file, line, test); +} + +const char* DeathTest::LastMessage() { + return last_death_test_message_.c_str(); +} + +void DeathTest::set_last_death_test_message(const String& message) { + last_death_test_message_ = message; +} + +String DeathTest::last_death_test_message_; + +// Provides cross platform implementation for some death functionality. +class DeathTestImpl : public DeathTest { + protected: + DeathTestImpl(const char* a_statement, const RE* a_regex) + : statement_(a_statement), + regex_(a_regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS), + read_fd_(-1), + write_fd_(-1) {} + + // read_fd_ is expected to be closed and cleared by a derived class. + ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + + void Abort(AbortReason reason); + virtual bool Passed(bool status_ok); + + const char* statement() const { return statement_; } + const RE* regex() const { return regex_; } + bool spawned() const { return spawned_; } + void set_spawned(bool is_spawned) { spawned_ = is_spawned; } + int status() const { return status_; } + void set_status(int a_status) { status_ = a_status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } + int read_fd() const { return read_fd_; } + void set_read_fd(int fd) { read_fd_ = fd; } + int write_fd() const { return write_fd_; } + void set_write_fd(int fd) { write_fd_ = fd; } + + // Called in the parent process only. Reads the result code of the death + // test child process via a pipe, interprets it to set the outcome_ + // member, and closes read_fd_. Outputs diagnostics and terminates in + // case of unexpected codes. + void ReadAndInterpretStatusByte(); + + private: + // The textual content of the code this object is testing. This class + // doesn't own this string and should not attempt to delete it. + const char* const statement_; + // The regular expression which test output must match. DeathTestImpl + // doesn't own this object and should not attempt to delete it. + const RE* const regex_; + // True if the death test child process has been successfully spawned. + bool spawned_; + // The exit status of the child process. + int status_; + // How the death test concluded. + DeathTestOutcome outcome_; + // Descriptor to the read end of the pipe to the child process. It is + // always -1 in the child process. The child keeps its write end of the + // pipe in write_fd_. + int read_fd_; + // Descriptor to the child's write end of the pipe to the parent process. + // It is always -1 in the parent process. The parent keeps its end of the + // pipe in read_fd_. + int write_fd_; +}; + +// Called in the parent process only. Reads the result code of the death +// test child process via a pipe, interprets it to set the outcome_ +// member, and closes read_fd_. Outputs diagnostics and terminates in +// case of unexpected codes. +void DeathTestImpl::ReadAndInterpretStatusByte() { + char flag; + int bytes_read; + + // The read() here blocks until data is available (signifying the + // failure of the death test) or until the pipe is closed (signifying + // its success), so it's okay to call this in the parent before + // the child process has exited. + do { + bytes_read = posix::Read(read_fd(), &flag, 1); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == 0) { + set_outcome(DIED); + } else if (bytes_read == 1) { + switch (flag) { + case kDeathTestReturned: + set_outcome(RETURNED); + break; + case kDeathTestThrew: + set_outcome(THREW); + break; + case kDeathTestLived: + set_outcome(LIVED); + break; + case kDeathTestInternalError: + FailFromInternalError(read_fd()); // Does not return. + break; + default: + GTEST_LOG_(FATAL) << "Death test child process reported " + << "unexpected status byte (" + << static_cast(flag) << ")"; + } + } else { + GTEST_LOG_(FATAL) << "Read from death test child process failed: " + << GetLastErrnoDescription(); + } + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); + set_read_fd(-1); +} + +// Signals that the death test code which should have exited, didn't. +// Should be called only in a death test child process. +// Writes a status byte to the child's status file descriptor, then +// calls _exit(1). +void DeathTestImpl::Abort(AbortReason reason) { + // The parent process considers the death test to be a failure if + // it finds any data in our pipe. So, here we write a single flag byte + // to the pipe, then exit. + const char status_ch = + reason == TEST_DID_NOT_DIE ? kDeathTestLived : + reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; + + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); + // We are leaking the descriptor here because on some platforms (i.e., + // when built as Windows DLL), destructors of global objects will still + // run after calling _exit(). On such systems, write_fd_ will be + // indirectly closed from the destructor of UnitTestImpl, causing double + // close if it is also closed here. On debug configurations, double close + // may assert. As there are no in-process buffers to flush here, we are + // relying on the OS to close the descriptor after the process terminates + // when the destructors are not run. + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +} + +// Returns an indented copy of stderr output for a death test. +// This makes distinguishing death test output lines from regular log lines +// much easier. +static ::std::string FormatDeathTestOutput(const ::std::string& output) { + ::std::string ret; + for (size_t at = 0; ; ) { + const size_t line_end = output.find('\n', at); + ret += "[ DEATH ] "; + if (line_end == ::std::string::npos) { + ret += output.substr(at); + break; + } + ret += output.substr(at, line_end + 1 - at); + at = line_end + 1; + } + return ret; +} + +// Assesses the success or failure of a death test, using both private +// members which have previously been set, and one argument: +// +// Private data members: +// outcome: An enumeration describing how the death test +// concluded: DIED, LIVED, THREW, or RETURNED. The death test +// fails in the latter three cases. +// status: The exit status of the child process. On *nix, it is in the +// in the format specified by wait(2). On Windows, this is the +// value supplied to the ExitProcess() API or a numeric code +// of the exception that terminated the program. +// regex: A regular expression object to be applied to +// the test's captured standard error output; the death test +// fails if it does not match. +// +// Argument: +// status_ok: true if exit_status is acceptable in the context of +// this particular death test, which fails if it is false +// +// Returns true iff all of the above conditions are met. Otherwise, the +// first failing condition, in the order given above, is the one that is +// reported. Also sets the last death test message string. +bool DeathTestImpl::Passed(bool status_ok) { + if (!spawned()) + return false; + + const String error_message = GetCapturedStderr(); + + bool success = false; + Message buffer; + + buffer << "Death test: " << statement() << "\n"; + switch (outcome()) { + case LIVED: + buffer << " Result: failed to die.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case THREW: + buffer << " Result: threw an exception.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case RETURNED: + buffer << " Result: illegal return in test statement.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case DIED: + if (status_ok) { + const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); + if (matched) { + success = true; + } else { + buffer << " Result: died but not with expected error.\n" + << " Expected: " << regex()->pattern() << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + } else { + buffer << " Result: died but not with expected exit code:\n" + << " " << ExitSummary(status()) << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + break; + case IN_PROGRESS: + default: + GTEST_LOG_(FATAL) + << "DeathTest::Passed somehow called before conclusion of test"; + } + + DeathTest::set_last_death_test_message(buffer.GetString()); + return success; +} + +# if GTEST_OS_WINDOWS +// WindowsDeathTest implements death tests on Windows. Due to the +// specifics of starting new processes on Windows, death tests there are +// always threadsafe, and Google Test considers the +// --gtest_death_test_style=fast setting to be equivalent to +// --gtest_death_test_style=threadsafe there. +// +// A few implementation notes: Like the Linux version, the Windows +// implementation uses pipes for child-to-parent communication. But due to +// the specifics of pipes on Windows, some extra steps are required: +// +// 1. The parent creates a communication pipe and stores handles to both +// ends of it. +// 2. The parent starts the child and provides it with the information +// necessary to acquire the handle to the write end of the pipe. +// 3. The child acquires the write end of the pipe and signals the parent +// using a Windows event. +// 4. Now the parent can release the write end of the pipe on its side. If +// this is done before step 3, the object's reference count goes down to +// 0 and it is destroyed, preventing the child from acquiring it. The +// parent now has to release it, or read operations on the read end of +// the pipe will not return when the child terminates. +// 5. The parent reads child's output through the pipe (outcome code and +// any possible error messages) from the pipe, and its stderr and then +// determines whether to fail the test. +// +// Note: to distinguish Win32 API calls from the local method and function +// calls, the former are explicitly resolved in the global namespace. +// +class WindowsDeathTest : public DeathTestImpl { + public: + WindowsDeathTest(const char* a_statement, + const RE* a_regex, + const char* file, + int line) + : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // Handle to the write end of the pipe to the child process. + AutoHandle write_handle_; + // Child process handle. + AutoHandle child_handle_; + // Event the child process uses to signal the parent that it has + // acquired the handle to the write end of the pipe. After seeing this + // event the parent can release its own handles to make sure its + // ReadFile() calls return when the child terminates. + AutoHandle event_handle_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int WindowsDeathTest::Wait() { + if (!spawned()) + return 0; + + // Wait until the child either signals that it has acquired the write end + // of the pipe or it dies. + const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; + switch (::WaitForMultipleObjects(2, + wait_handles, + FALSE, // Waits for any of the handles. + INFINITE)) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + break; + default: + GTEST_DEATH_TEST_CHECK_(false); // Should not get here. + } + + // The child has acquired the write end of the pipe or exited. + // We release the handle on our side and continue. + write_handle_.Reset(); + event_handle_.Reset(); + + ReadAndInterpretStatusByte(); + + // Waits for the child process to exit if it haven't already. This + // returns immediately if the child has already exited, regardless of + // whether previous calls to WaitForMultipleObjects synchronized on this + // handle or not. + GTEST_DEATH_TEST_CHECK_( + WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), + INFINITE)); + DWORD status_code; + GTEST_DEATH_TEST_CHECK_( + ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); + child_handle_.Reset(); + set_status(static_cast(status_code)); + return status(); +} + +// The AssumeRole process for a Windows death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole WindowsDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // WindowsDeathTest uses an anonymous pipe to communicate results of + // a death test. + SECURITY_ATTRIBUTES handles_are_inheritable = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + HANDLE read_handle, write_handle; + GTEST_DEATH_TEST_CHECK_( + ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, + 0) // Default buffer size. + != FALSE); + set_read_fd(::_open_osfhandle(reinterpret_cast(read_handle), + O_RDONLY)); + write_handle_.Reset(write_handle); + event_handle_.Reset(::CreateEvent( + &handles_are_inheritable, + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + NULL)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); + const String filter_flag = String::Format("--%s%s=%s.%s", + GTEST_FLAG_PREFIX_, kFilterFlag, + info->test_case_name(), + info->name()); + const String internal_flag = String::Format( + "--%s%s=%s|%d|%d|%u|%Iu|%Iu", + GTEST_FLAG_PREFIX_, + kInternalRunDeathTestFlag, + file_, line_, + death_test_index, + static_cast(::GetCurrentProcessId()), + // size_t has the same with as pointers on both 32-bit and 64-bit + // Windows platforms. + // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. + reinterpret_cast(write_handle), + reinterpret_cast(event_handle_.Get())); + + char executable_path[_MAX_PATH + 1]; // NOLINT + GTEST_DEATH_TEST_CHECK_( + _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, + executable_path, + _MAX_PATH)); + + String command_line = String::Format("%s %s \"%s\"", + ::GetCommandLineA(), + filter_flag.c_str(), + internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // The child process will share the standard handles with the parent. + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFO)); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION process_info; + GTEST_DEATH_TEST_CHECK_(::CreateProcessA( + executable_path, + const_cast(command_line.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + NULL, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), + &startup_info, + &process_info) != FALSE); + child_handle_.Reset(process_info.hProcess); + ::CloseHandle(process_info.hThread); + set_spawned(true); + return OVERSEE_TEST; +} +# else // We are not on Windows. + +// ForkingDeathTest provides implementations for most of the abstract +// methods of the DeathTest interface. Only the AssumeRole method is +// left undefined. +class ForkingDeathTest : public DeathTestImpl { + public: + ForkingDeathTest(const char* statement, const RE* regex); + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + + protected: + void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + + private: + // PID of child process during death test; 0 in the child process itself. + pid_t child_pid_; +}; + +// Constructs a ForkingDeathTest. +ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) + : DeathTestImpl(a_statement, a_regex), + child_pid_(-1) {} + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int ForkingDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + int status_value; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); + set_status(status_value); + return status_value; +} + +// A concrete death test class that forks, then immediately runs the test +// in the child process. +class NoExecDeathTest : public ForkingDeathTest { + public: + NoExecDeathTest(const char* a_statement, const RE* a_regex) : + ForkingDeathTest(a_statement, a_regex) { } + virtual TestRole AssumeRole(); +}; + +// The AssumeRole process for a fork-and-run death test. It implements a +// straightforward fork, with a simple pipe to transmit the status byte. +DeathTest::TestRole NoExecDeathTest::AssumeRole() { + const size_t thread_count = GetThreadCount(); + if (thread_count != 1) { + GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + + DeathTest::set_last_death_test_message(""); + CaptureStderr(); + // When we fork the process below, the log file buffers are copied, but the + // file descriptors are shared. We flush all log files here so that closing + // the file descriptors in the child process doesn't throw off the + // synchronization between descriptors and buffers in the parent process. + // This is as close to the fork as possible to avoid a race condition in case + // there are multiple threads running before the death test, and another + // thread writes to the log file. + FlushInfoLog(); + + const pid_t child_pid = fork(); + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + set_child_pid(child_pid); + if (child_pid == 0) { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0])); + set_write_fd(pipe_fd[1]); + // Redirects all logging to stderr in the child process to prevent + // concurrent writes to the log files. We capture stderr in the parent + // process and append the child process' output to a log. + LogToStderr(); + // Event forwarding to the listeners of event listener API mush be shut + // down in death test subprocesses. + GetUnitTestImpl()->listeners()->SuppressEventForwarding(); + return EXECUTE_TEST; + } else { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; + } +} + +// A concrete death test class that forks and re-executes the main +// program from the beginning, with command-line flags set that cause +// only this specific death test to be run. +class ExecDeathTest : public ForkingDeathTest { + public: + ExecDeathTest(const char* a_statement, const RE* a_regex, + const char* file, int line) : + ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } + virtual TestRole AssumeRole(); + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; +}; + +// Utility class for accumulating command-line arguments. +class Arguments { + public: + Arguments() { + args_.push_back(NULL); + } + + ~Arguments() { + for (std::vector::iterator i = args_.begin(); i != args_.end(); + ++i) { + free(*i); + } + } + void AddArgument(const char* argument) { + args_.insert(args_.end() - 1, posix::StrDup(argument)); + } + + template + void AddArguments(const ::std::vector& arguments) { + for (typename ::std::vector::const_iterator i = arguments.begin(); + i != arguments.end(); + ++i) { + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); + } + } + char* const* Argv() { + return &args_[0]; + } + private: + std::vector args_; +}; + +// A struct that encompasses the arguments to the child process of a +// threadsafe-style death test process. +struct ExecDeathTestArgs { + char* const* argv; // Command-line arguments for the child's call to exec + int close_fd; // File descriptor to close; the read end of a pipe +}; + +# if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +# else +// Some POSIX platforms expect you to declare environ. extern "C" makes +// it reside in the global namespace. +extern "C" char** environ; +inline char** GetEnviron() { return environ; } +# endif // GTEST_OS_MAC + +// The main function for a threadsafe-style death test child process. +// This function is called in a clone()-ed process and thus must avoid +// any potentially unsafe operations like malloc or libc functions. +static int ExecDeathTestChildMain(void* child_arg) { + ExecDeathTestArgs* const args = static_cast(child_arg); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); + + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(String::Format("chdir(\"%s\") failed: %s", + original_dir, + GetLastErrnoDescription().c_str())); + return EXIT_FAILURE; + } + + // We can safely call execve() as it's a direct system call. We + // cannot use execvp() as it's a libc function and thus potentially + // unsafe. Since execve() doesn't search the PATH, the user must + // invoke the test program via a valid path that contains at least + // one path separator. + execve(args->argv[0], args->argv, GetEnviron()); + DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s", + args->argv[0], + original_dir, + GetLastErrnoDescription().c_str())); + return EXIT_FAILURE; +} + +// Two utility routines that together determine the direction the stack +// grows. +// This could be accomplished more elegantly by a single recursive +// function, but we want to guard against the unlikely possibility of +// a smart compiler optimizing the recursion away. +// +// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining +// StackLowerThanAddress into StackGrowsDown, which then doesn't give +// correct answer. +bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_; +bool StackLowerThanAddress(const void* ptr) { + int dummy; + return &dummy < ptr; +} + +bool StackGrowsDown() { + int dummy; + return StackLowerThanAddress(&dummy); +} + +// A threadsafe implementation of fork(2) for threadsafe-style death tests +// that uses clone(2). It dies with an error message if anything goes +// wrong. +static pid_t ExecDeathTestFork(char* const* argv, int close_fd) { + ExecDeathTestArgs args = { argv, close_fd }; + pid_t child_pid = -1; + +# if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + void* const stack_top = + static_cast(stack) + (stack_grows_down ? stack_size : 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +# else + const bool use_fork = true; +# endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { + ExecDeathTestChildMain(&args); + _exit(0); + } + + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + return child_pid; +} + +// The AssumeRole process for a fork-and-exec death test. It re-executes the +// main program from the beginning, setting the --gtest_filter +// and --gtest_internal_run_death_test flags to cause only the current +// death test to be re-run. +DeathTest::TestRole ExecDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + // Clear the close-on-exec flag on the write end of the pipe, lest + // it be closed when the child process does an exec: + GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); + + const String filter_flag = + String::Format("--%s%s=%s.%s", + GTEST_FLAG_PREFIX_, kFilterFlag, + info->test_case_name(), info->name()); + const String internal_flag = + String::Format("--%s%s=%s|%d|%d|%d", + GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag, + file_, line_, death_test_index, pipe_fd[1]); + Arguments args; + args.AddArguments(GetArgvs()); + args.AddArgument(filter_flag.c_str()); + args.AddArgument(internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // See the comment in NoExecDeathTest::AssumeRole for why the next line + // is necessary. + FlushInfoLog(); + + const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_child_pid(child_pid); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; +} + +# endif // !GTEST_OS_WINDOWS + +// Creates a concrete DeathTest-derived class that depends on the +// --gtest_death_test_style flag, and sets the pointer pointed to +// by the "test" argument to its address. If the test should be +// skipped, sets that pointer to NULL. Returns true, unless the +// flag is set to an invalid value. +bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, + const char* file, int line, + DeathTest** test) { + UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const int death_test_index = impl->current_test_info() + ->increment_death_test_count(); + + if (flag != NULL) { + if (death_test_index > flag->index()) { + DeathTest::set_last_death_test_message(String::Format( + "Death test count (%d) somehow exceeded expected maximum (%d)", + death_test_index, flag->index())); + return false; + } + + if (!(flag->file() == file && flag->line() == line && + flag->index() == death_test_index)) { + *test = NULL; + return true; + } + } + +# if GTEST_OS_WINDOWS + + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new WindowsDeathTest(statement, regex, file, line); + } + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") { + *test = new ExecDeathTest(statement, regex, file, line); + } else if (GTEST_FLAG(death_test_style) == "fast") { + *test = new NoExecDeathTest(statement, regex); + } + +# endif // GTEST_OS_WINDOWS + + else { // NOLINT - this is more readable than unbalanced brackets inside #if. + DeathTest::set_last_death_test_message(String::Format( + "Unknown death test style \"%s\" encountered", + GTEST_FLAG(death_test_style).c_str())); + return false; + } + + return true; +} + +// Splits a given string on a given delimiter, populating a given +// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have +// ::std::string, so we can use it here. +static void SplitString(const ::std::string& str, char delimiter, + ::std::vector< ::std::string>* dest) { + ::std::vector< ::std::string> parsed; + ::std::string::size_type pos = 0; + while (::testing::internal::AlwaysTrue()) { + const ::std::string::size_type colon = str.find(delimiter, pos); + if (colon == ::std::string::npos) { + parsed.push_back(str.substr(pos)); + break; + } else { + parsed.push_back(str.substr(pos, colon - pos)); + pos = colon + 1; + } + } + dest->swap(parsed); +} + +# if GTEST_OS_WINDOWS +// Recreates the pipe and event handles from the provided parameters, +// signals the event, and returns a file descriptor wrapped around the pipe +// handle. This function is called in the child process only. +int GetStatusFileDescriptor(unsigned int parent_process_id, + size_t write_handle_as_size_t, + size_t event_handle_as_size_t) { + AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, // Non-inheritable. + parent_process_id)); + if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { + DeathTestAbort(String::Format("Unable to open parent process %u", + parent_process_id)); + } + + // TODO(vladl@google.com): Replace the following check with a + // compile-time assertion when available. + GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); + + const HANDLE write_handle = + reinterpret_cast(write_handle_as_size_t); + HANDLE dup_write_handle; + + // The newly initialized handle is accessible only in in the parent + // process. To obtain one accessible within the child, we need to use + // DuplicateHandle. + if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, + ::GetCurrentProcess(), &dup_write_handle, + 0x0, // Requested privileges ignored since + // DUPLICATE_SAME_ACCESS is used. + FALSE, // Request non-inheritable handler. + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort(String::Format( + "Unable to duplicate the pipe handle %Iu from the parent process %u", + write_handle_as_size_t, parent_process_id)); + } + + const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); + HANDLE dup_event_handle; + + if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, + ::GetCurrentProcess(), &dup_event_handle, + 0x0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort(String::Format( + "Unable to duplicate the event handle %Iu from the parent process %u", + event_handle_as_size_t, parent_process_id)); + } + + const int write_fd = + ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); + if (write_fd == -1) { + DeathTestAbort(String::Format( + "Unable to convert pipe handle %Iu to a file descriptor", + write_handle_as_size_t)); + } + + // Signals the parent that the write end of the pipe has been acquired + // so the parent can release its own write end. + ::SetEvent(dup_event_handle); + + return write_fd; +} +# endif // GTEST_OS_WINDOWS + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { + if (GTEST_FLAG(internal_run_death_test) == "") return NULL; + + // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we + // can use it here. + int line = -1; + int index = -1; + ::std::vector< ::std::string> fields; + SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); + int write_fd = -1; + +# if GTEST_OS_WINDOWS + + unsigned int parent_process_id = 0; + size_t write_handle_as_size_t = 0; + size_t event_handle_as_size_t = 0; + + if (fields.size() != 6 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &parent_process_id) + || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) + || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { + DeathTestAbort(String::Format( + "Bad --gtest_internal_run_death_test flag: %s", + GTEST_FLAG(internal_run_death_test).c_str())); + } + write_fd = GetStatusFileDescriptor(parent_process_id, + write_handle_as_size_t, + event_handle_as_size_t); +# else + + if (fields.size() != 4 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &write_fd)) { + DeathTestAbort(String::Format( + "Bad --gtest_internal_run_death_test flag: %s", + GTEST_FLAG(internal_run_death_test).c_str())); + } + +# endif // GTEST_OS_WINDOWS + + return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); +} + +} // namespace internal + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace testing +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: keith.ray@gmail.com (Keith Ray) + + +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include +#elif GTEST_OS_WINDOWS +# include +# include +#elif GTEST_OS_SYMBIAN || GTEST_OS_NACL +// Symbian OpenC and NaCl have PATH_MAX in sys/syslimits.h +# include +#else +# include +# include // Some Linux distributions define PATH_MAX here. +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_MAX_ _MAX_PATH +#elif defined(PATH_MAX) +# define GTEST_PATH_MAX_ PATH_MAX +#elif defined(_XOPEN_PATH_MAX) +# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX +#else +# define GTEST_PATH_MAX_ _POSIX_PATH_MAX +#endif // GTEST_OS_WINDOWS + + +namespace testing { +namespace internal { + +#if GTEST_OS_WINDOWS +// On Windows, '\\' is the standard path separator, but many tools and the +// Windows API also accept '/' as an alternate path separator. Unless otherwise +// noted, a file path can contain either kind of path separators, or a mixture +// of them. +const char kPathSeparator = '\\'; +const char kAlternatePathSeparator = '/'; +const char kPathSeparatorString[] = "\\"; +const char kAlternatePathSeparatorString[] = "/"; +# if GTEST_OS_WINDOWS_MOBILE +// Windows CE doesn't have a current directory. You should not use +// the current directory in tests on Windows CE, but this at least +// provides a reasonable fallback. +const char kCurrentDirectoryString[] = "\\"; +// Windows CE doesn't define INVALID_FILE_ATTRIBUTES +const DWORD kInvalidFileAttributes = 0xffffffff; +# else +const char kCurrentDirectoryString[] = ".\\"; +# endif // GTEST_OS_WINDOWS_MOBILE +#else +const char kPathSeparator = '/'; +const char kPathSeparatorString[] = "/"; +const char kCurrentDirectoryString[] = "./"; +#endif // GTEST_OS_WINDOWS + +// Returns whether the given character is a valid path separator. +static bool IsPathSeparator(char c) { +#if GTEST_HAS_ALT_PATH_SEP_ + return (c == kPathSeparator) || (c == kAlternatePathSeparator); +#else + return c == kPathSeparator; +#endif +} + +// Returns the current working directory, or "" if unsuccessful. +FilePath FilePath::GetCurrentDir() { +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE doesn't have a current directory, so we just return + // something reasonable. + return FilePath(kCurrentDirectoryString); +#elif GTEST_OS_WINDOWS + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#else + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns a copy of the FilePath with the case-insensitive extension removed. +// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns +// FilePath("dir/file"). If a case-insensitive extension is not +// found, returns a copy of the original FilePath. +FilePath FilePath::RemoveExtension(const char* extension) const { + String dot_extension(String::Format(".%s", extension)); + if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) { + return FilePath(String(pathname_.c_str(), pathname_.length() - 4)); + } + return *this; +} + +// Returns a pointer to the last occurence of a valid path separator in +// the FilePath. On Windows, for example, both '/' and '\' are valid path +// separators. Returns NULL if no path separator was found. +const char* FilePath::FindLastPathSeparator() const { + const char* const last_sep = strrchr(c_str(), kPathSeparator); +#if GTEST_HAS_ALT_PATH_SEP_ + const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); + // Comparing two pointers of which only one is NULL is undefined. + if (last_alt_sep != NULL && + (last_sep == NULL || last_alt_sep > last_sep)) { + return last_alt_sep; + } +#endif + return last_sep; +} + +// Returns a copy of the FilePath with the directory part removed. +// Example: FilePath("path/to/file").RemoveDirectoryName() returns +// FilePath("file"). If there is no directory part ("just_a_file"), it returns +// the FilePath unmodified. If there is no file part ("just_a_dir/") it +// returns an empty FilePath (""). +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveDirectoryName() const { + const char* const last_sep = FindLastPathSeparator(); + return last_sep ? FilePath(String(last_sep + 1)) : *this; +} + +// RemoveFileName returns the directory path with the filename removed. +// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". +// If the FilePath is "a_file" or "/a_file", RemoveFileName returns +// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does +// not have a file, like "just/a/dir/", it returns the FilePath unmodified. +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveFileName() const { + const char* const last_sep = FindLastPathSeparator(); + String dir; + if (last_sep) { + dir = String(c_str(), last_sep + 1 - c_str()); + } else { + dir = kCurrentDirectoryString; + } + return FilePath(dir); +} + +// Helper functions for naming files in a directory for xml output. + +// Given directory = "dir", base_name = "test", number = 0, +// extension = "xml", returns "dir/test.xml". If number is greater +// than zero (e.g., 12), returns "dir/test_12.xml". +// On Windows platform, uses \ as the separator rather than /. +FilePath FilePath::MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension) { + String file; + if (number == 0) { + file = String::Format("%s.%s", base_name.c_str(), extension); + } else { + file = String::Format("%s_%d.%s", base_name.c_str(), number, extension); + } + return ConcatPaths(directory, FilePath(file)); +} + +// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". +// On Windows, uses \ as the separator rather than /. +FilePath FilePath::ConcatPaths(const FilePath& directory, + const FilePath& relative_path) { + if (directory.IsEmpty()) + return relative_path; + const FilePath dir(directory.RemoveTrailingPathSeparator()); + return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator, + relative_path.c_str())); +} + +// Returns true if pathname describes something findable in the file-system, +// either a file, directory, or whatever. +bool FilePath::FileOrDirectoryExists() const { +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + return attributes != kInvalidFileAttributes; +#else + posix::StatStruct file_stat; + return posix::Stat(pathname_.c_str(), &file_stat) == 0; +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns true if pathname describes a directory in the file-system +// that exists. +bool FilePath::DirectoryExists() const { + bool result = false; +#if GTEST_OS_WINDOWS + // Don't strip off trailing separator if path is a root directory on + // Windows (like "C:\\"). + const FilePath& path(IsRootDirectory() ? *this : + RemoveTrailingPathSeparator()); +#else + const FilePath& path(*this); +#endif + +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + if ((attributes != kInvalidFileAttributes) && + (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = true; + } +#else + posix::StatStruct file_stat; + result = posix::Stat(path.c_str(), &file_stat) == 0 && + posix::IsDir(file_stat); +#endif // GTEST_OS_WINDOWS_MOBILE + + return result; +} + +// Returns true if pathname describes a root directory. (Windows has one +// root directory per disk drive.) +bool FilePath::IsRootDirectory() const { +#if GTEST_OS_WINDOWS + // TODO(wan@google.com): on Windows a network share like + // \\server\share can be a root directory, although it cannot be the + // current directory. Handle this properly. + return pathname_.length() == 3 && IsAbsolutePath(); +#else + return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); +#endif +} + +// Returns true if pathname describes an absolute path. +bool FilePath::IsAbsolutePath() const { + const char* const name = pathname_.c_str(); +#if GTEST_OS_WINDOWS + return pathname_.length() >= 3 && + ((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z')) && + name[1] == ':' && + IsPathSeparator(name[2]); +#else + return IsPathSeparator(name[0]); +#endif +} + +// Returns a pathname for a file that does not currently exist. The pathname +// will be directory/base_name.extension or +// directory/base_name_.extension if directory/base_name.extension +// already exists. The number will be incremented until a pathname is found +// that does not already exist. +// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. +// There could be a race condition if two or more processes are calling this +// function at the same time -- they could both pick the same filename. +FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension) { + FilePath full_pathname; + int number = 0; + do { + full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); + } while (full_pathname.FileOrDirectoryExists()); + return full_pathname; +} + +// Returns true if FilePath ends with a path separator, which indicates that +// it is intended to represent a directory. Returns false otherwise. +// This does NOT check that a directory (or file) actually exists. +bool FilePath::IsDirectory() const { + return !pathname_.empty() && + IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); +} + +// Create directories so that path exists. Returns true if successful or if +// the directories already exist; returns false if unable to create directories +// for any reason. +bool FilePath::CreateDirectoriesRecursively() const { + if (!this->IsDirectory()) { + return false; + } + + if (pathname_.length() == 0 || this->DirectoryExists()) { + return true; + } + + const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); + return parent.CreateDirectoriesRecursively() && this->CreateFolder(); +} + +// Create the directory so that path exists. Returns true if successful or +// if the directory already exists; returns false if unable to create the +// directory for any reason, including if the parent directory does not +// exist. Not named "CreateDirectory" because that's a macro on Windows. +bool FilePath::CreateFolder() const { +#if GTEST_OS_WINDOWS_MOBILE + FilePath removed_sep(this->RemoveTrailingPathSeparator()); + LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); + int result = CreateDirectory(unicode, NULL) ? 0 : -1; + delete [] unicode; +#elif GTEST_OS_WINDOWS + int result = _mkdir(pathname_.c_str()); +#else + int result = mkdir(pathname_.c_str(), 0777); +#endif // GTEST_OS_WINDOWS_MOBILE + + if (result == -1) { + return this->DirectoryExists(); // An error is OK if the directory exists. + } + return true; // No error. +} + +// If input name has a trailing separator character, remove it and return the +// name, otherwise return the name string unmodified. +// On Windows platform, uses \ as the separator, other platforms use /. +FilePath FilePath::RemoveTrailingPathSeparator() const { + return IsDirectory() + ? FilePath(String(pathname_.c_str(), pathname_.length() - 1)) + : *this; +} + +// Removes any redundant separators that might be in the pathname. +// For example, "bar///foo" becomes "bar/foo". Does not eliminate other +// redundancies that might be in a pathname involving "." or "..". +// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). +void FilePath::Normalize() { + if (pathname_.c_str() == NULL) { + pathname_ = ""; + return; + } + const char* src = pathname_.c_str(); + char* const dest = new char[pathname_.length() + 1]; + char* dest_ptr = dest; + memset(dest_ptr, 0, pathname_.length() + 1); + + while (*src != '\0') { + *dest_ptr = *src; + if (!IsPathSeparator(*src)) { + src++; + } else { +#if GTEST_HAS_ALT_PATH_SEP_ + if (*dest_ptr == kAlternatePathSeparator) { + *dest_ptr = kPathSeparator; + } +#endif + while (IsPathSeparator(*src)) + src++; + } + dest_ptr++; + } + *dest_ptr = '\0'; + pathname_ = dest; + delete[] dest; +} + +} // namespace internal +} // namespace testing +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + + +#include +#include +#include +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include // For TerminateProcess() +#elif GTEST_OS_WINDOWS +# include +# include +#else +# include +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_MAC +# include +# include +# include +#endif // GTEST_OS_MAC + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { +namespace internal { + +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; +const int kStdErrFileno = 2; +#else +const int kStdOutFileno = STDOUT_FILENO; +const int kStdErrFileno = STDERR_FILENO; +#endif // _MSC_VER + +#if GTEST_OS_MAC + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const task_t task = mach_task_self(); + mach_msg_type_number_t thread_count; + thread_act_array_t thread_list; + const kern_return_t status = task_threads(task, &thread_list, &thread_count); + if (status == KERN_SUCCESS) { + // task_threads allocates resources in thread_list and we need to free them + // to avoid leaks. + vm_deallocate(task, + reinterpret_cast(thread_list), + sizeof(thread_t) * thread_count); + return static_cast(thread_count); + } else { + return 0; + } +} + +#else + +size_t GetThreadCount() { + // There's no portable way to detect the number of threads, so we just + // return 0 to indicate that we cannot detect it. + return 0; +} + +#endif // GTEST_OS_MAC + +#if GTEST_USES_POSIX_RE + +// Implements RE. Currently only needed for death tests. + +RE::~RE() { + if (is_valid_) { + // regfree'ing an invalid regex might crash because the content + // of the regex is undefined. Since the regex's are essentially + // the same, one cannot be valid (or invalid) without the other + // being so too. + regfree(&partial_regex_); + regfree(&full_regex_); + } + free(const_cast(pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.full_regex_, str, 1, &match, 0) == 0; +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = posix::StrDup(regex); + + // Reserves enough bytes to hold the regular expression used for a + // full match. + const size_t full_regex_len = strlen(regex) + 10; + char* const full_pattern = new char[full_regex_len]; + + snprintf(full_pattern, full_regex_len, "^(%s)$", regex); + is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; + // We want to call regcomp(&partial_regex_, ...) even if the + // previous expression returns false. Otherwise partial_regex_ may + // not be properly initialized can may cause trouble when it's + // freed. + // + // Some implementation of POSIX regex (e.g. on at least some + // versions of Cygwin) doesn't accept the empty string as a valid + // regex. We change it to an equivalent form "()" to be safe. + if (is_valid_) { + const char* const partial_regex = (*regex == '\0') ? "()" : regex; + is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; + } + EXPECT_TRUE(is_valid_) + << "Regular expression \"" << regex + << "\" is not a valid POSIX Extended regular expression."; + + delete[] full_pattern; +} + +#elif GTEST_USES_SIMPLE_RE + +// Returns true iff ch appears anywhere in str (excluding the +// terminating '\0' character). +bool IsInSet(char ch, const char* str) { + return ch != '\0' && strchr(str, ch) != NULL; +} + +// Returns true iff ch belongs to the given classification. Unlike +// similar functions in , these aren't affected by the +// current locale. +bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } +bool IsAsciiPunct(char ch) { + return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); +} +bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } +bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } +bool IsAsciiWordChar(char ch) { + return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_'; +} + +// Returns true iff "\\c" is a supported escape sequence. +bool IsValidEscape(char c) { + return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); +} + +// Returns true iff the given atom (specified by escaped and pattern) +// matches ch. The result is undefined if the atom is invalid. +bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { + if (escaped) { // "\\p" where p is pattern_char. + switch (pattern_char) { + case 'd': return IsAsciiDigit(ch); + case 'D': return !IsAsciiDigit(ch); + case 'f': return ch == '\f'; + case 'n': return ch == '\n'; + case 'r': return ch == '\r'; + case 's': return IsAsciiWhiteSpace(ch); + case 'S': return !IsAsciiWhiteSpace(ch); + case 't': return ch == '\t'; + case 'v': return ch == '\v'; + case 'w': return IsAsciiWordChar(ch); + case 'W': return !IsAsciiWordChar(ch); + } + return IsAsciiPunct(pattern_char) && pattern_char == ch; + } + + return (pattern_char == '.' && ch != '\n') || pattern_char == ch; +} + +// Helper function used by ValidateRegex() to format error messages. +String FormatRegexSyntaxError(const char* regex, int index) { + return (Message() << "Syntax error at index " << index + << " in simple regular expression \"" << regex << "\": ").GetString(); +} + +// Generates non-fatal failures and returns false if regex is invalid; +// otherwise returns true. +bool ValidateRegex(const char* regex) { + if (regex == NULL) { + // TODO(wan@google.com): fix the source file location in the + // assertion failures to match where the regex is used in user + // code. + ADD_FAILURE() << "NULL is not a valid simple regular expression."; + return false; + } + + bool is_valid = true; + + // True iff ?, *, or + can follow the previous atom. + bool prev_repeatable = false; + for (int i = 0; regex[i]; i++) { + if (regex[i] == '\\') { // An escape sequence + i++; + if (regex[i] == '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "'\\' cannot appear at the end."; + return false; + } + + if (!IsValidEscape(regex[i])) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "invalid escape sequence \"\\" << regex[i] << "\"."; + is_valid = false; + } + prev_repeatable = true; + } else { // Not an escape sequence. + const char ch = regex[i]; + + if (ch == '^' && i > 0) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'^' can only appear at the beginning."; + is_valid = false; + } else if (ch == '$' && regex[i + 1] != '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'$' can only appear at the end."; + is_valid = false; + } else if (IsInSet(ch, "()[]{}|")) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' is unsupported."; + is_valid = false; + } else if (IsRepeat(ch) && !prev_repeatable) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' can only follow a repeatable token."; + is_valid = false; + } + + prev_repeatable = !IsInSet(ch, "^$?*+"); + } + } + + return is_valid; +} + +// Matches a repeated regex atom followed by a valid simple regular +// expression. The regex atom is defined as c if escaped is false, +// or \c otherwise. repeat is the repetition meta character (?, *, +// or +). The behavior is undefined if str contains too many +// characters to be indexable by size_t, in which case the test will +// probably time out anyway. We are fine with this limitation as +// std::string has it too. +bool MatchRepetitionAndRegexAtHead( + bool escaped, char c, char repeat, const char* regex, + const char* str) { + const size_t min_count = (repeat == '+') ? 1 : 0; + const size_t max_count = (repeat == '?') ? 1 : + static_cast(-1) - 1; + // We cannot call numeric_limits::max() as it conflicts with the + // max() macro on Windows. + + for (size_t i = 0; i <= max_count; ++i) { + // We know that the atom matches each of the first i characters in str. + if (i >= min_count && MatchRegexAtHead(regex, str + i)) { + // We have enough matches at the head, and the tail matches too. + // Since we only care about *whether* the pattern matches str + // (as opposed to *how* it matches), there is no need to find a + // greedy match. + return true; + } + if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) + return false; + } + return false; +} + +// Returns true iff regex matches a prefix of str. regex must be a +// valid simple regular expression and not start with "^", or the +// result is undefined. +bool MatchRegexAtHead(const char* regex, const char* str) { + if (*regex == '\0') // An empty regex matches a prefix of anything. + return true; + + // "$" only matches the end of a string. Note that regex being + // valid guarantees that there's nothing after "$" in it. + if (*regex == '$') + return *str == '\0'; + + // Is the first thing in regex an escape sequence? + const bool escaped = *regex == '\\'; + if (escaped) + ++regex; + if (IsRepeat(regex[1])) { + // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so + // here's an indirect recursion. It terminates as the regex gets + // shorter in each recursion. + return MatchRepetitionAndRegexAtHead( + escaped, regex[0], regex[1], regex + 2, str); + } else { + // regex isn't empty, isn't "$", and doesn't start with a + // repetition. We match the first atom of regex with the first + // character of str and recurse. + return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && + MatchRegexAtHead(regex + 1, str + 1); + } +} + +// Returns true iff regex matches any substring of str. regex must be +// a valid simple regular expression, or the result is undefined. +// +// The algorithm is recursive, but the recursion depth doesn't exceed +// the regex length, so we won't need to worry about running out of +// stack space normally. In rare cases the time complexity can be +// exponential with respect to the regex length + the string length, +// but usually it's must faster (often close to linear). +bool MatchRegexAnywhere(const char* regex, const char* str) { + if (regex == NULL || str == NULL) + return false; + + if (*regex == '^') + return MatchRegexAtHead(regex + 1, str); + + // A successful match can be anywhere in str. + do { + if (MatchRegexAtHead(regex, str)) + return true; + } while (*str++ != '\0'); + return false; +} + +// Implements the RE class. + +RE::~RE() { + free(const_cast(pattern_)); + free(const_cast(full_pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = full_pattern_ = NULL; + if (regex != NULL) { + pattern_ = posix::StrDup(regex); + } + + is_valid_ = ValidateRegex(regex); + if (!is_valid_) { + // No need to calculate the full pattern when the regex is invalid. + return; + } + + const size_t len = strlen(regex); + // Reserves enough bytes to hold the regular expression used for a + // full match: we need space to prepend a '^', append a '$', and + // terminate the string with '\0'. + char* buffer = static_cast(malloc(len + 3)); + full_pattern_ = buffer; + + if (*regex != '^') + *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. + + // We don't use snprintf or strncpy, as they trigger a warning when + // compiled with VC++ 8.0. + memcpy(buffer, regex, len); + buffer += len; + + if (len == 0 || regex[len - 1] != '$') + *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. + + *buffer = '\0'; +} + +#endif // GTEST_USES_POSIX_RE + +const char kUnknownFile[] = "unknown file"; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { + const char* const file_name = file == NULL ? kUnknownFile : file; + + if (line < 0) { + return String::Format("%s:", file_name).c_str(); + } +#ifdef _MSC_VER + return String::Format("%s(%d):", file_name, line).c_str(); +#else + return String::Format("%s:%d:", file_name, line).c_str(); +#endif // _MSC_VER +} + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +// Note that FormatCompilerIndependentFileLocation() does NOT append colon +// to the file location it produces, unlike FormatFileLocation(). +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( + const char* file, int line) { + const char* const file_name = file == NULL ? kUnknownFile : file; + + if (line < 0) + return file_name; + else + return String::Format("%s:%d", file_name, line).c_str(); +} + + +GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) + : severity_(severity) { + const char* const marker = + severity == GTEST_INFO ? "[ INFO ]" : + severity == GTEST_WARNING ? "[WARNING]" : + severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; + GetStream() << ::std::endl << marker << " " + << FormatFileLocation(file, line).c_str() << ": "; +} + +// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. +GTestLog::~GTestLog() { + GetStream() << ::std::endl; + if (severity_ == GTEST_FATAL) { + fflush(stderr); + posix::Abort(); + } +} +// Disable Microsoft deprecation warnings for POSIX functions called from +// this class (creat, dup, dup2, and close) +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4996) +#endif // _MSC_VER + +#if GTEST_HAS_STREAM_REDIRECTION + +// Object that captures an output stream (stdout/stderr). +class CapturedStream { + public: + // The ctor redirects the stream to a temporary file. + CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { + +# if GTEST_OS_WINDOWS + char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT + char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT + + ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); + const UINT success = ::GetTempFileNameA(temp_dir_path, + "gtest_redir", + 0, // Generate unique file name. + temp_file_path); + GTEST_CHECK_(success != 0) + << "Unable to create a temporary file in " << temp_dir_path; + const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); + GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " + << temp_file_path; + filename_ = temp_file_path; +# else + // There's no guarantee that a test has write access to the + // current directory, so we create the temporary file in the /tmp + // directory instead. + char name_template[] = "/tmp/captured_stream.XXXXXX"; + const int captured_fd = mkstemp(name_template); + filename_ = name_template; +# endif // GTEST_OS_WINDOWS + fflush(NULL); + dup2(captured_fd, fd_); + close(captured_fd); + } + + ~CapturedStream() { + remove(filename_.c_str()); + } + + String GetCapturedString() { + if (uncaptured_fd_ != -1) { + // Restores the original stream. + fflush(NULL); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } + + FILE* const file = posix::FOpen(filename_.c_str(), "r"); + const String content = ReadEntireFile(file); + posix::FClose(file); + return content; + } + + private: + // Reads the entire content of a file as a String. + static String ReadEntireFile(FILE* file); + + // Returns the size (in bytes) of a file. + static size_t GetFileSize(FILE* file); + + const int fd_; // A stream to capture. + int uncaptured_fd_; + // Name of the temporary file holding the stderr output. + ::std::string filename_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); +}; + +// Returns the size (in bytes) of a file. +size_t CapturedStream::GetFileSize(FILE* file) { + fseek(file, 0, SEEK_END); + return static_cast(ftell(file)); +} + +// Reads the entire content of a file as a string. +String CapturedStream::ReadEntireFile(FILE* file) { + const size_t file_size = GetFileSize(file); + char* const buffer = new char[file_size]; + + size_t bytes_last_read = 0; // # of bytes read in the last fread() + size_t bytes_read = 0; // # of bytes read so far + + fseek(file, 0, SEEK_SET); + + // Keeps reading the file until we cannot read further or the + // pre-determined file size is reached. + do { + bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); + bytes_read += bytes_last_read; + } while (bytes_last_read > 0 && bytes_read < file_size); + + const String content(buffer, bytes_read); + delete[] buffer; + + return content; +} + +# ifdef _MSC_VER +# pragma warning(pop) +# endif // _MSC_VER + +static CapturedStream* g_captured_stderr = NULL; +static CapturedStream* g_captured_stdout = NULL; + +// Starts capturing an output stream (stdout/stderr). +void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { + if (*stream != NULL) { + GTEST_LOG_(FATAL) << "Only one " << stream_name + << " capturer can exist at a time."; + } + *stream = new CapturedStream(fd); +} + +// Stops capturing the output stream and returns the captured string. +String GetCapturedStream(CapturedStream** captured_stream) { + const String content = (*captured_stream)->GetCapturedString(); + + delete *captured_stream; + *captured_stream = NULL; + + return content; +} + +// Starts capturing stdout. +void CaptureStdout() { + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() { + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); } + +// Stops capturing stderr and returns the captured string. +String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); } + +#endif // GTEST_HAS_STREAM_REDIRECTION + +#if GTEST_HAS_DEATH_TEST + +// A copy of all command line arguments. Set by InitGoogleTest(). +::std::vector g_argvs; + +// Returns the command line as a vector of strings. +const ::std::vector& GetArgvs() { return g_argvs; } + +#endif // GTEST_HAS_DEATH_TEST + +#if GTEST_OS_WINDOWS_MOBILE +namespace posix { +void Abort() { + DebugBreak(); + TerminateProcess(GetCurrentProcess(), 1); +} +} // namespace posix +#endif // GTEST_OS_WINDOWS_MOBILE + +// Returns the name of the environment variable corresponding to the +// given flag. For example, FlagToEnvVar("foo") will return +// "GTEST_FOO" in the open-source version. +static String FlagToEnvVar(const char* flag) { + const String full_flag = + (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); + + Message env_var; + for (size_t i = 0; i != full_flag.length(); i++) { + env_var << ToUpper(full_flag.c_str()[i]); + } + + return env_var.GetString(); +} + +// Parses 'str' for a 32-bit signed integer. If successful, writes +// the result to *value and returns true; otherwise leaves *value +// unchanged and returns false. +bool ParseInt32(const Message& src_text, const char* str, Int32* value) { + // Parses the environment variable as a decimal integer. + char* end = NULL; + const long long_value = strtol(str, &end, 10); // NOLINT + + // Has strtol() consumed all characters in the string? + if (*end != '\0') { + // No - an invalid character was encountered. + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value \"" << str << "\".\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + // Is the parsed value in the range of an Int32? + const Int32 result = static_cast(long_value); + if (long_value == LONG_MAX || long_value == LONG_MIN || + // The parsed value overflows as a long. (strtol() returns + // LONG_MAX or LONG_MIN when the input overflows.) + result != long_value + // The parsed value overflows as an Int32. + ) { + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value " << str << ", which overflows.\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + *value = result; + return true; +} + +// Reads and returns the Boolean environment variable corresponding to +// the given flag; if it's not set, returns default_value. +// +// The value is considered true iff it's not "0". +bool BoolFromGTestEnv(const char* flag, bool default_value) { + const String env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + return string_value == NULL ? + default_value : strcmp(string_value, "0") != 0; +} + +// Reads and returns a 32-bit integer stored in the environment +// variable corresponding to the given flag; if it isn't set or +// doesn't represent a valid 32-bit integer, returns default_value. +Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { + const String env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + if (string_value == NULL) { + // The environment variable is not set. + return default_value; + } + + Int32 result = default_value; + if (!ParseInt32(Message() << "Environment variable " << env_var, + string_value, &result)) { + printf("The default value %s is used.\n", + (Message() << default_value).GetString().c_str()); + fflush(stdout); + return default_value; + } + + return result; +} + +// Reads and returns the string environment variable corresponding to +// the given flag; if it's not set, returns default_value. +const char* StringFromGTestEnv(const char* flag, const char* default_value) { + const String env_var = FlagToEnvVar(flag); + const char* const value = posix::GetEnv(env_var.c_str()); + return value == NULL ? default_value : value; +} + +} // namespace internal +} // namespace testing +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// It uses the << operator when possible, and prints the bytes in the +// object otherwise. A user can override its behavior for a class +// type Foo by defining either operator<<(::std::ostream&, const Foo&) +// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that +// defines Foo. + +#include +#include +#include // NOLINT +#include + +namespace testing { + +namespace { + +using ::std::ostream; + +#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s. +# define snprintf _snprintf +#elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf. +# define snprintf _snprintf_s +#elif _MSC_VER +# define snprintf _snprintf +#endif // GTEST_OS_WINDOWS_MOBILE + +// Prints a segment of bytes in the given object. +void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, + size_t count, ostream* os) { + char text[5] = ""; + for (size_t i = 0; i != count; i++) { + const size_t j = start + i; + if (i != 0) { + // Organizes the bytes into groups of 2 for easy parsing by + // human. + if ((j % 2) == 0) + *os << ' '; + else + *os << '-'; + } + snprintf(text, sizeof(text), "%02X", obj_bytes[j]); + *os << text; + } +} + +// Prints the bytes in the given value to the given ostream. +void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, + ostream* os) { + // Tells the user how big the object is. + *os << count << "-byte object <"; + + const size_t kThreshold = 132; + const size_t kChunkSize = 64; + // If the object size is bigger than kThreshold, we'll have to omit + // some details by printing only the first and the last kChunkSize + // bytes. + // TODO(wan): let the user control the threshold using a flag. + if (count < kThreshold) { + PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); + } else { + PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); + *os << " ... "; + // Rounds up to 2-byte boundary. + const size_t resume_pos = (count - kChunkSize + 1)/2*2; + PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); + } + *os << ">"; +} + +} // namespace + +namespace internal2 { + +// Delegates to PrintBytesInObjectToImpl() to print the bytes in the +// given object. The delegation simplifies the implementation, which +// uses the << operator and thus is easier done outside of the +// ::testing::internal namespace, which contains a << operator that +// sometimes conflicts with the one in STL. +void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, + ostream* os) { + PrintBytesInObjectToImpl(obj_bytes, count, os); +} + +} // namespace internal2 + +namespace internal { + +// Depending on the value of a char (or wchar_t), we print it in one +// of three formats: +// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), +// - as a hexidecimal escape sequence (e.g. '\x7F'), or +// - as a special escape sequence (e.g. '\r', '\n'). +enum CharFormat { + kAsIs, + kHexEscape, + kSpecialEscape +}; + +// Returns true if c is a printable ASCII character. We test the +// value of c directly instead of calling isprint(), which is buggy on +// Windows Mobile. +inline bool IsPrintableAscii(wchar_t c) { + return 0x20 <= c && c <= 0x7E; +} + +// Prints a wide or narrow char c as a character literal without the +// quotes, escaping it when necessary; returns how c was formatted. +// The template argument UnsignedChar is the unsigned version of Char, +// which is the type of c. +template +static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { + switch (static_cast(c)) { + case L'\0': + *os << "\\0"; + break; + case L'\'': + *os << "\\'"; + break; + case L'\\': + *os << "\\\\"; + break; + case L'\a': + *os << "\\a"; + break; + case L'\b': + *os << "\\b"; + break; + case L'\f': + *os << "\\f"; + break; + case L'\n': + *os << "\\n"; + break; + case L'\r': + *os << "\\r"; + break; + case L'\t': + *os << "\\t"; + break; + case L'\v': + *os << "\\v"; + break; + default: + if (IsPrintableAscii(c)) { + *os << static_cast(c); + return kAsIs; + } else { + *os << String::Format("\\x%X", static_cast(c)); + return kHexEscape; + } + } + return kSpecialEscape; +} + +// Prints a char c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) { + switch (c) { + case L'\'': + *os << "'"; + return kAsIs; + case L'"': + *os << "\\\""; + return kSpecialEscape; + default: + return PrintAsCharLiteralTo(c, os); + } +} + +// Prints a char c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) { + return PrintAsWideStringLiteralTo(static_cast(c), os); +} + +// Prints a wide or narrow character c and its code. '\0' is printed +// as "'\\0'", other unprintable characters are also properly escaped +// using the standard C++ escape sequence. The template argument +// UnsignedChar is the unsigned version of Char, which is the type of c. +template +void PrintCharAndCodeTo(Char c, ostream* os) { + // First, print c as a literal in the most readable form we can find. + *os << ((sizeof(c) > 1) ? "L'" : "'"); + const CharFormat format = PrintAsCharLiteralTo(c, os); + *os << "'"; + + // To aid user debugging, we also print c's code in decimal, unless + // it's 0 (in which case c was printed as '\\0', making the code + // obvious). + if (c == 0) + return; + *os << " (" << String::Format("%d", c).c_str(); + + // For more convenience, we print c's code again in hexidecimal, + // unless c was already printed in the form '\x##' or the code is in + // [1, 9]. + if (format == kHexEscape || (1 <= c && c <= 9)) { + // Do nothing. + } else { + *os << String::Format(", 0x%X", + static_cast(c)).c_str(); + } + *os << ")"; +} + +void PrintTo(unsigned char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} +void PrintTo(signed char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} + +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its code. L'\0' is printed as "L'\\0'". +void PrintTo(wchar_t wc, ostream* os) { + PrintCharAndCodeTo(wc, os); +} + +// Prints the given array of characters to the ostream. +// The array starts at *begin, the length is len, it may include '\0' characters +// and may not be null-terminated. +static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) { + *os << "\""; + bool is_previous_hex = false; + for (size_t index = 0; index < len; ++index) { + const char cur = begin[index]; + if (is_previous_hex && IsXDigit(cur)) { + // Previous character is of '\x..' form and this character can be + // interpreted as another hexadecimal digit in its number. Break string to + // disambiguate. + *os << "\" \""; + } + is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape; + } + *os << "\""; +} + +// Prints a (const) char array of 'len' elements, starting at address 'begin'. +void UniversalPrintArray(const char* begin, size_t len, ostream* os) { + PrintCharsAsStringTo(begin, len, os); +} + +// Prints the given array of wide characters to the ostream. +// The array starts at *begin, the length is len, it may include L'\0' +// characters and may not be null-terminated. +static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len, + ostream* os) { + *os << "L\""; + bool is_previous_hex = false; + for (size_t index = 0; index < len; ++index) { + const wchar_t cur = begin[index]; + if (is_previous_hex && isascii(cur) && IsXDigit(static_cast(cur))) { + // Previous character is of '\x..' form and this character can be + // interpreted as another hexadecimal digit in its number. Break string to + // disambiguate. + *os << "\" L\""; + } + is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape; + } + *os << "\""; +} + +// Prints the given C string to the ostream. +void PrintTo(const char* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, strlen(s), os); + } +} + +// MSVC compiler can be configured to define whar_t as a typedef +// of unsigned short. Defining an overload for const wchar_t* in that case +// would cause pointers to unsigned shorts be printed as wide strings, +// possibly accessing more memory than intended and causing invalid +// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when +// wchar_t is implemented as a native type. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Prints the given wide C string to the ostream. +void PrintTo(const wchar_t* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintWideCharsAsStringTo(s, wcslen(s), os); + } +} +#endif // wchar_t is native + +// Prints a ::string object. +#if GTEST_HAS_GLOBAL_STRING +void PrintStringTo(const ::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +void PrintStringTo(const ::std::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} + +// Prints a ::wstring object. +#if GTEST_HAS_GLOBAL_WSTRING +void PrintWideStringTo(const ::wstring& s, ostream* os) { + PrintWideCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +void PrintWideStringTo(const ::std::wstring& s, ostream* os) { + PrintWideCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_STD_WSTRING + +} // namespace internal + +} // namespace testing +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: mheule@google.com (Markus Heule) +// +// The Google C++ Testing Framework (Google Test) + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +using internal::GetUnitTestImpl; + +// Gets the summary of the failure message by omitting the stack trace +// in it. +internal::String TestPartResult::ExtractSummary(const char* message) { + const char* const stack_trace = strstr(message, internal::kStackTraceMarker); + return stack_trace == NULL ? internal::String(message) : + internal::String(message, stack_trace - message); +} + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { + return os + << result.file_name() << ":" << result.line_number() << ": " + << (result.type() == TestPartResult::kSuccess ? "Success" : + result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : + "Non-fatal failure") << ":\n" + << result.message() << std::endl; +} + +// Appends a TestPartResult to the array. +void TestPartResultArray::Append(const TestPartResult& result) { + array_.push_back(result); +} + +// Returns the TestPartResult at the given index (0-based). +const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { + if (index < 0 || index >= size()) { + printf("\nInvalid index (%d) into TestPartResultArray.\n", index); + internal::posix::Abort(); + } + + return array_[index]; +} + +// Returns the number of TestPartResult objects in the array. +int TestPartResultArray::size() const { + return static_cast(array_.size()); +} + +namespace internal { + +HasNewFatalFailureHelper::HasNewFatalFailureHelper() + : has_new_fatal_failure_(false), + original_reporter_(GetUnitTestImpl()-> + GetTestPartResultReporterForCurrentThread()) { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); +} + +HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( + original_reporter_); +} + +void HasNewFatalFailureHelper::ReportTestPartResult( + const TestPartResult& result) { + if (result.fatally_failed()) + has_new_fatal_failure_ = true; + original_reporter_->ReportTestPartResult(result); +} + +} // namespace internal + +} // namespace testing +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + + +namespace testing { +namespace internal { + +#if GTEST_HAS_TYPED_TEST_P + +// Skips to the first non-space char in str. Returns an empty string if str +// contains only whitespace characters. +static const char* SkipSpaces(const char* str) { + while (IsSpace(*str)) + str++; + return str; +} + +// Verifies that registered_tests match the test names in +// defined_test_names_; returns registered_tests if successful, or +// aborts the program otherwise. +const char* TypedTestCasePState::VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests) { + typedef ::std::set::const_iterator DefinedTestIter; + registered_ = true; + + // Skip initial whitespace in registered_tests since some + // preprocessors prefix stringizied literals with whitespace. + registered_tests = SkipSpaces(registered_tests); + + Message errors; + ::std::set tests; + for (const char* names = registered_tests; names != NULL; + names = SkipComma(names)) { + const String name = GetPrefixUntilComma(names); + if (tests.count(name) != 0) { + errors << "Test " << name << " is listed more than once.\n"; + continue; + } + + bool found = false; + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (name == *it) { + found = true; + break; + } + } + + if (found) { + tests.insert(name); + } else { + errors << "No test named " << name + << " can be found in this test case.\n"; + } + } + + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (tests.count(*it) == 0) { + errors << "You forgot to list test " << *it << ".\n"; + } + } + + const String& errors_str = errors.GetString(); + if (errors_str != "") { + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors_str.c_str()); + fflush(stderr); + posix::Abort(); + } + + return registered_tests; +} + +#endif // GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/gtest-main.cc b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/gtest-main.cc new file mode 100644 index 00000000..4f5bbb28 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/gtest-main.cc @@ -0,0 +1,6 @@ +#include "gtest.h" + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/gtest.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/gtest.h new file mode 100644 index 00000000..3143bd67 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/gtest/gtest.h @@ -0,0 +1,19537 @@ +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for Google Test. It should be +// included by any test program that uses Google Test. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! +// +// Acknowledgment: Google Test borrowed the idea of automatic test +// registration from Barthelemy Dagenais' (barthelemy@prologique.com) +// easyUnit framework. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_H_ + +#include +#include + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares functions and macros used internally by +// Google Test. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan) +// +// Low-level types and utilities for porting Google Test to various +// platforms. They are subject to change without notice. DO NOT USE +// THEM IN USER CODE. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +// The user can define the following macros in the build script to +// control Google Test's behavior. If the user doesn't define a macro +// in this list, Google Test will define it. +// +// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) +// is/isn't available. +// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions +// are enabled. +// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::string, which is different to std::string). +// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::wstring, which is different to std::wstring). +// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular +// expressions are/aren't available. +// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that +// is/isn't available. +// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't +// enabled. +// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that +// std::wstring does/doesn't work (Google Test can +// be used where std::wstring is unavailable). +// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple +// is/isn't available. +// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the +// compiler supports Microsoft's "Structured +// Exception Handling". +// GTEST_HAS_STREAM_REDIRECTION +// - Define it to 1/0 to indicate whether the +// platform supports I/O stream redirection using +// dup() and dup2(). +// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google +// Test's own tr1 tuple implementation should be +// used. Unused when the user sets +// GTEST_HAS_TR1_TUPLE to 0. +// GTEST_LINKED_AS_SHARED_LIBRARY +// - Define to 1 when compiling tests that use +// Google Test as a shared library (known as +// DLL on Windows). +// GTEST_CREATE_SHARED_LIBRARY +// - Define to 1 when compiling Google Test itself +// as a shared library. + +// This header defines the following utilities: +// +// Macros indicating the current platform (defined to 1 if compiled on +// the given platform; otherwise undefined): +// GTEST_OS_AIX - IBM AIX +// GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_HPUX - HP-UX +// GTEST_OS_LINUX - Linux +// GTEST_OS_LINUX_ANDROID - Google Android +// GTEST_OS_MAC - Mac OS X +// GTEST_OS_NACL - Google Native Client (NaCl) +// GTEST_OS_SOLARIS - Sun Solaris +// GTEST_OS_SYMBIAN - Symbian +// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) +// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop +// GTEST_OS_WINDOWS_MINGW - MinGW +// GTEST_OS_WINDOWS_MOBILE - Windows Mobile +// GTEST_OS_ZOS - z/OS +// +// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the +// most stable support. Since core members of the Google Test project +// don't have access to other platforms, support for them may be less +// stable. If you notice any problems on your platform, please notify +// googletestframework@googlegroups.com (patches for fixing them are +// even more welcome!). +// +// Note that it is possible that none of the GTEST_OS_* macros are defined. +// +// Macros indicating available Google Test features (defined to 1 if +// the corresponding feature is supported; otherwise undefined): +// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized +// tests) +// GTEST_HAS_DEATH_TEST - death tests +// GTEST_HAS_PARAM_TEST - value-parameterized tests +// GTEST_HAS_TYPED_TEST - typed tests +// GTEST_HAS_TYPED_TEST_P - type-parameterized tests +// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with +// GTEST_HAS_POSIX_RE (see above) which users can +// define themselves. +// GTEST_USES_SIMPLE_RE - our own simple regex is used; +// the above two are mutually exclusive. +// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). +// +// Macros for basic C++ coding: +// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. +// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a +// variable don't have to be used. +// GTEST_DISALLOW_ASSIGN_ - disables operator=. +// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. +// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. +// +// Synchronization: +// Mutex, MutexLock, ThreadLocal, GetThreadCount() +// - synchronization primitives. +// GTEST_IS_THREADSAFE - defined to 1 to indicate that the above +// synchronization primitives have real implementations +// and Google Test is thread-safe; or 0 otherwise. +// +// Template meta programming: +// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only. +// IteratorTraits - partial implementation of std::iterator_traits, which +// is not available in libCstd when compiled with Sun C++. +// +// Smart pointers: +// scoped_ptr - as in TR2. +// +// Regular expressions: +// RE - a simple regular expression class using the POSIX +// Extended Regular Expression syntax on UNIX-like +// platforms, or a reduced regular exception syntax on +// other platforms, including Windows. +// +// Logging: +// GTEST_LOG_() - logs messages at the specified severity level. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. +// +// Stdout and stderr capturing: +// CaptureStdout() - starts capturing stdout. +// GetCapturedStdout() - stops capturing stdout and returns the captured +// string. +// CaptureStderr() - starts capturing stderr. +// GetCapturedStderr() - stops capturing stderr and returns the captured +// string. +// +// Integer types: +// TypeWithSize - maps an integer to a int type. +// Int32, UInt32, Int64, UInt64, TimeInMillis +// - integers of known sizes. +// BiggestInt - the biggest signed integer type. +// +// Command-line utilities: +// GTEST_FLAG() - references a flag. +// GTEST_DECLARE_*() - declares a flag. +// GTEST_DEFINE_*() - defines a flag. +// GetArgvs() - returns the command line as a vector of strings. +// +// Environment variable utilities: +// GetEnv() - gets the value of an environment variable. +// BoolFromGTestEnv() - parses a bool environment variable. +// Int32FromGTestEnv() - parses an Int32 environment variable. +// StringFromGTestEnv() - parses a string environment variable. + +#include // for isspace, etc +#include // for ptrdiff_t +#include +#include +#include +#ifndef _WIN32_WCE +# include +# include +#endif // !_WIN32_WCE + +#include // NOLINT +#include // NOLINT +#include // NOLINT + +#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" +#define GTEST_FLAG_PREFIX_ "gtest_" +#define GTEST_FLAG_PREFIX_DASH_ "gtest-" +#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" +#define GTEST_NAME_ "Google Test" +#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/" + +// Determines the version of gcc that is used to compile this. +#ifdef __GNUC__ +// 40302 means version 4.3.2. +# define GTEST_GCC_VER_ \ + (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) +#endif // __GNUC__ + +// Determines the platform on which Google Test is compiled. +#ifdef __CYGWIN__ +# define GTEST_OS_CYGWIN 1 +#elif defined __SYMBIAN32__ +# define GTEST_OS_SYMBIAN 1 +#elif defined _WIN32 +# define GTEST_OS_WINDOWS 1 +# ifdef _WIN32_WCE +# define GTEST_OS_WINDOWS_MOBILE 1 +# elif defined(__MINGW__) || defined(__MINGW32__) +# define GTEST_OS_WINDOWS_MINGW 1 +# else +# define GTEST_OS_WINDOWS_DESKTOP 1 +# endif // _WIN32_WCE +#elif defined __APPLE__ +# define GTEST_OS_MAC 1 +#elif defined __linux__ +# define GTEST_OS_LINUX 1 +# ifdef ANDROID +# define GTEST_OS_LINUX_ANDROID 1 +# endif // ANDROID +#elif defined __MVS__ +# define GTEST_OS_ZOS 1 +#elif defined(__sun) && defined(__SVR4) +# define GTEST_OS_SOLARIS 1 +#elif defined(_AIX) +# define GTEST_OS_AIX 1 +#elif defined(__hpux) +# define GTEST_OS_HPUX 1 +#elif defined __native_client__ +# define GTEST_OS_NACL 1 +#endif // __CYGWIN__ + +// Brings in definitions for functions used in the testing::internal::posix +// namespace (read, write, close, chdir, isatty, stat). We do not currently +// use them on Windows Mobile. +#if !GTEST_OS_WINDOWS +// This assumes that non-Windows OSes provide unistd.h. For OSes where this +// is not the case, we need to include headers that provide the functions +// mentioned above. +# include +# if !GTEST_OS_NACL +// TODO(vladl@google.com): Remove this condition when Native Client SDK adds +// strings.h (tracked in +// http://code.google.com/p/nativeclient/issues/detail?id=1175). +# include // Native Client doesn't provide strings.h. +# endif +#elif !GTEST_OS_WINDOWS_MOBILE +# include +# include +#endif + +// Defines this to true iff Google Test can use POSIX regular expressions. +#ifndef GTEST_HAS_POSIX_RE +# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) +#endif + +#if GTEST_HAS_POSIX_RE + +// On some platforms, needs someone to define size_t, and +// won't compile otherwise. We can #include it here as we already +// included , which is guaranteed to define size_t through +// . +# include // NOLINT + +# define GTEST_USES_POSIX_RE 1 + +#elif GTEST_OS_WINDOWS + +// is not available on Windows. Use our own simple regex +// implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#else + +// may not be available on this platform. Use our own +// simple regex implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#endif // GTEST_HAS_POSIX_RE + +#ifndef GTEST_HAS_EXCEPTIONS +// The user didn't tell us whether exceptions are enabled, so we need +// to figure it out. +# if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +// macro to enable exceptions, so we'll do the same. +// Assumes that exceptions are enabled by default. +# ifndef _HAS_EXCEPTIONS +# define _HAS_EXCEPTIONS 1 +# endif // _HAS_EXCEPTIONS +# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS +# elif defined(__GNUC__) && __EXCEPTIONS +// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__SUNPRO_CC) +// Sun Pro CC supports exceptions. However, there is no compile-time way of +// detecting whether they are enabled or not. Therefore, we assume that +// they are enabled unless the user tells us otherwise. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__IBMCPP__) && __EXCEPTIONS +// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__HP_aCC) +// Exception handling is in effect by default in HP aCC compiler. It has to +// be turned of by +noeh compiler option if desired. +# define GTEST_HAS_EXCEPTIONS 1 +# else +// For other compilers, we assume exceptions are disabled to be +// conservative. +# define GTEST_HAS_EXCEPTIONS 0 +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +#endif // GTEST_HAS_EXCEPTIONS + +#if !defined(GTEST_HAS_STD_STRING) +// Even though we don't use this macro any longer, we keep it in case +// some clients still depend on it. +# define GTEST_HAS_STD_STRING 1 +#elif !GTEST_HAS_STD_STRING +// The user told us that ::std::string isn't available. +# error "Google Test cannot be used where ::std::string isn't available." +#endif // !defined(GTEST_HAS_STD_STRING) + +#ifndef GTEST_HAS_GLOBAL_STRING +// The user didn't tell us whether ::string is available, so we need +// to figure it out. + +# define GTEST_HAS_GLOBAL_STRING 0 + +#endif // GTEST_HAS_GLOBAL_STRING + +#ifndef GTEST_HAS_STD_WSTRING +// The user didn't tell us whether ::std::wstring is available, so we need +// to figure it out. +// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring +// is available. + +// Cygwin 1.7 and below doesn't support ::std::wstring. +// Solaris' libc++ doesn't support it either. Android has +// no support for it at least as recent as Froyo (2.2). +# define GTEST_HAS_STD_WSTRING \ + (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS)) + +#endif // GTEST_HAS_STD_WSTRING + +#ifndef GTEST_HAS_GLOBAL_WSTRING +// The user didn't tell us whether ::wstring is available, so we need +// to figure it out. +# define GTEST_HAS_GLOBAL_WSTRING \ + (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Determines whether RTTI is available. +#ifndef GTEST_HAS_RTTI +// The user didn't tell us whether RTTI is enabled, so we need to +// figure it out. + +# ifdef _MSC_VER + +# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled. +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) + +# ifdef __GXX_RTTI +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif // __GXX_RTTI + +// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if +// both the typeid and dynamic_cast features are present. +# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) + +# ifdef __RTTI_ALL__ +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +# else + +// For all other compilers, we assume RTTI is enabled. +# define GTEST_HAS_RTTI 1 + +# endif // _MSC_VER + +#endif // GTEST_HAS_RTTI + +// It's this header's responsibility to #include when RTTI +// is enabled. +#if GTEST_HAS_RTTI +# include +#endif + +// Determines whether Google Test can use the pthreads library. +#ifndef GTEST_HAS_PTHREAD +// The user didn't tell us explicitly, so we assume pthreads support is +// available on Linux and Mac. +// +// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 +// to your compiler flags. +# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX) +#endif // GTEST_HAS_PTHREAD + +#if GTEST_HAS_PTHREAD +// gtest-port.h guarantees to #include when GTEST_HAS_PTHREAD is +// true. +# include // NOLINT + +// For timespec and nanosleep, used below. +# include // NOLINT +#endif + +// Determines whether Google Test can use tr1/tuple. You can define +// this macro to 0 to prevent Google Test from using tuple (any +// feature depending on tuple with be disabled in this mode). +#ifndef GTEST_HAS_TR1_TUPLE +// The user didn't tell us not to do it, so we assume it's OK. +# define GTEST_HAS_TR1_TUPLE 1 +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether Google Test's own tr1 tuple implementation +// should be used. +#ifndef GTEST_USE_OWN_TR1_TUPLE +// The user didn't tell us, so we need to figure it out. + +// We use our own TR1 tuple if we aren't sure the user has an +// implementation of it already. At this time, GCC 4.0.0+ and MSVC +// 2010 are the only mainstream compilers that come with a TR1 tuple +// implementation. NVIDIA's CUDA NVCC compiler pretends to be GCC by +// defining __GNUC__ and friends, but cannot compile GCC's tuple +// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB +// Feature Pack download, which we cannot assume the user has. +# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \ + || _MSC_VER >= 1600 +# define GTEST_USE_OWN_TR1_TUPLE 0 +# else +# define GTEST_USE_OWN_TR1_TUPLE 1 +# endif + +#endif // GTEST_USE_OWN_TR1_TUPLE + +// To avoid conditional compilation everywhere, we make it +// gtest-port.h's responsibility to #include the header implementing +// tr1/tuple. +#if GTEST_HAS_TR1_TUPLE + +# if GTEST_USE_OWN_TR1_TUPLE +// This file was GENERATED by a script. DO NOT EDIT BY HAND!!! + +// Copyright 2009 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Implements a subset of TR1 tuple needed by Google Test and Google Mock. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ + +#include // For ::std::pair. + +// The compiler used in Symbian has a bug that prevents us from declaring the +// tuple template as a friend (it complains that tuple is redefined). This +// hack bypasses the bug by declaring the members that should otherwise be +// private as public. +// Sun Studio versions < 12 also have the above bug. +#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: +#else +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ + template friend class tuple; \ + private: +#endif + +// GTEST_n_TUPLE_(T) is the type of an n-tuple. +#define GTEST_0_TUPLE_(T) tuple<> +#define GTEST_1_TUPLE_(T) tuple +#define GTEST_2_TUPLE_(T) tuple +#define GTEST_3_TUPLE_(T) tuple +#define GTEST_4_TUPLE_(T) tuple +#define GTEST_5_TUPLE_(T) tuple +#define GTEST_6_TUPLE_(T) tuple +#define GTEST_7_TUPLE_(T) tuple +#define GTEST_8_TUPLE_(T) tuple +#define GTEST_9_TUPLE_(T) tuple +#define GTEST_10_TUPLE_(T) tuple + +// GTEST_n_TYPENAMES_(T) declares a list of n typenames. +#define GTEST_0_TYPENAMES_(T) +#define GTEST_1_TYPENAMES_(T) typename T##0 +#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1 +#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2 +#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3 +#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4 +#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5 +#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6 +#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, typename T##7 +#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8 +#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8, typename T##9 + +// In theory, defining stuff in the ::std namespace is undefined +// behavior. We can do this as we are playing the role of a standard +// library vendor. +namespace std { +namespace tr1 { + +template +class tuple; + +// Anything in namespace gtest_internal is Google Test's INTERNAL +// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. +namespace gtest_internal { + +// ByRef::type is T if T is a reference; otherwise it's const T&. +template +struct ByRef { typedef const T& type; }; // NOLINT +template +struct ByRef { typedef T& type; }; // NOLINT + +// A handy wrapper for ByRef. +#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type + +// AddRef::type is T if T is a reference; otherwise it's T&. This +// is the same as tr1::add_reference::type. +template +struct AddRef { typedef T& type; }; // NOLINT +template +struct AddRef { typedef T& type; }; // NOLINT + +// A handy wrapper for AddRef. +#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type + +// A helper for implementing get(). +template class Get; + +// A helper for implementing tuple_element. kIndexValid is true +// iff k < the number of fields in tuple type T. +template +struct TupleElement; + +template +struct TupleElement { typedef T0 type; }; + +template +struct TupleElement { typedef T1 type; }; + +template +struct TupleElement { typedef T2 type; }; + +template +struct TupleElement { typedef T3 type; }; + +template +struct TupleElement { typedef T4 type; }; + +template +struct TupleElement { typedef T5 type; }; + +template +struct TupleElement { typedef T6 type; }; + +template +struct TupleElement { typedef T7 type; }; + +template +struct TupleElement { typedef T8 type; }; + +template +struct TupleElement { typedef T9 type; }; + +} // namespace gtest_internal + +template <> +class tuple<> { + public: + tuple() {} + tuple(const tuple& /* t */) {} + tuple& operator=(const tuple& /* t */) { return *this; } +}; + +template +class GTEST_1_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} + + tuple(const tuple& t) : f0_(t.f0_) {} + + template + tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_1_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { + f0_ = t.f0_; + return *this; + } + + T0 f0_; +}; + +template +class GTEST_2_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0), + f1_(f1) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {} + + template + tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} + template + tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_2_TUPLE_(U)& t) { + return CopyFrom(t); + } + template + tuple& operator=(const ::std::pair& p) { + f0_ = p.first; + f1_ = p.second; + return *this; + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + return *this; + } + + T0 f0_; + T1 f1_; +}; + +template +class GTEST_3_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + template + tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_3_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; +}; + +template +class GTEST_4_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} + + template + tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_4_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; +}; + +template +class GTEST_5_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, + GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_) {} + + template + tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_5_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; +}; + +template +class GTEST_6_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_) {} + + template + tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_6_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; +}; + +template +class GTEST_7_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + template + tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_7_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; +}; + +template +class GTEST_8_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, + GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + template + tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_8_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; +}; + +template +class GTEST_9_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7), f8_(f8) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + template + tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_9_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; +}; + +template +class tuple { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), + f9_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} + + template + tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), + f9_(t.f9_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_10_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + f9_ = t.f9_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; + T9 f9_; +}; + +// 6.1.3.2 Tuple creation functions. + +// Known limitations: we don't support passing an +// std::tr1::reference_wrapper to make_tuple(). And we don't +// implement tie(). + +inline tuple<> make_tuple() { return tuple<>(); } + +template +inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { + return GTEST_1_TUPLE_(T)(f0); +} + +template +inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { + return GTEST_2_TUPLE_(T)(f0, f1); +} + +template +inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) { + return GTEST_3_TUPLE_(T)(f0, f1, f2); +} + +template +inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3) { + return GTEST_4_TUPLE_(T)(f0, f1, f2, f3); +} + +template +inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4) { + return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4); +} + +template +inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5) { + return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5); +} + +template +inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6) { + return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6); +} + +template +inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) { + return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7); +} + +template +inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8) { + return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8); +} + +template +inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8, const T9& f9) { + return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); +} + +// 6.1.3.3 Tuple helper classes. + +template struct tuple_size; + +template +struct tuple_size { static const int value = 0; }; + +template +struct tuple_size { static const int value = 1; }; + +template +struct tuple_size { static const int value = 2; }; + +template +struct tuple_size { static const int value = 3; }; + +template +struct tuple_size { static const int value = 4; }; + +template +struct tuple_size { static const int value = 5; }; + +template +struct tuple_size { static const int value = 6; }; + +template +struct tuple_size { static const int value = 7; }; + +template +struct tuple_size { static const int value = 8; }; + +template +struct tuple_size { static const int value = 9; }; + +template +struct tuple_size { static const int value = 10; }; + +template +struct tuple_element { + typedef typename gtest_internal::TupleElement< + k < (tuple_size::value), k, Tuple>::type type; +}; + +#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type + +// 6.1.3.4 Element access. + +namespace gtest_internal { + +template <> +class Get<0> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + Field(Tuple& t) { return t.f0_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + ConstField(const Tuple& t) { return t.f0_; } +}; + +template <> +class Get<1> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + Field(Tuple& t) { return t.f1_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + ConstField(const Tuple& t) { return t.f1_; } +}; + +template <> +class Get<2> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + Field(Tuple& t) { return t.f2_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + ConstField(const Tuple& t) { return t.f2_; } +}; + +template <> +class Get<3> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + Field(Tuple& t) { return t.f3_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + ConstField(const Tuple& t) { return t.f3_; } +}; + +template <> +class Get<4> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + Field(Tuple& t) { return t.f4_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + ConstField(const Tuple& t) { return t.f4_; } +}; + +template <> +class Get<5> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + Field(Tuple& t) { return t.f5_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + ConstField(const Tuple& t) { return t.f5_; } +}; + +template <> +class Get<6> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + Field(Tuple& t) { return t.f6_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + ConstField(const Tuple& t) { return t.f6_; } +}; + +template <> +class Get<7> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + Field(Tuple& t) { return t.f7_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + ConstField(const Tuple& t) { return t.f7_; } +}; + +template <> +class Get<8> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + Field(Tuple& t) { return t.f8_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + ConstField(const Tuple& t) { return t.f8_; } +}; + +template <> +class Get<9> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + Field(Tuple& t) { return t.f9_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + ConstField(const Tuple& t) { return t.f9_; } +}; + +} // namespace gtest_internal + +template +GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::Field(t); +} + +template +GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(const GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::ConstField(t); +} + +// 6.1.3.5 Relational operators + +// We only implement == and !=, as we don't have a need for the rest yet. + +namespace gtest_internal { + +// SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the +// first k fields of t1 equals the first k fields of t2. +// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if +// k1 != k2. +template +struct SameSizeTuplePrefixComparator; + +template <> +struct SameSizeTuplePrefixComparator<0, 0> { + template + static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { + return true; + } +}; + +template +struct SameSizeTuplePrefixComparator { + template + static bool Eq(const Tuple1& t1, const Tuple2& t2) { + return SameSizeTuplePrefixComparator::Eq(t1, t2) && + ::std::tr1::get(t1) == ::std::tr1::get(t2); + } +}; + +} // namespace gtest_internal + +template +inline bool operator==(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { + return gtest_internal::SameSizeTuplePrefixComparator< + tuple_size::value, + tuple_size::value>::Eq(t, u); +} + +template +inline bool operator!=(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { return !(t == u); } + +// 6.1.4 Pairs. +// Unimplemented. + +} // namespace tr1 +} // namespace std + +#undef GTEST_0_TUPLE_ +#undef GTEST_1_TUPLE_ +#undef GTEST_2_TUPLE_ +#undef GTEST_3_TUPLE_ +#undef GTEST_4_TUPLE_ +#undef GTEST_5_TUPLE_ +#undef GTEST_6_TUPLE_ +#undef GTEST_7_TUPLE_ +#undef GTEST_8_TUPLE_ +#undef GTEST_9_TUPLE_ +#undef GTEST_10_TUPLE_ + +#undef GTEST_0_TYPENAMES_ +#undef GTEST_1_TYPENAMES_ +#undef GTEST_2_TYPENAMES_ +#undef GTEST_3_TYPENAMES_ +#undef GTEST_4_TYPENAMES_ +#undef GTEST_5_TYPENAMES_ +#undef GTEST_6_TYPENAMES_ +#undef GTEST_7_TYPENAMES_ +#undef GTEST_8_TYPENAMES_ +#undef GTEST_9_TYPENAMES_ +#undef GTEST_10_TYPENAMES_ + +#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ +#undef GTEST_BY_REF_ +#undef GTEST_ADD_REF_ +#undef GTEST_TUPLE_ELEMENT_ + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +# elif GTEST_OS_SYMBIAN + +// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to +// use STLport's tuple implementation, which unfortunately doesn't +// work as the copy of STLport distributed with Symbian is incomplete. +// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to +// use its own tuple implementation. +# ifdef BOOST_HAS_TR1_TUPLE +# undef BOOST_HAS_TR1_TUPLE +# endif // BOOST_HAS_TR1_TUPLE + +// This prevents , which defines +// BOOST_HAS_TR1_TUPLE, from being #included by Boost's . +# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED +# include + +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) +// GCC 4.0+ implements tr1/tuple in the header. This does +// not conform to the TR1 spec, which requires the header to be . + +# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 +// Until version 4.3.2, gcc has a bug that causes , +// which is #included by , to not compile when RTTI is +// disabled. _TR1_FUNCTIONAL is the header guard for +// . Hence the following #define is a hack to prevent +// from being included. +# define _TR1_FUNCTIONAL 1 +# include +# undef _TR1_FUNCTIONAL // Allows the user to #include + // if he chooses to. +# else +# include // NOLINT +# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 + +# else +// If the compiler is not GCC 4.0+, we assume the user is using a +// spec-conforming TR1 implementation. +# include // NOLINT +# endif // GTEST_USE_OWN_TR1_TUPLE + +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether clone(2) is supported. +// Usually it will only be available on Linux, excluding +// Linux on the Itanium architecture. +// Also see http://linux.die.net/man/2/clone. +#ifndef GTEST_HAS_CLONE +// The user didn't tell us, so we need to figure it out. + +# if GTEST_OS_LINUX && !defined(__ia64__) +# define GTEST_HAS_CLONE 1 +# else +# define GTEST_HAS_CLONE 0 +# endif // GTEST_OS_LINUX && !defined(__ia64__) + +#endif // GTEST_HAS_CLONE + +// Determines whether to support stream redirection. This is used to test +// output correctness and to implement death tests. +#ifndef GTEST_HAS_STREAM_REDIRECTION +// By default, we assume that stream redirection is supported on all +// platforms except known mobile ones. +# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN +# define GTEST_HAS_STREAM_REDIRECTION 0 +# else +# define GTEST_HAS_STREAM_REDIRECTION 1 +# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN +#endif // GTEST_HAS_STREAM_REDIRECTION + +// Determines whether to support death tests. +// Google Test does not support death tests for VC 7.1 and earlier as +// abort() in a VC 7.1 application compiled as GUI in debug config +// pops up a dialog window that cannot be suppressed programmatically. +#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ + GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX) +# define GTEST_HAS_DEATH_TEST 1 +# include // NOLINT +#endif + +// We don't support MSVC 7.1 with exceptions disabled now. Therefore +// all the compilers we care about are adequate for supporting +// value-parameterized tests. +#define GTEST_HAS_PARAM_TEST 1 + +// Determines whether to support type-driven tests. + +// Typed tests need and variadic macros, which GCC, VC++ 8.0, +// Sun Pro CC, IBM Visual Age, and HP aCC support. +#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ + defined(__IBMCPP__) || defined(__HP_aCC) +# define GTEST_HAS_TYPED_TEST 1 +# define GTEST_HAS_TYPED_TEST_P 1 +#endif + +// Determines whether to support Combine(). This only makes sense when +// value-parameterized tests are enabled. The implementation doesn't +// work on Sun Studio since it doesn't understand templated conversion +// operators. +#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) +# define GTEST_HAS_COMBINE 1 +#endif + +// Determines whether the system compiler uses UTF-16 for encoding wide strings. +#define GTEST_WIDE_STRING_USES_UTF16_ \ + (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) + +// Determines whether test results can be streamed to a socket. +#if GTEST_OS_LINUX +# define GTEST_CAN_STREAM_RESULTS_ 1 +#endif + +// Defines some utility macros. + +// The GNU compiler emits a warning if nested "if" statements are followed by +// an "else" statement and braces are not used to explicitly disambiguate the +// "else" binding. This leads to problems with code like: +// +// if (gate) +// ASSERT_*(condition) << "Some message"; +// +// The "switch (0) case 0:" idiom is used to suppress this. +#ifdef __INTEL_COMPILER +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ +#else +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT +#endif + +// Use this annotation at the end of a struct/class definition to +// prevent the compiler from optimizing away instances that are never +// used. This is useful when all interesting logic happens inside the +// c'tor and / or d'tor. Example: +// +// struct Foo { +// Foo() { ... } +// } GTEST_ATTRIBUTE_UNUSED_; +// +// Also use it after a variable or parameter declaration to tell the +// compiler the variable/parameter does not have to be used. +#if defined(__GNUC__) && !defined(COMPILER_ICC) +# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) +#else +# define GTEST_ATTRIBUTE_UNUSED_ +#endif + +// A macro to disallow operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_ASSIGN_(type)\ + void operator=(type const &) + +// A macro to disallow copy constructor and operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ + type(type const &);\ + GTEST_DISALLOW_ASSIGN_(type) + +// Tell the compiler to warn about unused return values for functions declared +// with this macro. The macro should be used on function declarations +// following the argument list: +// +// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; +#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC) +# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) +#else +# define GTEST_MUST_USE_RESULT_ +#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC + +// Determine whether the compiler supports Microsoft's Structured Exception +// Handling. This is supported by several Windows compilers but generally +// does not exist on any other system. +#ifndef GTEST_HAS_SEH +// The user didn't tell us, so we need to figure it out. + +# if defined(_MSC_VER) || defined(__BORLANDC__) +// These two compilers are known to support SEH. +# define GTEST_HAS_SEH 1 +# else +// Assume no SEH. +# define GTEST_HAS_SEH 0 +# endif + +#endif // GTEST_HAS_SEH + +#ifdef _MSC_VER + +# if GTEST_LINKED_AS_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllimport) +# elif GTEST_CREATE_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllexport) +# endif + +#endif // _MSC_VER + +#ifndef GTEST_API_ +# define GTEST_API_ +#endif + +#ifdef __GNUC__ +// Ask the compiler to never inline a given function. +# define GTEST_NO_INLINE_ __attribute__((noinline)) +#else +# define GTEST_NO_INLINE_ +#endif + +namespace testing { + +class Message; + +namespace internal { + +class String; + +// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +template +struct CompileAssert { +}; + +#define GTEST_COMPILE_ASSERT_(expr, msg) \ + typedef ::testing::internal::CompileAssert<(bool(expr))> \ + msg[bool(expr) ? 1 : -1] + +// Implementation details of GTEST_COMPILE_ASSERT_: +// +// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// GTEST_COMPILE_ASSERT_(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h. +// +// This template is declared, but intentionally undefined. +template +struct StaticAssertTypeEqHelper; + +template +struct StaticAssertTypeEqHelper {}; + +#if GTEST_HAS_GLOBAL_STRING +typedef ::string string; +#else +typedef ::std::string string; +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_GLOBAL_WSTRING +typedef ::wstring wstring; +#elif GTEST_HAS_STD_WSTRING +typedef ::std::wstring wstring; +#endif // GTEST_HAS_GLOBAL_WSTRING + +// A helper for suppressing warnings on constant condition. It just +// returns 'condition'. +GTEST_API_ bool IsTrue(bool condition); + +// Defines scoped_ptr. + +// This implementation of scoped_ptr is PARTIAL - it only contains +// enough stuff to satisfy Google Test's need. +template +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T* p = NULL) : ptr_(p) {} + ~scoped_ptr() { reset(); } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + T* get() const { return ptr_; } + + T* release() { + T* const ptr = ptr_; + ptr_ = NULL; + return ptr; + } + + void reset(T* p = NULL) { + if (p != ptr_) { + if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. + delete ptr_; + } + ptr_ = p; + } + } + private: + T* ptr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); +}; + +// Defines RE. + +// A simple C++ wrapper for . It uses the POSIX Extended +// Regular Expression syntax. +class GTEST_API_ RE { + public: + // A copy constructor is required by the Standard to initialize object + // references from r-values. + RE(const RE& other) { Init(other.pattern()); } + + // Constructs an RE from a string. + RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + + RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT + +#endif // GTEST_HAS_GLOBAL_STRING + + RE(const char* regex) { Init(regex); } // NOLINT + ~RE(); + + // Returns the string representation of the regex. + const char* pattern() const { return pattern_; } + + // FullMatch(str, re) returns true iff regular expression re matches + // the entire str. + // PartialMatch(str, re) returns true iff regular expression re + // matches a substring of str (including str itself). + // + // TODO(wan@google.com): make FullMatch() and PartialMatch() work + // when str contains NUL characters. + static bool FullMatch(const ::std::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::std::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#if GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const ::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#endif // GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const char* str, const RE& re); + static bool PartialMatch(const char* str, const RE& re); + + private: + void Init(const char* regex); + + // We use a const char* instead of a string, as Google Test may be used + // where string is not available. We also do not use Google Test's own + // String type here, in order to simplify dependencies between the + // files. + const char* pattern_; + bool is_valid_; + +#if GTEST_USES_POSIX_RE + + regex_t full_regex_; // For FullMatch(). + regex_t partial_regex_; // For PartialMatch(). + +#else // GTEST_USES_SIMPLE_RE + + const char* full_pattern_; // For FullMatch(); + +#endif + + GTEST_DISALLOW_ASSIGN_(RE); +}; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file, + int line); + +// Defines logging utilities: +// GTEST_LOG_(severity) - logs messages at the specified severity level. The +// message itself is streamed into the macro. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. + +enum GTestLogSeverity { + GTEST_INFO, + GTEST_WARNING, + GTEST_ERROR, + GTEST_FATAL +}; + +// Formats log entry severity, provides a stream object for streaming the +// log message, and terminates the message with a newline when going out of +// scope. +class GTEST_API_ GTestLog { + public: + GTestLog(GTestLogSeverity severity, const char* file, int line); + + // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. + ~GTestLog(); + + ::std::ostream& GetStream() { return ::std::cerr; } + + private: + const GTestLogSeverity severity_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); +}; + +#define GTEST_LOG_(severity) \ + ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ + __FILE__, __LINE__).GetStream() + +inline void LogToStderr() {} +inline void FlushInfoLog() { fflush(NULL); } + +// INTERNAL IMPLEMENTATION - DO NOT USE. +// +// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition +// is not satisfied. +// Synopsys: +// GTEST_CHECK_(boolean_condition); +// or +// GTEST_CHECK_(boolean_condition) << "Additional message"; +// +// This checks the condition and if the condition is not satisfied +// it prints message about the condition violation, including the +// condition itself, plus additional message streamed into it, if any, +// and then it aborts the program. It aborts the program irrespective of +// whether it is built in the debug mode or not. +#define GTEST_CHECK_(condition) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::IsTrue(condition)) \ + ; \ + else \ + GTEST_LOG_(FATAL) << "Condition " #condition " failed. " + +// An all-mode assert to verify that the given POSIX-style function +// call returns 0 (indicating success). Known limitation: this +// doesn't expand to a balanced 'if' statement, so enclose the macro +// in {} if you need to use it as the only statement in an 'if' +// branch. +#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ + if (const int gtest_error = (posix_call)) \ + GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ + << gtest_error + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Use ImplicitCast_ as a safe version of static_cast for upcasting in +// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a +// const Foo*). When you use ImplicitCast_, the compiler checks that +// the cast is safe. Such explicit ImplicitCast_s are necessary in +// surprisingly many situations where C++ demands an exact type match +// instead of an argument type convertable to a target type. +// +// The syntax for using ImplicitCast_ is the same as for static_cast: +// +// ImplicitCast_(expr) +// +// ImplicitCast_ would have been part of the C++ standard library, +// but the proposal was submitted too late. It will probably make +// its way into the language in the future. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., implicit_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template +inline To ImplicitCast_(To x) { return x; } + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., down_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template // use like this: DownCast_(foo); +inline To DownCast_(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + const To to = NULL; + ::testing::internal::ImplicitCast_(to); + } + +#if GTEST_HAS_RTTI + // RTTI: debug mode only! + GTEST_CHECK_(f == NULL || dynamic_cast(f) != NULL); +#endif + return static_cast(f); +} + +// Downcasts the pointer of type Base to Derived. +// Derived must be a subclass of Base. The parameter MUST +// point to a class of type Derived, not any subclass of it. +// When RTTI is available, the function performs a runtime +// check to enforce this. +template +Derived* CheckedDowncastToActualType(Base* base) { +#if GTEST_HAS_RTTI + GTEST_CHECK_(typeid(*base) == typeid(Derived)); + return dynamic_cast(base); // NOLINT +#else + return static_cast(base); // Poor man's downcast. +#endif +} + +#if GTEST_HAS_STREAM_REDIRECTION + +// Defines the stderr capturer: +// CaptureStdout - starts capturing stdout. +// GetCapturedStdout - stops capturing stdout and returns the captured string. +// CaptureStderr - starts capturing stderr. +// GetCapturedStderr - stops capturing stderr and returns the captured string. +// +GTEST_API_ void CaptureStdout(); +GTEST_API_ String GetCapturedStdout(); +GTEST_API_ void CaptureStderr(); +GTEST_API_ String GetCapturedStderr(); + +#endif // GTEST_HAS_STREAM_REDIRECTION + + +#if GTEST_HAS_DEATH_TEST + +// A copy of all command line arguments. Set by InitGoogleTest(). +extern ::std::vector g_argvs; + +// GTEST_HAS_DEATH_TEST implies we have ::std::string. +const ::std::vector& GetArgvs(); + +#endif // GTEST_HAS_DEATH_TEST + +// Defines synchronization primitives. + +#if GTEST_HAS_PTHREAD + +// Sleeps for (roughly) n milli-seconds. This function is only for +// testing Google Test's own constructs. Don't use it in user tests, +// either directly or indirectly. +inline void SleepMilliseconds(int n) { + const timespec time = { + 0, // 0 seconds. + n * 1000L * 1000L, // And n ms. + }; + nanosleep(&time, NULL); +} + +// Allows a controller thread to pause execution of newly created +// threads until notified. Instances of this class must be created +// and destroyed in the controller thread. +// +// This class is only for testing Google Test's own constructs. Do not +// use it in user tests, either directly or indirectly. +class Notification { + public: + Notification() : notified_(false) {} + + // Notifies all threads created with this notification to start. Must + // be called from the controller thread. + void Notify() { notified_ = true; } + + // Blocks until the controller thread notifies. Must be called from a test + // thread. + void WaitForNotification() { + while(!notified_) { + SleepMilliseconds(10); + } + } + + private: + volatile bool notified_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); +}; + +// As a C-function, ThreadFuncWithCLinkage cannot be templated itself. +// Consequently, it cannot select a correct instantiation of ThreadWithParam +// in order to call its Run(). Introducing ThreadWithParamBase as a +// non-templated base class for ThreadWithParam allows us to bypass this +// problem. +class ThreadWithParamBase { + public: + virtual ~ThreadWithParamBase() {} + virtual void Run() = 0; +}; + +// pthread_create() accepts a pointer to a function type with the C linkage. +// According to the Standard (7.5/1), function types with different linkages +// are different even if they are otherwise identical. Some compilers (for +// example, SunStudio) treat them as different types. Since class methods +// cannot be defined with C-linkage we need to define a free C-function to +// pass into pthread_create(). +extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { + static_cast(thread)->Run(); + return NULL; +} + +// Helper class for testing Google Test's multi-threading constructs. +// To use it, write: +// +// void ThreadFunc(int param) { /* Do things with param */ } +// Notification thread_can_start; +// ... +// // The thread_can_start parameter is optional; you can supply NULL. +// ThreadWithParam thread(&ThreadFunc, 5, &thread_can_start); +// thread_can_start.Notify(); +// +// These classes are only for testing Google Test's own constructs. Do +// not use them in user tests, either directly or indirectly. +template +class ThreadWithParam : public ThreadWithParamBase { + public: + typedef void (*UserThreadFunc)(T); + + ThreadWithParam( + UserThreadFunc func, T param, Notification* thread_can_start) + : func_(func), + param_(param), + thread_can_start_(thread_can_start), + finished_(false) { + ThreadWithParamBase* const base = this; + // The thread can be created only after all fields except thread_ + // have been initialized. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); + } + ~ThreadWithParam() { Join(); } + + void Join() { + if (!finished_) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); + finished_ = true; + } + } + + virtual void Run() { + if (thread_can_start_ != NULL) + thread_can_start_->WaitForNotification(); + func_(param_); + } + + private: + const UserThreadFunc func_; // User-supplied thread function. + const T param_; // User-supplied parameter to the thread function. + // When non-NULL, used to block execution until the controller thread + // notifies. + Notification* const thread_can_start_; + bool finished_; // true iff we know that the thread function has finished. + pthread_t thread_; // The native thread object. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); +}; + +// MutexBase and Mutex implement mutex on pthreads-based platforms. They +// are used in conjunction with class MutexLock: +// +// Mutex mutex; +// ... +// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end +// // of the current scope. +// +// MutexBase implements behavior for both statically and dynamically +// allocated mutexes. Do not use MutexBase directly. Instead, write +// the following to define a static mutex: +// +// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); +// +// You can forward declare a static mutex like this: +// +// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); +// +// To create a dynamic mutex, just define an object of type Mutex. +class MutexBase { + public: + // Acquires this mutex. + void Lock() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); + owner_ = pthread_self(); + } + + // Releases this mutex. + void Unlock() { + // We don't protect writing to owner_ here, as it's the caller's + // responsibility to ensure that the current thread holds the + // mutex when this is called. + owner_ = 0; + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); + } + + // Does nothing if the current thread holds the mutex. Otherwise, crashes + // with high probability. + void AssertHeld() const { + GTEST_CHECK_(owner_ == pthread_self()) + << "The current thread is not holding the mutex @" << this; + } + + // A static mutex may be used before main() is entered. It may even + // be used before the dynamic initialization stage. Therefore we + // must be able to initialize a static mutex object at link time. + // This means MutexBase has to be a POD and its member variables + // have to be public. + public: + pthread_mutex_t mutex_; // The underlying pthread mutex. + pthread_t owner_; // The thread holding the mutex; 0 means no one holds it. +}; + +// Forward-declares a static mutex. +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::MutexBase mutex + +// Defines and statically (i.e. at link time) initializes a static mutex. +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ + ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 } + +// The Mutex class can only be used for mutexes created at runtime. It +// shares its API with MutexBase otherwise. +class Mutex : public MutexBase { + public: + Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + owner_ = 0; + } + ~Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); +}; + +// We cannot name this class MutexLock as the ctor declaration would +// conflict with a macro named MutexLock, which is defined on some +// platforms. Hence the typedef trick below. +class GTestMutexLock { + public: + explicit GTestMutexLock(MutexBase* mutex) + : mutex_(mutex) { mutex_->Lock(); } + + ~GTestMutexLock() { mutex_->Unlock(); } + + private: + MutexBase* const mutex_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); +}; + +typedef GTestMutexLock MutexLock; + +// Helpers for ThreadLocal. + +// pthread_key_create() requires DeleteThreadLocalValue() to have +// C-linkage. Therefore it cannot be templatized to access +// ThreadLocal. Hence the need for class +// ThreadLocalValueHolderBase. +class ThreadLocalValueHolderBase { + public: + virtual ~ThreadLocalValueHolderBase() {} +}; + +// Called by pthread to delete thread-local data stored by +// pthread_setspecific(). +extern "C" inline void DeleteThreadLocalValue(void* value_holder) { + delete static_cast(value_holder); +} + +// Implements thread-local storage on pthreads-based systems. +// +// // Thread 1 +// ThreadLocal tl(100); // 100 is the default value for each thread. +// +// // Thread 2 +// tl.set(150); // Changes the value for thread 2 only. +// EXPECT_EQ(150, tl.get()); +// +// // Thread 1 +// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value. +// tl.set(200); +// EXPECT_EQ(200, tl.get()); +// +// The template type argument T must have a public copy constructor. +// In addition, the default ThreadLocal constructor requires T to have +// a public default constructor. +// +// An object managed for a thread by a ThreadLocal instance is deleted +// when the thread exits. Or, if the ThreadLocal instance dies in +// that thread, when the ThreadLocal dies. It's the user's +// responsibility to ensure that all other threads using a ThreadLocal +// have exited when it dies, or the per-thread objects for those +// threads will not be deleted. +// +// Google Test only uses global ThreadLocal objects. That means they +// will die after main() has returned. Therefore, no per-thread +// object managed by Google Test will be leaked as long as all threads +// using Google Test have exited when main() returns. +template +class ThreadLocal { + public: + ThreadLocal() : key_(CreateKey()), + default_() {} + explicit ThreadLocal(const T& value) : key_(CreateKey()), + default_(value) {} + + ~ThreadLocal() { + // Destroys the managed object for the current thread, if any. + DeleteThreadLocalValue(pthread_getspecific(key_)); + + // Releases resources associated with the key. This will *not* + // delete managed objects for other threads. + GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); + } + + T* pointer() { return GetOrCreateValue(); } + const T* pointer() const { return GetOrCreateValue(); } + const T& get() const { return *pointer(); } + void set(const T& value) { *pointer() = value; } + + private: + // Holds a value of type T. + class ValueHolder : public ThreadLocalValueHolderBase { + public: + explicit ValueHolder(const T& value) : value_(value) {} + + T* pointer() { return &value_; } + + private: + T value_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder); + }; + + static pthread_key_t CreateKey() { + pthread_key_t key; + // When a thread exits, DeleteThreadLocalValue() will be called on + // the object managed for that thread. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_key_create(&key, &DeleteThreadLocalValue)); + return key; + } + + T* GetOrCreateValue() const { + ThreadLocalValueHolderBase* const holder = + static_cast(pthread_getspecific(key_)); + if (holder != NULL) { + return CheckedDowncastToActualType(holder)->pointer(); + } + + ValueHolder* const new_holder = new ValueHolder(default_); + ThreadLocalValueHolderBase* const holder_base = new_holder; + GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); + return new_holder->pointer(); + } + + // A key pthreads uses for looking up per-thread values. + const pthread_key_t key_; + const T default_; // The default value for each thread. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); +}; + +# define GTEST_IS_THREADSAFE 1 + +#else // GTEST_HAS_PTHREAD + +// A dummy implementation of synchronization primitives (mutex, lock, +// and thread-local variable). Necessary for compiling Google Test where +// mutex is not supported - using Google Test in multiple threads is not +// supported on such platforms. + +class Mutex { + public: + Mutex() {} + void AssertHeld() const {} +}; + +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::Mutex mutex + +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex + +class GTestMutexLock { + public: + explicit GTestMutexLock(Mutex*) {} // NOLINT +}; + +typedef GTestMutexLock MutexLock; + +template +class ThreadLocal { + public: + ThreadLocal() : value_() {} + explicit ThreadLocal(const T& value) : value_(value) {} + T* pointer() { return &value_; } + const T* pointer() const { return &value_; } + const T& get() const { return value_; } + void set(const T& value) { value_ = value; } + private: + T value_; +}; + +// The above synchronization primitives have dummy implementations. +// Therefore Google Test is not thread-safe. +# define GTEST_IS_THREADSAFE 0 + +#endif // GTEST_HAS_PTHREAD + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +GTEST_API_ size_t GetThreadCount(); + +// Passing non-POD classes through ellipsis (...) crashes the ARM +// compiler and generates a warning in Sun Studio. The Nokia Symbian +// and the IBM XL C/C++ compiler try to instantiate a copy constructor +// for objects passed through ellipsis (...), failing for uncopyable +// objects. We define this to ensure that only POD is passed through +// ellipsis on these systems. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_ELLIPSIS_NEEDS_POD_ 1 +#else +# define GTEST_CAN_COMPARE_NULL 1 +#endif + +// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between +// const T& and const T* in a function template. These compilers +// _can_ decide between class template specializations for T and T*, +// so a tr1::type_traits-like is_pointer works. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) +# define GTEST_NEEDS_IS_POINTER_ 1 +#endif + +template +struct bool_constant { + typedef bool_constant type; + static const bool value = bool_value; +}; +template const bool bool_constant::value; + +typedef bool_constant false_type; +typedef bool_constant true_type; + +template +struct is_pointer : public false_type {}; + +template +struct is_pointer : public true_type {}; + +template +struct IteratorTraits { + typedef typename Iterator::value_type value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_SEP_ "\\" +# define GTEST_HAS_ALT_PATH_SEP_ 1 +// The biggest signed integer type the compiler supports. +typedef __int64 BiggestInt; +#else +# define GTEST_PATH_SEP_ "/" +# define GTEST_HAS_ALT_PATH_SEP_ 0 +typedef long long BiggestInt; // NOLINT +#endif // GTEST_OS_WINDOWS + +// Utilities for char. + +// isspace(int ch) and friends accept an unsigned char or EOF. char +// may be signed, depending on the compiler (or compiler flags). +// Therefore we need to cast a char to unsigned char before calling +// isspace(), etc. + +inline bool IsAlpha(char ch) { + return isalpha(static_cast(ch)) != 0; +} +inline bool IsAlNum(char ch) { + return isalnum(static_cast(ch)) != 0; +} +inline bool IsDigit(char ch) { + return isdigit(static_cast(ch)) != 0; +} +inline bool IsLower(char ch) { + return islower(static_cast(ch)) != 0; +} +inline bool IsSpace(char ch) { + return isspace(static_cast(ch)) != 0; +} +inline bool IsUpper(char ch) { + return isupper(static_cast(ch)) != 0; +} +inline bool IsXDigit(char ch) { + return isxdigit(static_cast(ch)) != 0; +} + +inline char ToLower(char ch) { + return static_cast(tolower(static_cast(ch))); +} +inline char ToUpper(char ch) { + return static_cast(toupper(static_cast(ch))); +} + +// The testing::internal::posix namespace holds wrappers for common +// POSIX functions. These wrappers hide the differences between +// Windows/MSVC and POSIX systems. Since some compilers define these +// standard functions as macros, the wrapper cannot have the same name +// as the wrapped function. + +namespace posix { + +// Functions with a different name on Windows. + +#if GTEST_OS_WINDOWS + +typedef struct _stat StatStruct; + +# ifdef __BORLANDC__ +inline int IsATTY(int fd) { return isatty(fd); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +# else // !__BORLANDC__ +# if GTEST_OS_WINDOWS_MOBILE +inline int IsATTY(int /* fd */) { return 0; } +# else +inline int IsATTY(int fd) { return _isatty(fd); } +# endif // GTEST_OS_WINDOWS_MOBILE +inline int StrCaseCmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return _strdup(src); } +# endif // __BORLANDC__ + +# if GTEST_OS_WINDOWS_MOBILE +inline int FileNo(FILE* file) { return reinterpret_cast(_fileno(file)); } +// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this +// time and thus not defined there. +# else +inline int FileNo(FILE* file) { return _fileno(file); } +inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } +inline int RmDir(const char* dir) { return _rmdir(dir); } +inline bool IsDir(const StatStruct& st) { + return (_S_IFDIR & st.st_mode) != 0; +} +# endif // GTEST_OS_WINDOWS_MOBILE + +#else + +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int IsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + +#endif // GTEST_OS_WINDOWS + +// Functions deprecated by MSVC 8.0. + +#ifdef _MSC_VER +// Temporarily disable warning 4996 (deprecated function). +# pragma warning(push) +# pragma warning(disable:4996) +#endif + +inline const char* StrNCpy(char* dest, const char* src, size_t n) { + return strncpy(dest, src, n); +} + +// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and +// StrError() aren't needed on Windows CE at this time and thus not +// defined there. + +#if !GTEST_OS_WINDOWS_MOBILE +inline int ChDir(const char* dir) { return chdir(dir); } +#endif +inline FILE* FOpen(const char* path, const char* mode) { + return fopen(path, mode); +} +#if !GTEST_OS_WINDOWS_MOBILE +inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { + return freopen(path, mode, stream); +} +inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } +#endif +inline int FClose(FILE* fp) { return fclose(fp); } +#if !GTEST_OS_WINDOWS_MOBILE +inline int Read(int fd, void* buf, unsigned int count) { + return static_cast(read(fd, buf, count)); +} +inline int Write(int fd, const void* buf, unsigned int count) { + return static_cast(write(fd, buf, count)); +} +inline int Close(int fd) { return close(fd); } +inline const char* StrError(int errnum) { return strerror(errnum); } +#endif +inline const char* GetEnv(const char* name) { +#if GTEST_OS_WINDOWS_MOBILE + // We are on Windows CE, which has no environment variables. + return NULL; +#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) + // Environment variables which we programmatically clear will be set to the + // empty string rather than unset (NULL). Handle that case. + const char* const env = getenv(name); + return (env != NULL && env[0] != '\0') ? env : NULL; +#else + return getenv(name); +#endif +} + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + +#if GTEST_OS_WINDOWS_MOBILE +// Windows CE has no C library. The abort() function is used in +// several places in Google Test. This implementation provides a reasonable +// imitation of standard behaviour. +void Abort(); +#else +inline void Abort() { abort(); } +#endif // GTEST_OS_WINDOWS_MOBILE + +} // namespace posix + +// The maximum number a BiggestInt can represent. This definition +// works no matter BiggestInt is represented in one's complement or +// two's complement. +// +// We cannot rely on numeric_limits in STL, as __int64 and long long +// are not part of standard C++ and numeric_limits doesn't need to be +// defined for them. +const BiggestInt kMaxBiggestInt = + ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); + +// This template class serves as a compile-time function from size to +// type. It maps a size in bytes to a primitive type with that +// size. e.g. +// +// TypeWithSize<4>::UInt +// +// is typedef-ed to be unsigned int (unsigned integer made up of 4 +// bytes). +// +// Such functionality should belong to STL, but I cannot find it +// there. +// +// Google Test uses this class in the implementation of floating-point +// comparison. +// +// For now it only handles UInt (unsigned int) as that's all Google Test +// needs. Other types can be easily added in the future if need +// arises. +template +class TypeWithSize { + public: + // This prevents the user from using TypeWithSize with incorrect + // values of N. + typedef void UInt; +}; + +// The specialization for size 4. +template <> +class TypeWithSize<4> { + public: + // unsigned int has size 4 in both gcc and MSVC. + // + // As base/basictypes.h doesn't compile on Windows, we cannot use + // uint32, uint64, and etc here. + typedef int Int; + typedef unsigned int UInt; +}; + +// The specialization for size 8. +template <> +class TypeWithSize<8> { + public: + +#if GTEST_OS_WINDOWS + typedef __int64 Int; + typedef unsigned __int64 UInt; +#else + typedef long long Int; // NOLINT + typedef unsigned long long UInt; // NOLINT +#endif // GTEST_OS_WINDOWS +}; + +// Integer types of known sizes. +typedef TypeWithSize<4>::Int Int32; +typedef TypeWithSize<4>::UInt UInt32; +typedef TypeWithSize<8>::Int Int64; +typedef TypeWithSize<8>::UInt UInt64; +typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. + +// Utilities for command line flags and environment variables. + +// Macro for referencing flags. +#define GTEST_FLAG(name) FLAGS_gtest_##name + +// Macros for declaring flags. +#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) +#define GTEST_DECLARE_int32_(name) \ + GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) +#define GTEST_DECLARE_string_(name) \ + GTEST_API_ extern ::testing::internal::String GTEST_FLAG(name) + +// Macros for defining flags. +#define GTEST_DEFINE_bool_(name, default_val, doc) \ + GTEST_API_ bool GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_int32_(name, default_val, doc) \ + GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_string_(name, default_val, doc) \ + GTEST_API_ ::testing::internal::String GTEST_FLAG(name) = (default_val) + +// Parses 'str' for a 32-bit signed integer. If successful, writes the result +// to *value and returns true; otherwise leaves *value unchanged and returns +// false. +// TODO(chandlerc): Find a better way to refactor flag and environment parsing +// out of both gtest-port.cc and gtest.cc to avoid exporting this utility +// function. +bool ParseInt32(const Message& src_text, const char* str, Int32* value); + +// Parses a bool/Int32/string from the environment variable +// corresponding to the given Google Test flag. +bool BoolFromGTestEnv(const char* flag, bool default_val); +GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +const char* StringFromGTestEnv(const char* flag, const char* default_val); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +#if GTEST_OS_LINUX +# include +# include +# include +# include +#endif // GTEST_OS_LINUX + +#include +#include +#include +#include +#include + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares the String class and functions used internally by +// Google Test. They are subject to change without notice. They should not used +// by code external to Google Test. +// +// This header file is #included by . +// It should not be #included by other files. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ + +#ifdef __BORLANDC__ +// string.h is not guaranteed to provide strcpy on C++ Builder. +# include +#endif + +#include + +#include + +namespace testing { +namespace internal { + +// String - a UTF-8 string class. +// +// For historic reasons, we don't use std::string. +// +// TODO(wan@google.com): replace this class with std::string or +// implement it in terms of the latter. +// +// Note that String can represent both NULL and the empty string, +// while std::string cannot represent NULL. +// +// NULL and the empty string are considered different. NULL is less +// than anything (including the empty string) except itself. +// +// This class only provides minimum functionality necessary for +// implementing Google Test. We do not intend to implement a full-fledged +// string class here. +// +// Since the purpose of this class is to provide a substitute for +// std::string on platforms where it cannot be used, we define a copy +// constructor and assignment operators such that we don't need +// conditional compilation in a lot of places. +// +// In order to make the representation efficient, the d'tor of String +// is not virtual. Therefore DO NOT INHERIT FROM String. +class GTEST_API_ String { + public: + // Static utility methods + + // Returns the input enclosed in double quotes if it's not NULL; + // otherwise returns "(null)". For example, "\"Hello\"" is returned + // for input "Hello". + // + // This is useful for printing a C string in the syntax of a literal. + // + // Known issue: escape sequences are not handled yet. + static String ShowCStringQuoted(const char* c_str); + + // Clones a 0-terminated C string, allocating memory using new. The + // caller is responsible for deleting the return value using + // delete[]. Returns the cloned string, or NULL if the input is + // NULL. + // + // This is different from strdup() in string.h, which allocates + // memory using malloc(). + static const char* CloneCString(const char* c_str); + +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be + // able to pass strings to Win32 APIs on CE we need to convert them + // to 'Unicode', UTF-16. + + // Creates a UTF-16 wide string from the given ANSI string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the wide string, or NULL if the + // input is NULL. + // + // The wide string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static LPCWSTR AnsiToUtf16(const char* c_str); + + // Creates an ANSI string from the given wide string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the ANSI string, or NULL if the + // input is NULL. + // + // The returned string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static const char* Utf16ToAnsi(LPCWSTR utf16_str); +#endif + + // Compares two C strings. Returns true iff they have the same content. + // + // Unlike strcmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CStringEquals(const char* lhs, const char* rhs); + + // Converts a wide C string to a String using the UTF-8 encoding. + // NULL will be converted to "(null)". If an error occurred during + // the conversion, "(failed to convert from wide string)" is + // returned. + static String ShowWideCString(const wchar_t* wide_c_str); + + // Similar to ShowWideCString(), except that this function encloses + // the converted string in double quotes. + static String ShowWideCStringQuoted(const wchar_t* wide_c_str); + + // Compares two wide C strings. Returns true iff they have the same + // content. + // + // Unlike wcscmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); + + // Compares two C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike strcasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CaseInsensitiveCStringEquals(const char* lhs, + const char* rhs); + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. + static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs); + + // Formats a list of arguments to a String, using the same format + // spec string as for printf. + // + // We do not use the StringPrintf class as it is not universally + // available. + // + // The result is limited to 4096 characters (including the tailing + // 0). If 4096 characters are not enough to format the input, + // "" is returned. + static String Format(const char* format, ...); + + // C'tors + + // The default c'tor constructs a NULL string. + String() : c_str_(NULL), length_(0) {} + + // Constructs a String by cloning a 0-terminated C string. + String(const char* a_c_str) { // NOLINT + if (a_c_str == NULL) { + c_str_ = NULL; + length_ = 0; + } else { + ConstructNonNull(a_c_str, strlen(a_c_str)); + } + } + + // Constructs a String by copying a given number of chars from a + // buffer. E.g. String("hello", 3) creates the string "hel", + // String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "", + // and String(NULL, 1) results in access violation. + String(const char* buffer, size_t a_length) { + ConstructNonNull(buffer, a_length); + } + + // The copy c'tor creates a new copy of the string. The two + // String objects do not share content. + String(const String& str) : c_str_(NULL), length_(0) { *this = str; } + + // D'tor. String is intended to be a final class, so the d'tor + // doesn't need to be virtual. + ~String() { delete[] c_str_; } + + // Allows a String to be implicitly converted to an ::std::string or + // ::string, and vice versa. Converting a String containing a NULL + // pointer to ::std::string or ::string is undefined behavior. + // Converting a ::std::string or ::string containing an embedded NUL + // character to a String will result in the prefix up to the first + // NUL character. + String(const ::std::string& str) { + ConstructNonNull(str.c_str(), str.length()); + } + + operator ::std::string() const { return ::std::string(c_str(), length()); } + +#if GTEST_HAS_GLOBAL_STRING + String(const ::string& str) { + ConstructNonNull(str.c_str(), str.length()); + } + + operator ::string() const { return ::string(c_str(), length()); } +#endif // GTEST_HAS_GLOBAL_STRING + + // Returns true iff this is an empty string (i.e. ""). + bool empty() const { return (c_str() != NULL) && (length() == 0); } + + // Compares this with another String. + // Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0 + // if this is greater than rhs. + int Compare(const String& rhs) const; + + // Returns true iff this String equals the given C string. A NULL + // string and a non-NULL string are considered not equal. + bool operator==(const char* a_c_str) const { return Compare(a_c_str) == 0; } + + // Returns true iff this String is less than the given String. A + // NULL string is considered less than "". + bool operator<(const String& rhs) const { return Compare(rhs) < 0; } + + // Returns true iff this String doesn't equal the given C string. A NULL + // string and a non-NULL string are considered not equal. + bool operator!=(const char* a_c_str) const { return !(*this == a_c_str); } + + // Returns true iff this String ends with the given suffix. *Any* + // String is considered to end with a NULL or empty suffix. + bool EndsWith(const char* suffix) const; + + // Returns true iff this String ends with the given suffix, not considering + // case. Any String is considered to end with a NULL or empty suffix. + bool EndsWithCaseInsensitive(const char* suffix) const; + + // Returns the length of the encapsulated string, or 0 if the + // string is NULL. + size_t length() const { return length_; } + + // Gets the 0-terminated C string this String object represents. + // The String object still owns the string. Therefore the caller + // should NOT delete the return value. + const char* c_str() const { return c_str_; } + + // Assigns a C string to this object. Self-assignment works. + const String& operator=(const char* a_c_str) { + return *this = String(a_c_str); + } + + // Assigns a String object to this object. Self-assignment works. + const String& operator=(const String& rhs) { + if (this != &rhs) { + delete[] c_str_; + if (rhs.c_str() == NULL) { + c_str_ = NULL; + length_ = 0; + } else { + ConstructNonNull(rhs.c_str(), rhs.length()); + } + } + + return *this; + } + + private: + // Constructs a non-NULL String from the given content. This + // function can only be called when c_str_ has not been allocated. + // ConstructNonNull(NULL, 0) results in an empty string (""). + // ConstructNonNull(NULL, non_zero) is undefined behavior. + void ConstructNonNull(const char* buffer, size_t a_length) { + char* const str = new char[a_length + 1]; + memcpy(str, buffer, a_length); + str[a_length] = '\0'; + c_str_ = str; + length_ = a_length; + } + + const char* c_str_; + size_t length_; +}; // class String + +// Streams a String to an ostream. Each '\0' character in the String +// is replaced with "\\0". +inline ::std::ostream& operator<<(::std::ostream& os, const String& str) { + if (str.c_str() == NULL) { + os << "(null)"; + } else { + const char* const c_str = str.c_str(); + for (size_t i = 0; i != str.length(); i++) { + if (c_str[i] == '\0') { + os << "\\0"; + } else { + os << c_str[i]; + } + } + } + return os; +} + +// Gets the content of the stringstream's buffer as a String. Each '\0' +// character in the buffer is replaced with "\\0". +GTEST_API_ String StringStreamToString(::std::stringstream* stream); + +// Converts a streamable value to a String. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". + +// Declared here but defined in gtest.h, so that it has access +// to the definition of the Message class, required by the ARM +// compiler. +template +String StreamableToString(const T& streamable); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: keith.ray@gmail.com (Keith Ray) +// +// Google Test filepath utilities +// +// This header file declares classes and functions used internally by +// Google Test. They are subject to change without notice. +// +// This file is #included in . +// Do not include this header file separately! + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ + + +namespace testing { +namespace internal { + +// FilePath - a class for file and directory pathname manipulation which +// handles platform-specific conventions (like the pathname separator). +// Used for helper functions for naming files in a directory for xml output. +// Except for Set methods, all methods are const or static, which provides an +// "immutable value object" -- useful for peace of mind. +// A FilePath with a value ending in a path separator ("like/this/") represents +// a directory, otherwise it is assumed to represent a file. In either case, +// it may or may not represent an actual file or directory in the file system. +// Names are NOT checked for syntax correctness -- no checking for illegal +// characters, malformed paths, etc. + +class GTEST_API_ FilePath { + public: + FilePath() : pathname_("") { } + FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } + + explicit FilePath(const char* pathname) : pathname_(pathname) { + Normalize(); + } + + explicit FilePath(const String& pathname) : pathname_(pathname) { + Normalize(); + } + + FilePath& operator=(const FilePath& rhs) { + Set(rhs); + return *this; + } + + void Set(const FilePath& rhs) { + pathname_ = rhs.pathname_; + } + + String ToString() const { return pathname_; } + const char* c_str() const { return pathname_.c_str(); } + + // Returns the current working directory, or "" if unsuccessful. + static FilePath GetCurrentDir(); + + // Given directory = "dir", base_name = "test", number = 0, + // extension = "xml", returns "dir/test.xml". If number is greater + // than zero (e.g., 12), returns "dir/test_12.xml". + // On Windows platform, uses \ as the separator rather than /. + static FilePath MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension); + + // Given directory = "dir", relative_path = "test.xml", + // returns "dir/test.xml". + // On Windows, uses \ as the separator rather than /. + static FilePath ConcatPaths(const FilePath& directory, + const FilePath& relative_path); + + // Returns a pathname for a file that does not currently exist. The pathname + // will be directory/base_name.extension or + // directory/base_name_.extension if directory/base_name.extension + // already exists. The number will be incremented until a pathname is found + // that does not already exist. + // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. + // There could be a race condition if two or more processes are calling this + // function at the same time -- they could both pick the same filename. + static FilePath GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension); + + // Returns true iff the path is NULL or "". + bool IsEmpty() const { return c_str() == NULL || *c_str() == '\0'; } + + // If input name has a trailing separator character, removes it and returns + // the name, otherwise return the name string unmodified. + // On Windows platform, uses \ as the separator, other platforms use /. + FilePath RemoveTrailingPathSeparator() const; + + // Returns a copy of the FilePath with the directory part removed. + // Example: FilePath("path/to/file").RemoveDirectoryName() returns + // FilePath("file"). If there is no directory part ("just_a_file"), it returns + // the FilePath unmodified. If there is no file part ("just_a_dir/") it + // returns an empty FilePath (""). + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveDirectoryName() const; + + // RemoveFileName returns the directory path with the filename removed. + // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". + // If the FilePath is "a_file" or "/a_file", RemoveFileName returns + // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does + // not have a file, like "just/a/dir/", it returns the FilePath unmodified. + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveFileName() const; + + // Returns a copy of the FilePath with the case-insensitive extension removed. + // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns + // FilePath("dir/file"). If a case-insensitive extension is not + // found, returns a copy of the original FilePath. + FilePath RemoveExtension(const char* extension) const; + + // Creates directories so that path exists. Returns true if successful or if + // the directories already exist; returns false if unable to create + // directories for any reason. Will also return false if the FilePath does + // not represent a directory (that is, it doesn't end with a path separator). + bool CreateDirectoriesRecursively() const; + + // Create the directory so that path exists. Returns true if successful or + // if the directory already exists; returns false if unable to create the + // directory for any reason, including if the parent directory does not + // exist. Not named "CreateDirectory" because that's a macro on Windows. + bool CreateFolder() const; + + // Returns true if FilePath describes something in the file-system, + // either a file, directory, or whatever, and that something exists. + bool FileOrDirectoryExists() const; + + // Returns true if pathname describes a directory in the file-system + // that exists. + bool DirectoryExists() const; + + // Returns true if FilePath ends with a path separator, which indicates that + // it is intended to represent a directory. Returns false otherwise. + // This does NOT check that a directory (or file) actually exists. + bool IsDirectory() const; + + // Returns true if pathname describes a root directory. (Windows has one + // root directory per disk drive.) + bool IsRootDirectory() const; + + // Returns true if pathname describes an absolute path. + bool IsAbsolutePath() const; + + private: + // Replaces multiple consecutive separators with a single separator. + // For example, "bar///foo" becomes "bar/foo". Does not eliminate other + // redundancies that might be in a pathname involving "." or "..". + // + // A pathname with multiple consecutive separators may occur either through + // user error or as a result of some scripts or APIs that generate a pathname + // with a trailing separator. On other platforms the same API or script + // may NOT generate a pathname with a trailing "/". Then elsewhere that + // pathname may have another "/" and pathname components added to it, + // without checking for the separator already being there. + // The script language and operating system may allow paths like "foo//bar" + // but some of the functions in FilePath will not handle that correctly. In + // particular, RemoveTrailingPathSeparator() only removes one separator, and + // it is called in CreateDirectoriesRecursively() assuming that it will change + // a pathname from directory syntax (trailing separator) to filename syntax. + // + // On Windows this method also replaces the alternate path separator '/' with + // the primary path separator '\\', so that for example "bar\\/\\foo" becomes + // "bar\\foo". + + void Normalize(); + + // Returns a pointer to the last occurence of a valid path separator in + // the FilePath. On Windows, for example, both '/' and '\' are valid path + // separators. Returns NULL if no path separator was found. + const char* FindLastPathSeparator() const; + + String pathname_; +}; // class FilePath + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +// This file was GENERATED by command: +// pump.py gtest-type-util.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Type utilities needed for implementing typed and type-parameterized +// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently we support at most 50 types in a list, and at most 50 +// type-parameterized tests in one type-parameterized test case. +// Please contact googletestframework@googlegroups.com if you need +// more. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + + +// #ifdef __GNUC__ is too general here. It is possible to use gcc without using +// libstdc++ (which is where cxxabi.h comes from). +# ifdef __GLIBCXX__ +# include +# elif defined(__HP_aCC) +# include +# endif // __GLIBCXX__ + +namespace testing { +namespace internal { + +// GetTypeName() returns a human-readable name of type T. +// NB: This function is also used in Google Mock, so don't move it inside of +// the typed-test-only section below. +template +String GetTypeName() { +# if GTEST_HAS_RTTI + + const char* const name = typeid(T).name(); +# if defined(__GLIBCXX__) || defined(__HP_aCC) + int status = 0; + // gcc's implementation of typeid(T).name() mangles the type name, + // so we have to demangle it. +# ifdef __GLIBCXX__ + using abi::__cxa_demangle; +# endif // __GLIBCXX__ + char* const readable_name = __cxa_demangle(name, 0, 0, &status); + const String name_str(status == 0 ? readable_name : name); + free(readable_name); + return name_str; +# else + return name; +# endif // __GLIBCXX__ || __HP_aCC + +# else + + return ""; + +# endif // GTEST_HAS_RTTI +} + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// AssertyTypeEq::type is defined iff T1 and T2 are the same +// type. This can be used as a compile-time assertion to ensure that +// two types are equal. + +template +struct AssertTypeEq; + +template +struct AssertTypeEq { + typedef bool type; +}; + +// A unique type used as the default value for the arguments of class +// template Types. This allows us to simulate variadic templates +// (e.g. Types, Type, and etc), which C++ doesn't +// support directly. +struct None {}; + +// The following family of struct and struct templates are used to +// represent type lists. In particular, TypesN +// represents a type list with N types (T1, T2, ..., and TN) in it. +// Except for Types0, every struct in the family has two member types: +// Head for the first type in the list, and Tail for the rest of the +// list. + +// The empty type list. +struct Types0 {}; + +// Type lists of length 1, 2, 3, and so on. + +template +struct Types1 { + typedef T1 Head; + typedef Types0 Tail; +}; +template +struct Types2 { + typedef T1 Head; + typedef Types1 Tail; +}; + +template +struct Types3 { + typedef T1 Head; + typedef Types2 Tail; +}; + +template +struct Types4 { + typedef T1 Head; + typedef Types3 Tail; +}; + +template +struct Types5 { + typedef T1 Head; + typedef Types4 Tail; +}; + +template +struct Types6 { + typedef T1 Head; + typedef Types5 Tail; +}; + +template +struct Types7 { + typedef T1 Head; + typedef Types6 Tail; +}; + +template +struct Types8 { + typedef T1 Head; + typedef Types7 Tail; +}; + +template +struct Types9 { + typedef T1 Head; + typedef Types8 Tail; +}; + +template +struct Types10 { + typedef T1 Head; + typedef Types9 Tail; +}; + +template +struct Types11 { + typedef T1 Head; + typedef Types10 Tail; +}; + +template +struct Types12 { + typedef T1 Head; + typedef Types11 Tail; +}; + +template +struct Types13 { + typedef T1 Head; + typedef Types12 Tail; +}; + +template +struct Types14 { + typedef T1 Head; + typedef Types13 Tail; +}; + +template +struct Types15 { + typedef T1 Head; + typedef Types14 Tail; +}; + +template +struct Types16 { + typedef T1 Head; + typedef Types15 Tail; +}; + +template +struct Types17 { + typedef T1 Head; + typedef Types16 Tail; +}; + +template +struct Types18 { + typedef T1 Head; + typedef Types17 Tail; +}; + +template +struct Types19 { + typedef T1 Head; + typedef Types18 Tail; +}; + +template +struct Types20 { + typedef T1 Head; + typedef Types19 Tail; +}; + +template +struct Types21 { + typedef T1 Head; + typedef Types20 Tail; +}; + +template +struct Types22 { + typedef T1 Head; + typedef Types21 Tail; +}; + +template +struct Types23 { + typedef T1 Head; + typedef Types22 Tail; +}; + +template +struct Types24 { + typedef T1 Head; + typedef Types23 Tail; +}; + +template +struct Types25 { + typedef T1 Head; + typedef Types24 Tail; +}; + +template +struct Types26 { + typedef T1 Head; + typedef Types25 Tail; +}; + +template +struct Types27 { + typedef T1 Head; + typedef Types26 Tail; +}; + +template +struct Types28 { + typedef T1 Head; + typedef Types27 Tail; +}; + +template +struct Types29 { + typedef T1 Head; + typedef Types28 Tail; +}; + +template +struct Types30 { + typedef T1 Head; + typedef Types29 Tail; +}; + +template +struct Types31 { + typedef T1 Head; + typedef Types30 Tail; +}; + +template +struct Types32 { + typedef T1 Head; + typedef Types31 Tail; +}; + +template +struct Types33 { + typedef T1 Head; + typedef Types32 Tail; +}; + +template +struct Types34 { + typedef T1 Head; + typedef Types33 Tail; +}; + +template +struct Types35 { + typedef T1 Head; + typedef Types34 Tail; +}; + +template +struct Types36 { + typedef T1 Head; + typedef Types35 Tail; +}; + +template +struct Types37 { + typedef T1 Head; + typedef Types36 Tail; +}; + +template +struct Types38 { + typedef T1 Head; + typedef Types37 Tail; +}; + +template +struct Types39 { + typedef T1 Head; + typedef Types38 Tail; +}; + +template +struct Types40 { + typedef T1 Head; + typedef Types39 Tail; +}; + +template +struct Types41 { + typedef T1 Head; + typedef Types40 Tail; +}; + +template +struct Types42 { + typedef T1 Head; + typedef Types41 Tail; +}; + +template +struct Types43 { + typedef T1 Head; + typedef Types42 Tail; +}; + +template +struct Types44 { + typedef T1 Head; + typedef Types43 Tail; +}; + +template +struct Types45 { + typedef T1 Head; + typedef Types44 Tail; +}; + +template +struct Types46 { + typedef T1 Head; + typedef Types45 Tail; +}; + +template +struct Types47 { + typedef T1 Head; + typedef Types46 Tail; +}; + +template +struct Types48 { + typedef T1 Head; + typedef Types47 Tail; +}; + +template +struct Types49 { + typedef T1 Head; + typedef Types48 Tail; +}; + +template +struct Types50 { + typedef T1 Head; + typedef Types49 Tail; +}; + + +} // namespace internal + +// We don't want to require the users to write TypesN<...> directly, +// as that would require them to count the length. Types<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Types +// will appear as Types in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Types, and Google Test will translate +// that to TypesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Types template. +template +struct Types { + typedef internal::Types50 type; +}; + +template <> +struct Types { + typedef internal::Types0 type; +}; +template +struct Types { + typedef internal::Types1 type; +}; +template +struct Types { + typedef internal::Types2 type; +}; +template +struct Types { + typedef internal::Types3 type; +}; +template +struct Types { + typedef internal::Types4 type; +}; +template +struct Types { + typedef internal::Types5 type; +}; +template +struct Types { + typedef internal::Types6 type; +}; +template +struct Types { + typedef internal::Types7 type; +}; +template +struct Types { + typedef internal::Types8 type; +}; +template +struct Types { + typedef internal::Types9 type; +}; +template +struct Types { + typedef internal::Types10 type; +}; +template +struct Types { + typedef internal::Types11 type; +}; +template +struct Types { + typedef internal::Types12 type; +}; +template +struct Types { + typedef internal::Types13 type; +}; +template +struct Types { + typedef internal::Types14 type; +}; +template +struct Types { + typedef internal::Types15 type; +}; +template +struct Types { + typedef internal::Types16 type; +}; +template +struct Types { + typedef internal::Types17 type; +}; +template +struct Types { + typedef internal::Types18 type; +}; +template +struct Types { + typedef internal::Types19 type; +}; +template +struct Types { + typedef internal::Types20 type; +}; +template +struct Types { + typedef internal::Types21 type; +}; +template +struct Types { + typedef internal::Types22 type; +}; +template +struct Types { + typedef internal::Types23 type; +}; +template +struct Types { + typedef internal::Types24 type; +}; +template +struct Types { + typedef internal::Types25 type; +}; +template +struct Types { + typedef internal::Types26 type; +}; +template +struct Types { + typedef internal::Types27 type; +}; +template +struct Types { + typedef internal::Types28 type; +}; +template +struct Types { + typedef internal::Types29 type; +}; +template +struct Types { + typedef internal::Types30 type; +}; +template +struct Types { + typedef internal::Types31 type; +}; +template +struct Types { + typedef internal::Types32 type; +}; +template +struct Types { + typedef internal::Types33 type; +}; +template +struct Types { + typedef internal::Types34 type; +}; +template +struct Types { + typedef internal::Types35 type; +}; +template +struct Types { + typedef internal::Types36 type; +}; +template +struct Types { + typedef internal::Types37 type; +}; +template +struct Types { + typedef internal::Types38 type; +}; +template +struct Types { + typedef internal::Types39 type; +}; +template +struct Types { + typedef internal::Types40 type; +}; +template +struct Types { + typedef internal::Types41 type; +}; +template +struct Types { + typedef internal::Types42 type; +}; +template +struct Types { + typedef internal::Types43 type; +}; +template +struct Types { + typedef internal::Types44 type; +}; +template +struct Types { + typedef internal::Types45 type; +}; +template +struct Types { + typedef internal::Types46 type; +}; +template +struct Types { + typedef internal::Types47 type; +}; +template +struct Types { + typedef internal::Types48 type; +}; +template +struct Types { + typedef internal::Types49 type; +}; + +namespace internal { + +# define GTEST_TEMPLATE_ template class + +// The template "selector" struct TemplateSel is used to +// represent Tmpl, which must be a class template with one type +// parameter, as a type. TemplateSel::Bind::type is defined +// as the type Tmpl. This allows us to actually instantiate the +// template "selected" by TemplateSel. +// +// This trick is necessary for simulating typedef for class templates, +// which C++ doesn't support directly. +template +struct TemplateSel { + template + struct Bind { + typedef Tmpl type; + }; +}; + +# define GTEST_BIND_(TmplSel, T) \ + TmplSel::template Bind::type + +// A unique struct template used as the default value for the +// arguments of class template Templates. This allows us to simulate +// variadic templates (e.g. Templates, Templates, +// and etc), which C++ doesn't support directly. +template +struct NoneT {}; + +// The following family of struct and struct templates are used to +// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except +// for Templates0, every struct in the family has two member types: +// Head for the selector of the first template in the list, and Tail +// for the rest of the list. + +// The empty template list. +struct Templates0 {}; + +// Template lists of length 1, 2, 3, and so on. + +template +struct Templates1 { + typedef TemplateSel Head; + typedef Templates0 Tail; +}; +template +struct Templates2 { + typedef TemplateSel Head; + typedef Templates1 Tail; +}; + +template +struct Templates3 { + typedef TemplateSel Head; + typedef Templates2 Tail; +}; + +template +struct Templates4 { + typedef TemplateSel Head; + typedef Templates3 Tail; +}; + +template +struct Templates5 { + typedef TemplateSel Head; + typedef Templates4 Tail; +}; + +template +struct Templates6 { + typedef TemplateSel Head; + typedef Templates5 Tail; +}; + +template +struct Templates7 { + typedef TemplateSel Head; + typedef Templates6 Tail; +}; + +template +struct Templates8 { + typedef TemplateSel Head; + typedef Templates7 Tail; +}; + +template +struct Templates9 { + typedef TemplateSel Head; + typedef Templates8 Tail; +}; + +template +struct Templates10 { + typedef TemplateSel Head; + typedef Templates9 Tail; +}; + +template +struct Templates11 { + typedef TemplateSel Head; + typedef Templates10 Tail; +}; + +template +struct Templates12 { + typedef TemplateSel Head; + typedef Templates11 Tail; +}; + +template +struct Templates13 { + typedef TemplateSel Head; + typedef Templates12 Tail; +}; + +template +struct Templates14 { + typedef TemplateSel Head; + typedef Templates13 Tail; +}; + +template +struct Templates15 { + typedef TemplateSel Head; + typedef Templates14 Tail; +}; + +template +struct Templates16 { + typedef TemplateSel Head; + typedef Templates15 Tail; +}; + +template +struct Templates17 { + typedef TemplateSel Head; + typedef Templates16 Tail; +}; + +template +struct Templates18 { + typedef TemplateSel Head; + typedef Templates17 Tail; +}; + +template +struct Templates19 { + typedef TemplateSel Head; + typedef Templates18 Tail; +}; + +template +struct Templates20 { + typedef TemplateSel Head; + typedef Templates19 Tail; +}; + +template +struct Templates21 { + typedef TemplateSel Head; + typedef Templates20 Tail; +}; + +template +struct Templates22 { + typedef TemplateSel Head; + typedef Templates21 Tail; +}; + +template +struct Templates23 { + typedef TemplateSel Head; + typedef Templates22 Tail; +}; + +template +struct Templates24 { + typedef TemplateSel Head; + typedef Templates23 Tail; +}; + +template +struct Templates25 { + typedef TemplateSel Head; + typedef Templates24 Tail; +}; + +template +struct Templates26 { + typedef TemplateSel Head; + typedef Templates25 Tail; +}; + +template +struct Templates27 { + typedef TemplateSel Head; + typedef Templates26 Tail; +}; + +template +struct Templates28 { + typedef TemplateSel Head; + typedef Templates27 Tail; +}; + +template +struct Templates29 { + typedef TemplateSel Head; + typedef Templates28 Tail; +}; + +template +struct Templates30 { + typedef TemplateSel Head; + typedef Templates29 Tail; +}; + +template +struct Templates31 { + typedef TemplateSel Head; + typedef Templates30 Tail; +}; + +template +struct Templates32 { + typedef TemplateSel Head; + typedef Templates31 Tail; +}; + +template +struct Templates33 { + typedef TemplateSel Head; + typedef Templates32 Tail; +}; + +template +struct Templates34 { + typedef TemplateSel Head; + typedef Templates33 Tail; +}; + +template +struct Templates35 { + typedef TemplateSel Head; + typedef Templates34 Tail; +}; + +template +struct Templates36 { + typedef TemplateSel Head; + typedef Templates35 Tail; +}; + +template +struct Templates37 { + typedef TemplateSel Head; + typedef Templates36 Tail; +}; + +template +struct Templates38 { + typedef TemplateSel Head; + typedef Templates37 Tail; +}; + +template +struct Templates39 { + typedef TemplateSel Head; + typedef Templates38 Tail; +}; + +template +struct Templates40 { + typedef TemplateSel Head; + typedef Templates39 Tail; +}; + +template +struct Templates41 { + typedef TemplateSel Head; + typedef Templates40 Tail; +}; + +template +struct Templates42 { + typedef TemplateSel Head; + typedef Templates41 Tail; +}; + +template +struct Templates43 { + typedef TemplateSel Head; + typedef Templates42 Tail; +}; + +template +struct Templates44 { + typedef TemplateSel Head; + typedef Templates43 Tail; +}; + +template +struct Templates45 { + typedef TemplateSel Head; + typedef Templates44 Tail; +}; + +template +struct Templates46 { + typedef TemplateSel Head; + typedef Templates45 Tail; +}; + +template +struct Templates47 { + typedef TemplateSel Head; + typedef Templates46 Tail; +}; + +template +struct Templates48 { + typedef TemplateSel Head; + typedef Templates47 Tail; +}; + +template +struct Templates49 { + typedef TemplateSel Head; + typedef Templates48 Tail; +}; + +template +struct Templates50 { + typedef TemplateSel Head; + typedef Templates49 Tail; +}; + + +// We don't want to require the users to write TemplatesN<...> directly, +// as that would require them to count the length. Templates<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Templates +// will appear as Templates in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Templates, and Google Test will translate +// that to TemplatesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Templates template. +template +struct Templates { + typedef Templates50 type; +}; + +template <> +struct Templates { + typedef Templates0 type; +}; +template +struct Templates { + typedef Templates1 type; +}; +template +struct Templates { + typedef Templates2 type; +}; +template +struct Templates { + typedef Templates3 type; +}; +template +struct Templates { + typedef Templates4 type; +}; +template +struct Templates { + typedef Templates5 type; +}; +template +struct Templates { + typedef Templates6 type; +}; +template +struct Templates { + typedef Templates7 type; +}; +template +struct Templates { + typedef Templates8 type; +}; +template +struct Templates { + typedef Templates9 type; +}; +template +struct Templates { + typedef Templates10 type; +}; +template +struct Templates { + typedef Templates11 type; +}; +template +struct Templates { + typedef Templates12 type; +}; +template +struct Templates { + typedef Templates13 type; +}; +template +struct Templates { + typedef Templates14 type; +}; +template +struct Templates { + typedef Templates15 type; +}; +template +struct Templates { + typedef Templates16 type; +}; +template +struct Templates { + typedef Templates17 type; +}; +template +struct Templates { + typedef Templates18 type; +}; +template +struct Templates { + typedef Templates19 type; +}; +template +struct Templates { + typedef Templates20 type; +}; +template +struct Templates { + typedef Templates21 type; +}; +template +struct Templates { + typedef Templates22 type; +}; +template +struct Templates { + typedef Templates23 type; +}; +template +struct Templates { + typedef Templates24 type; +}; +template +struct Templates { + typedef Templates25 type; +}; +template +struct Templates { + typedef Templates26 type; +}; +template +struct Templates { + typedef Templates27 type; +}; +template +struct Templates { + typedef Templates28 type; +}; +template +struct Templates { + typedef Templates29 type; +}; +template +struct Templates { + typedef Templates30 type; +}; +template +struct Templates { + typedef Templates31 type; +}; +template +struct Templates { + typedef Templates32 type; +}; +template +struct Templates { + typedef Templates33 type; +}; +template +struct Templates { + typedef Templates34 type; +}; +template +struct Templates { + typedef Templates35 type; +}; +template +struct Templates { + typedef Templates36 type; +}; +template +struct Templates { + typedef Templates37 type; +}; +template +struct Templates { + typedef Templates38 type; +}; +template +struct Templates { + typedef Templates39 type; +}; +template +struct Templates { + typedef Templates40 type; +}; +template +struct Templates { + typedef Templates41 type; +}; +template +struct Templates { + typedef Templates42 type; +}; +template +struct Templates { + typedef Templates43 type; +}; +template +struct Templates { + typedef Templates44 type; +}; +template +struct Templates { + typedef Templates45 type; +}; +template +struct Templates { + typedef Templates46 type; +}; +template +struct Templates { + typedef Templates47 type; +}; +template +struct Templates { + typedef Templates48 type; +}; +template +struct Templates { + typedef Templates49 type; +}; + +// The TypeList template makes it possible to use either a single type +// or a Types<...> list in TYPED_TEST_CASE() and +// INSTANTIATE_TYPED_TEST_CASE_P(). + +template +struct TypeList { typedef Types1 type; }; + +template +struct TypeList > { + typedef typename Types::type type; +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + +// Due to C++ preprocessor weirdness, we need double indirection to +// concatenate two tokens when one of them is __LINE__. Writing +// +// foo ## __LINE__ +// +// will result in the token foo__LINE__, instead of foo followed by +// the current line number. For more details, see +// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 +#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) +#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar + +// Google Test defines the testing::Message class to allow construction of +// test messages via the << operator. The idea is that anything +// streamable to std::ostream can be streamed to a testing::Message. +// This allows a user to use his own types in Google Test assertions by +// overloading the << operator. +// +// util/gtl/stl_logging-inl.h overloads << for STL containers. These +// overloads cannot be defined in the std namespace, as that will be +// undefined behavior. Therefore, they are defined in the global +// namespace instead. +// +// C++'s symbol lookup rule (i.e. Koenig lookup) says that these +// overloads are visible in either the std namespace or the global +// namespace, but not other namespaces, including the testing +// namespace which Google Test's Message class is in. +// +// To allow STL containers (and other types that has a << operator +// defined in the global namespace) to be used in Google Test assertions, +// testing::Message must access the custom << operator from the global +// namespace. Hence this helper function. +// +// Note: Jeffrey Yasskin suggested an alternative fix by "using +// ::operator<<;" in the definition of Message's operator<<. That fix +// doesn't require a helper function, but unfortunately doesn't +// compile with MSVC. +template +inline void GTestStreamToHelper(std::ostream* os, const T& val) { + *os << val; +} + +class ProtocolMessage; +namespace proto2 { class Message; } + +namespace testing { + +// Forward declarations. + +class AssertionResult; // Result of an assertion. +class Message; // Represents a failure message. +class Test; // Represents a test. +class TestInfo; // Information about a test. +class TestPartResult; // Result of a test part. +class UnitTest; // A collection of test cases. + +template +::std::string PrintToString(const T& value); + +namespace internal { + +struct TraceInfo; // Information about a trace point. +class ScopedTrace; // Implements scoped trace. +class TestInfoImpl; // Opaque implementation of TestInfo +class UnitTestImpl; // Opaque implementation of UnitTest + +// How many times InitGoogleTest() has been called. +extern int g_init_gtest_count; + +// The text used in failure messages to indicate the start of the +// stack trace. +GTEST_API_ extern const char kStackTraceMarker[]; + +// A secret type that Google Test users don't know about. It has no +// definition on purpose. Therefore it's impossible to create a +// Secret object, which is what we want. +class Secret; + +// Two overloaded helpers for checking at compile time whether an +// expression is a null pointer literal (i.e. NULL or any 0-valued +// compile-time integral constant). Their return values have +// different sizes, so we can use sizeof() to test which version is +// picked by the compiler. These helpers have no implementations, as +// we only need their signatures. +// +// Given IsNullLiteralHelper(x), the compiler will pick the first +// version if x can be implicitly converted to Secret*, and pick the +// second version otherwise. Since Secret is a secret and incomplete +// type, the only expression a user can write that has type Secret* is +// a null pointer literal. Therefore, we know that x is a null +// pointer literal if and only if the first version is picked by the +// compiler. +char IsNullLiteralHelper(Secret* p); +char (&IsNullLiteralHelper(...))[2]; // NOLINT + +// A compile-time bool constant that is true if and only if x is a +// null pointer literal (i.e. NULL or any 0-valued compile-time +// integral constant). +#ifdef GTEST_ELLIPSIS_NEEDS_POD_ +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_IS_NULL_LITERAL_(x) false +#else +# define GTEST_IS_NULL_LITERAL_(x) \ + (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) +#endif // GTEST_ELLIPSIS_NEEDS_POD_ + +// Appends the user-supplied message to the Google-Test-generated message. +GTEST_API_ String AppendUserMessage(const String& gtest_msg, + const Message& user_msg); + +// A helper class for creating scoped traces in user programs. +class GTEST_API_ ScopedTrace { + public: + // The c'tor pushes the given source file location and message onto + // a trace stack maintained by Google Test. + ScopedTrace(const char* file, int line, const Message& message); + + // The d'tor pops the info pushed by the c'tor. + // + // Note that the d'tor is not virtual in order to be efficient. + // Don't inherit from ScopedTrace! + ~ScopedTrace(); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); +} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its + // c'tor and d'tor. Therefore it doesn't + // need to be used otherwise. + +// Converts a streamable value to a String. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". +// Declared here but defined in gtest.h, so that it has access +// to the definition of the Message class, required by the ARM +// compiler. +template +String StreamableToString(const T& streamable); + +// The Symbian compiler has a bug that prevents it from selecting the +// correct overload of FormatForComparisonFailureMessage (see below) +// unless we pass the first argument by reference. If we do that, +// however, Visual Age C++ 10.1 generates a compiler error. Therefore +// we only apply the work-around for Symbian. +#if defined(__SYMBIAN32__) +# define GTEST_CREF_WORKAROUND_ const& +#else +# define GTEST_CREF_WORKAROUND_ +#endif + +// When this operand is a const char* or char*, if the other operand +// is a ::std::string or ::string, we print this operand as a C string +// rather than a pointer (we do the same for wide strings); otherwise +// we print it as a pointer to be safe. + +// This internal macro is used to avoid duplicated code. +#define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\ +inline String FormatForComparisonFailureMessage(\ + operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \ + const operand2_type& /*operand2*/) {\ + return operand1_printer(str);\ +}\ +inline String FormatForComparisonFailureMessage(\ + const operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \ + const operand2_type& /*operand2*/) {\ + return operand1_printer(str);\ +} + +GTEST_FORMAT_IMPL_(::std::string, String::ShowCStringQuoted) +#if GTEST_HAS_STD_WSTRING +GTEST_FORMAT_IMPL_(::std::wstring, String::ShowWideCStringQuoted) +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_STRING +GTEST_FORMAT_IMPL_(::string, String::ShowCStringQuoted) +#endif // GTEST_HAS_GLOBAL_STRING +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted) +#endif // GTEST_HAS_GLOBAL_WSTRING + +#undef GTEST_FORMAT_IMPL_ + +// The next four overloads handle the case where the operand being +// printed is a char/wchar_t pointer and the other operand is not a +// string/wstring object. In such cases, we just print the operand as +// a pointer to be safe. +#define GTEST_FORMAT_CHAR_PTR_IMPL_(CharType) \ + template \ + String FormatForComparisonFailureMessage(CharType* GTEST_CREF_WORKAROUND_ p, \ + const T&) { \ + return PrintToString(static_cast(p)); \ + } + +GTEST_FORMAT_CHAR_PTR_IMPL_(char) +GTEST_FORMAT_CHAR_PTR_IMPL_(const char) +GTEST_FORMAT_CHAR_PTR_IMPL_(wchar_t) +GTEST_FORMAT_CHAR_PTR_IMPL_(const wchar_t) + +#undef GTEST_FORMAT_CHAR_PTR_IMPL_ + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +GTEST_API_ AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const String& expected_value, + const String& actual_value, + bool ignoring_case); + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +GTEST_API_ String GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value); + +// This template class represents an IEEE floating-point number +// (either single-precision or double-precision, depending on the +// template parameters). +// +// The purpose of this class is to do more sophisticated number +// comparison. (Due to round-off error, etc, it's very unlikely that +// two floating-points will be equal exactly. Hence a naive +// comparison by the == operation often doesn't work.) +// +// Format of IEEE floating-point: +// +// The most-significant bit being the leftmost, an IEEE +// floating-point looks like +// +// sign_bit exponent_bits fraction_bits +// +// Here, sign_bit is a single bit that designates the sign of the +// number. +// +// For float, there are 8 exponent bits and 23 fraction bits. +// +// For double, there are 11 exponent bits and 52 fraction bits. +// +// More details can be found at +// http://en.wikipedia.org/wiki/IEEE_floating-point_standard. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +template +class FloatingPoint { + public: + // Defines the unsigned integer type that has the same size as the + // floating point number. + typedef typename TypeWithSize::UInt Bits; + + // Constants. + + // # of bits in a number. + static const size_t kBitCount = 8*sizeof(RawType); + + // # of fraction bits in a number. + static const size_t kFractionBitCount = + std::numeric_limits::digits - 1; + + // # of exponent bits in a number. + static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; + + // The mask for the sign bit. + static const Bits kSignBitMask = static_cast(1) << (kBitCount - 1); + + // The mask for the fraction bits. + static const Bits kFractionBitMask = + ~static_cast(0) >> (kExponentBitCount + 1); + + // The mask for the exponent bits. + static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); + + // How many ULP's (Units in the Last Place) we want to tolerate when + // comparing two numbers. The larger the value, the more error we + // allow. A 0 value means that two numbers must be exactly the same + // to be considered equal. + // + // The maximum error of a single floating-point operation is 0.5 + // units in the last place. On Intel CPU's, all floating-point + // calculations are done with 80-bit precision, while double has 64 + // bits. Therefore, 4 should be enough for ordinary use. + // + // See the following article for more details on ULP: + // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm. + static const size_t kMaxUlps = 4; + + // Constructs a FloatingPoint from a raw floating-point number. + // + // On an Intel CPU, passing a non-normalized NAN (Not a Number) + // around may change its bits, although the new value is guaranteed + // to be also a NAN. Therefore, don't expect this constructor to + // preserve the bits in x when x is a NAN. + explicit FloatingPoint(const RawType& x) { u_.value_ = x; } + + // Static methods + + // Reinterprets a bit pattern as a floating-point number. + // + // This function is needed to test the AlmostEquals() method. + static RawType ReinterpretBits(const Bits bits) { + FloatingPoint fp(0); + fp.u_.bits_ = bits; + return fp.u_.value_; + } + + // Returns the floating-point number that represent positive infinity. + static RawType Infinity() { + return ReinterpretBits(kExponentBitMask); + } + + // Non-static methods + + // Returns the bits that represents this number. + const Bits &bits() const { return u_.bits_; } + + // Returns the exponent bits of this number. + Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } + + // Returns the fraction bits of this number. + Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } + + // Returns the sign bit of this number. + Bits sign_bit() const { return kSignBitMask & u_.bits_; } + + // Returns true iff this is NAN (not a number). + bool is_nan() const { + // It's a NAN if the exponent bits are all ones and the fraction + // bits are not entirely zeros. + return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); + } + + // Returns true iff this number is at most kMaxUlps ULP's away from + // rhs. In particular, this function: + // + // - returns false if either number is (or both are) NAN. + // - treats really large numbers as almost equal to infinity. + // - thinks +0.0 and -0.0 are 0 DLP's apart. + bool AlmostEquals(const FloatingPoint& rhs) const { + // The IEEE standard says that any comparison operation involving + // a NAN must return false. + if (is_nan() || rhs.is_nan()) return false; + + return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) + <= kMaxUlps; + } + + private: + // The data type used to store the actual floating-point number. + union FloatingPointUnion { + RawType value_; // The raw floating-point number. + Bits bits_; // The bits that represent the number. + }; + + // Converts an integer from the sign-and-magnitude representation to + // the biased representation. More precisely, let N be 2 to the + // power of (kBitCount - 1), an integer x is represented by the + // unsigned number x + N. + // + // For instance, + // + // -N + 1 (the most negative number representable using + // sign-and-magnitude) is represented by 1; + // 0 is represented by N; and + // N - 1 (the biggest number representable using + // sign-and-magnitude) is represented by 2N - 1. + // + // Read http://en.wikipedia.org/wiki/Signed_number_representations + // for more details on signed number representations. + static Bits SignAndMagnitudeToBiased(const Bits &sam) { + if (kSignBitMask & sam) { + // sam represents a negative number. + return ~sam + 1; + } else { + // sam represents a positive number. + return kSignBitMask | sam; + } + } + + // Given two numbers in the sign-and-magnitude representation, + // returns the distance between them as an unsigned number. + static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, + const Bits &sam2) { + const Bits biased1 = SignAndMagnitudeToBiased(sam1); + const Bits biased2 = SignAndMagnitudeToBiased(sam2); + return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); + } + + FloatingPointUnion u_; +}; + +// Typedefs the instances of the FloatingPoint template class that we +// care to use. +typedef FloatingPoint Float; +typedef FloatingPoint Double; + +// In order to catch the mistake of putting tests that use different +// test fixture classes in the same test case, we need to assign +// unique IDs to fixture classes and compare them. The TypeId type is +// used to hold such IDs. The user should treat TypeId as an opaque +// type: the only operation allowed on TypeId values is to compare +// them for equality using the == operator. +typedef const void* TypeId; + +template +class TypeIdHelper { + public: + // dummy_ must not have a const type. Otherwise an overly eager + // compiler (e.g. MSVC 7.1 & 8.0) may try to merge + // TypeIdHelper::dummy_ for different Ts as an "optimization". + static bool dummy_; +}; + +template +bool TypeIdHelper::dummy_ = false; + +// GetTypeId() returns the ID of type T. Different values will be +// returned for different types. Calling the function twice with the +// same type argument is guaranteed to return the same ID. +template +TypeId GetTypeId() { + // The compiler is required to allocate a different + // TypeIdHelper::dummy_ variable for each T used to instantiate + // the template. Therefore, the address of dummy_ is guaranteed to + // be unique. + return &(TypeIdHelper::dummy_); +} + +// Returns the type ID of ::testing::Test. Always call this instead +// of GetTypeId< ::testing::Test>() to get the type ID of +// ::testing::Test, as the latter may give the wrong result due to a +// suspected linker bug when compiling Google Test as a Mac OS X +// framework. +GTEST_API_ TypeId GetTestTypeId(); + +// Defines the abstract factory interface that creates instances +// of a Test object. +class TestFactoryBase { + public: + virtual ~TestFactoryBase() {} + + // Creates a test instance to run. The instance is both created and destroyed + // within TestInfoImpl::Run() + virtual Test* CreateTest() = 0; + + protected: + TestFactoryBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase); +}; + +// This class provides implementation of TeastFactoryBase interface. +// It is used in TEST and TEST_F macros. +template +class TestFactoryImpl : public TestFactoryBase { + public: + virtual Test* CreateTest() { return new TestClass; } +}; + +#if GTEST_OS_WINDOWS + +// Predicate-formatters for implementing the HRESULT checking macros +// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} +// We pass a long instead of HRESULT to avoid causing an +// include dependency for the HRESULT type. +GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, + long hr); // NOLINT +GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, + long hr); // NOLINT + +#endif // GTEST_OS_WINDOWS + +// Types of SetUpTestCase() and TearDownTestCase() functions. +typedef void (*SetUpTestCaseFunc)(); +typedef void (*TearDownTestCaseFunc)(); + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param text representation of the test's value parameter, +// or NULL if this is not a type-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +GTEST_API_ TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory); + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// State of the definition of a type-parameterized test case. +class GTEST_API_ TypedTestCasePState { + public: + TypedTestCasePState() : registered_(false) {} + + // Adds the given test name to defined_test_names_ and return true + // if the test case hasn't been registered; otherwise aborts the + // program. + bool AddTestName(const char* file, int line, const char* case_name, + const char* test_name) { + if (registered_) { + fprintf(stderr, "%s Test %s must be defined before " + "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", + FormatFileLocation(file, line).c_str(), test_name, case_name); + fflush(stderr); + posix::Abort(); + } + defined_test_names_.insert(test_name); + return true; + } + + // Verifies that registered_tests match the test names in + // defined_test_names_; returns registered_tests if successful, or + // aborts the program otherwise. + const char* VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests); + + private: + bool registered_; + ::std::set defined_test_names_; +}; + +// Skips to the first non-space char after the first comma in 'str'; +// returns NULL if no comma is found in 'str'. +inline const char* SkipComma(const char* str) { + const char* comma = strchr(str, ','); + if (comma == NULL) { + return NULL; + } + while (IsSpace(*(++comma))) {} + return comma; +} + +// Returns the prefix of 'str' before the first comma in it; returns +// the entire string if it contains no comma. +inline String GetPrefixUntilComma(const char* str) { + const char* comma = strchr(str, ','); + return comma == NULL ? String(str) : String(str, comma - str); +} + +// TypeParameterizedTest::Register() +// registers a list of type-parameterized tests with Google Test. The +// return value is insignificant - we just need to return something +// such that we can call this function in a namespace scope. +// +// Implementation note: The GTEST_TEMPLATE_ macro declares a template +// template parameter. It's defined in gtest-type-util.h. +template +class TypeParameterizedTest { + public: + // 'index' is the index of the test in the type list 'Types' + // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, + // Types). Valid values for 'index' are [0, N - 1] where N is the + // length of Types. + static bool Register(const char* prefix, const char* case_name, + const char* test_names, int index) { + typedef typename Types::Head Type; + typedef Fixture FixtureClass; + typedef typename GTEST_BIND_(TestSel, Type) TestClass; + + // First, registers the first type-parameterized test in the type + // list. + MakeAndRegisterTestInfo( + String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/", + case_name, index).c_str(), + GetPrefixUntilComma(test_names).c_str(), + GetTypeName().c_str(), + NULL, // No value parameter. + GetTypeId(), + TestClass::SetUpTestCase, + TestClass::TearDownTestCase, + new TestFactoryImpl); + + // Next, recurses (at compile time) with the tail of the type list. + return TypeParameterizedTest + ::Register(prefix, case_name, test_names, index + 1); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTest { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/, int /*index*/) { + return true; + } +}; + +// TypeParameterizedTestCase::Register() +// registers *all combinations* of 'Tests' and 'Types' with Google +// Test. The return value is insignificant - we just need to return +// something such that we can call this function in a namespace scope. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* prefix, const char* case_name, + const char* test_names) { + typedef typename Tests::Head Head; + + // First, register the first test in 'Test' for each type in 'Types'. + TypeParameterizedTest::Register( + prefix, case_name, test_names, 0); + + // Next, recurses (at compile time) with the tail of the test list. + return TypeParameterizedTestCase + ::Register(prefix, case_name, SkipComma(test_names)); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/) { + return true; + } +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// Returns the current OS stack trace as a String. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +GTEST_API_ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test, + int skip_count); + +// Helpers for suppressing warnings on unreachable code or constant +// condition. + +// Always returns true. +GTEST_API_ bool AlwaysTrue(); + +// Always returns false. +inline bool AlwaysFalse() { return !AlwaysTrue(); } + +// Helper for suppressing false warning from Clang on a const char* +// variable declared in a conditional expression always being NULL in +// the else branch. +struct GTEST_API_ ConstCharPtr { + ConstCharPtr(const char* str) : value(str) {} + operator bool() const { return true; } + const char* value; +}; + +// A simple Linear Congruential Generator for generating random +// numbers with a uniform distribution. Unlike rand() and srand(), it +// doesn't use global state (and therefore can't interfere with user +// code). Unlike rand_r(), it's portable. An LCG isn't very random, +// but it's good enough for our purposes. +class GTEST_API_ Random { + public: + static const UInt32 kMaxRange = 1u << 31; + + explicit Random(UInt32 seed) : state_(seed) {} + + void Reseed(UInt32 seed) { state_ = seed; } + + // Generates a random number from [0, range). Crashes if 'range' is + // 0 or greater than kMaxRange. + UInt32 Generate(UInt32 range); + + private: + UInt32 state_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); +}; + +// Defining a variable of type CompileAssertTypesEqual will cause a +// compiler error iff T1 and T2 are different types. +template +struct CompileAssertTypesEqual; + +template +struct CompileAssertTypesEqual { +}; + +// Removes the reference from a type if it is a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::remove_reference, which is not widely available yet. +template +struct RemoveReference { typedef T type; }; // NOLINT +template +struct RemoveReference { typedef T type; }; // NOLINT + +// A handy wrapper around RemoveReference that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_REFERENCE_(T) \ + typename ::testing::internal::RemoveReference::type + +// Removes const from a type if it is a const type, otherwise leaves +// it unchanged. This is the same as tr1::remove_const, which is not +// widely available yet. +template +struct RemoveConst { typedef T type; }; // NOLINT +template +struct RemoveConst { typedef T type; }; // NOLINT + +// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above +// definition to fail to remove the const in 'const int[3]' and 'const +// char[3][4]'. The following specialization works around the bug. +// However, it causes trouble with GCC and thus needs to be +// conditionally compiled. +#if defined(_MSC_VER) || defined(__SUNPRO_CC) || defined(__IBMCPP__) +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; +#endif + +// A handy wrapper around RemoveConst that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_CONST_(T) \ + typename ::testing::internal::RemoveConst::type + +// Turns const U&, U&, const U, and U all into U. +#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ + GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) + +// Adds reference to a type if it is not a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::add_reference, which is not widely available yet. +template +struct AddReference { typedef T& type; }; // NOLINT +template +struct AddReference { typedef T& type; }; // NOLINT + +// A handy wrapper around AddReference that works when the argument T +// depends on template parameters. +#define GTEST_ADD_REFERENCE_(T) \ + typename ::testing::internal::AddReference::type + +// Adds a reference to const on top of T as necessary. For example, +// it transforms +// +// char ==> const char& +// const char ==> const char& +// char& ==> const char& +// const char& ==> const char& +// +// The argument T must depend on some template parameters. +#define GTEST_REFERENCE_TO_CONST_(T) \ + GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T)) + +// ImplicitlyConvertible::value is a compile-time bool +// constant that's true iff type From can be implicitly converted to +// type To. +template +class ImplicitlyConvertible { + private: + // We need the following helper functions only for their types. + // They have no implementations. + + // MakeFrom() is an expression whose type is From. We cannot simply + // use From(), as the type From may not have a public default + // constructor. + static From MakeFrom(); + + // These two functions are overloaded. Given an expression + // Helper(x), the compiler will pick the first version if x can be + // implicitly converted to type To; otherwise it will pick the + // second version. + // + // The first version returns a value of size 1, and the second + // version returns a value of size 2. Therefore, by checking the + // size of Helper(x), which can be done at compile time, we can tell + // which version of Helper() is used, and hence whether x can be + // implicitly converted to type To. + static char Helper(To); + static char (&Helper(...))[2]; // NOLINT + + // We have to put the 'public' section after the 'private' section, + // or MSVC refuses to compile the code. + public: + // MSVC warns about implicitly converting from double to int for + // possible loss of data, so we need to temporarily disable the + // warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4244) // Temporarily disables warning 4244. + + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +# pragma warning(pop) // Restores the warning state. +#elif defined(__BORLANDC__) + // C++Builder cannot use member overload resolution during template + // instantiation. The simplest workaround is to use its C++0x type traits + // functions (C++Builder 2009 and above only). + static const bool value = __is_convertible(From, To); +#else + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +#endif // _MSV_VER +}; +template +const bool ImplicitlyConvertible::value; + +// IsAProtocolMessage::value is a compile-time bool constant that's +// true iff T is type ProtocolMessage, proto2::Message, or a subclass +// of those. +template +struct IsAProtocolMessage + : public bool_constant< + ImplicitlyConvertible::value || + ImplicitlyConvertible::value> { +}; + +// When the compiler sees expression IsContainerTest(0), if C is an +// STL-style container class, the first overload of IsContainerTest +// will be viable (since both C::iterator* and C::const_iterator* are +// valid types and NULL can be implicitly converted to them). It will +// be picked over the second overload as 'int' is a perfect match for +// the type of argument 0. If C::iterator or C::const_iterator is not +// a valid type, the first overload is not viable, and the second +// overload will be picked. Therefore, we can determine whether C is +// a container class by checking the type of IsContainerTest(0). +// The value of the expression is insignificant. +// +// Note that we look for both C::iterator and C::const_iterator. The +// reason is that C++ injects the name of a class as a member of the +// class itself (e.g. you can refer to class iterator as either +// 'iterator' or 'iterator::iterator'). If we look for C::iterator +// only, for example, we would mistakenly think that a class named +// iterator is an STL container. +// +// Also note that the simpler approach of overloading +// IsContainerTest(typename C::const_iterator*) and +// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. +typedef int IsContainer; +template +IsContainer IsContainerTest(int /* dummy */, + typename C::iterator* /* it */ = NULL, + typename C::const_iterator* /* const_it */ = NULL) { + return 0; +} + +typedef char IsNotContainer; +template +IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } + +// EnableIf::type is void when 'Cond' is true, and +// undefined when 'Cond' is false. To use SFINAE to make a function +// overload only apply when a particular expression is true, add +// "typename EnableIf::type* = 0" as the last parameter. +template struct EnableIf; +template<> struct EnableIf { typedef void type; }; // NOLINT + +// Utilities for native arrays. + +// ArrayEq() compares two k-dimensional native arrays using the +// elements' operator==, where k can be any integer >= 0. When k is +// 0, ArrayEq() degenerates into comparing a single pair of values. + +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs); + +// This generic version is used when k is 0. +template +inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } + +// This overload is used when k >= 1. +template +inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { + return internal::ArrayEq(lhs, N, rhs); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous ArrayEq() function, arrays with different sizes would +// lead to different copies of the template code. +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs) { + for (size_t i = 0; i != size; i++) { + if (!internal::ArrayEq(lhs[i], rhs[i])) + return false; + } + return true; +} + +// Finds the first element in the iterator range [begin, end) that +// equals elem. Element may be a native array type itself. +template +Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { + for (Iter it = begin; it != end; ++it) { + if (internal::ArrayEq(*it, elem)) + return it; + } + return end; +} + +// CopyArray() copies a k-dimensional native array using the elements' +// operator=, where k can be any integer >= 0. When k is 0, +// CopyArray() degenerates into copying a single value. + +template +void CopyArray(const T* from, size_t size, U* to); + +// This generic version is used when k is 0. +template +inline void CopyArray(const T& from, U* to) { *to = from; } + +// This overload is used when k >= 1. +template +inline void CopyArray(const T(&from)[N], U(*to)[N]) { + internal::CopyArray(from, N, *to); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous CopyArray() function, arrays with different sizes +// would lead to different copies of the template code. +template +void CopyArray(const T* from, size_t size, U* to) { + for (size_t i = 0; i != size; i++) { + internal::CopyArray(from[i], to + i); + } +} + +// The relation between an NativeArray object (see below) and the +// native array it represents. +enum RelationToSource { + kReference, // The NativeArray references the native array. + kCopy // The NativeArray makes a copy of the native array and + // owns the copy. +}; + +// Adapts a native array to a read-only STL-style container. Instead +// of the complete STL container concept, this adaptor only implements +// members useful for Google Mock's container matchers. New members +// should be added as needed. To simplify the implementation, we only +// support Element being a raw type (i.e. having no top-level const or +// reference modifier). It's the client's responsibility to satisfy +// this requirement. Element can be an array type itself (hence +// multi-dimensional arrays are supported). +template +class NativeArray { + public: + // STL-style container typedefs. + typedef Element value_type; + typedef Element* iterator; + typedef const Element* const_iterator; + + // Constructs from a native array. + NativeArray(const Element* array, size_t count, RelationToSource relation) { + Init(array, count, relation); + } + + // Copy constructor. + NativeArray(const NativeArray& rhs) { + Init(rhs.array_, rhs.size_, rhs.relation_to_source_); + } + + ~NativeArray() { + // Ensures that the user doesn't instantiate NativeArray with a + // const or reference type. + static_cast(StaticAssertTypeEqHelper()); + if (relation_to_source_ == kCopy) + delete[] array_; + } + + // STL-style container methods. + size_t size() const { return size_; } + const_iterator begin() const { return array_; } + const_iterator end() const { return array_ + size_; } + bool operator==(const NativeArray& rhs) const { + return size() == rhs.size() && + ArrayEq(begin(), size(), rhs.begin()); + } + + private: + // Initializes this object; makes a copy of the input array if + // 'relation' is kCopy. + void Init(const Element* array, size_t a_size, RelationToSource relation) { + if (relation == kReference) { + array_ = array; + } else { + Element* const copy = new Element[a_size]; + CopyArray(array, a_size, copy); + array_ = copy; + } + size_ = a_size; + relation_to_source_ = relation; + } + + const Element* array_; + size_t size_; + RelationToSource relation_to_source_; + + GTEST_DISALLOW_ASSIGN_(NativeArray); +}; + +} // namespace internal +} // namespace testing + +#define GTEST_MESSAGE_AT_(file, line, message, result_type) \ + ::testing::internal::AssertHelper(result_type, file, line, message) \ + = ::testing::Message() + +#define GTEST_MESSAGE_(message, result_type) \ + GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) + +#define GTEST_FATAL_FAILURE_(message) \ + return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) + +#define GTEST_NONFATAL_FAILURE_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) + +#define GTEST_SUCCESS_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) + +// Suppresses MSVC warnings 4072 (unreachable code) for the code following +// statement if it returns or throws (or doesn't return or throw in some +// situations). +#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ + if (::testing::internal::AlwaysTrue()) { statement; } + +#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::ConstCharPtr gtest_msg = "") { \ + bool gtest_caught_expected = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + catch (...) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws a different type."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws nothing."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ + fail(gtest_msg.value) + +#define GTEST_TEST_NO_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ + fail("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: it throws.") + +#define GTEST_TEST_ANY_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + bool gtest_caught_any = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + gtest_caught_any = true; \ + } \ + if (!gtest_caught_any) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ + fail("Expected: " #statement " throws an exception.\n" \ + " Actual: it doesn't.") + + +// Implements Boolean test assertions such as EXPECT_TRUE. expression can be +// either a boolean expression or an AssertionResult. text is a textual +// represenation of expression as it was passed into the EXPECT_TRUE. +#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar_ = \ + ::testing::AssertionResult(expression)) \ + ; \ + else \ + fail(::testing::internal::GetBoolAssertionFailureMessage(\ + gtest_ar_, text, #actual, #expected).c_str()) + +#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \ + fail("Expected: " #statement " doesn't generate new fatal " \ + "failures in the current thread.\n" \ + " Actual: it does.") + +// Expands to the name of the class that implements the given test. +#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + test_case_name##_##test_name##_Test + +// Helper macro for defining tests. +#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ +class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ + public:\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ + private:\ + virtual void TestBody();\ + static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ +};\ +\ +::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ + ::test_info_ =\ + ::testing::internal::MakeAndRegisterTestInfo(\ + #test_case_name, #test_name, NULL, NULL, \ + (parent_id), \ + parent_class::SetUpTestCase, \ + parent_class::TearDownTestCase, \ + new ::testing::internal::TestFactoryImpl<\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ +void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for death tests. It is +// #included by gtest.h so a user doesn't need to include this +// directly. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines internal utilities needed for implementing +// death tests. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + + +#include + +namespace testing { +namespace internal { + +GTEST_DECLARE_string_(internal_run_death_test); + +// Names of the flags (needed for parsing Google Test flags). +const char kDeathTestStyleFlag[] = "death_test_style"; +const char kDeathTestUseFork[] = "death_test_use_fork"; +const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; + +#if GTEST_HAS_DEATH_TEST + +// DeathTest is a class that hides much of the complexity of the +// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method +// returns a concrete class that depends on the prevailing death test +// style, as defined by the --gtest_death_test_style and/or +// --gtest_internal_run_death_test flags. + +// In describing the results of death tests, these terms are used with +// the corresponding definitions: +// +// exit status: The integer exit information in the format specified +// by wait(2) +// exit code: The integer code passed to exit(3), _exit(2), or +// returned from main() +class GTEST_API_ DeathTest { + public: + // Create returns false if there was an error determining the + // appropriate action to take for the current death test; for example, + // if the gtest_death_test_style flag is set to an invalid value. + // The LastMessage method will return a more detailed message in that + // case. Otherwise, the DeathTest pointer pointed to by the "test" + // argument is set. If the death test should be skipped, the pointer + // is set to NULL; otherwise, it is set to the address of a new concrete + // DeathTest object that controls the execution of the current test. + static bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); + DeathTest(); + virtual ~DeathTest() { } + + // A helper class that aborts a death test when it's deleted. + class ReturnSentinel { + public: + explicit ReturnSentinel(DeathTest* test) : test_(test) { } + ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } + private: + DeathTest* const test_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); + } GTEST_ATTRIBUTE_UNUSED_; + + // An enumeration of possible roles that may be taken when a death + // test is encountered. EXECUTE means that the death test logic should + // be executed immediately. OVERSEE means that the program should prepare + // the appropriate environment for a child process to execute the death + // test, then wait for it to complete. + enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; + + // An enumeration of the three reasons that a test might be aborted. + enum AbortReason { + TEST_ENCOUNTERED_RETURN_STATEMENT, + TEST_THREW_EXCEPTION, + TEST_DID_NOT_DIE + }; + + // Assumes one of the above roles. + virtual TestRole AssumeRole() = 0; + + // Waits for the death test to finish and returns its status. + virtual int Wait() = 0; + + // Returns true if the death test passed; that is, the test process + // exited during the test, its exit status matches a user-supplied + // predicate, and its stderr output matches a user-supplied regular + // expression. + // The user-supplied predicate may be a macro expression rather + // than a function pointer or functor, or else Wait and Passed could + // be combined. + virtual bool Passed(bool exit_status_ok) = 0; + + // Signals that the death test did not die as expected. + virtual void Abort(AbortReason reason) = 0; + + // Returns a human-readable outcome message regarding the outcome of + // the last death test. + static const char* LastMessage(); + + static void set_last_death_test_message(const String& message); + + private: + // A string containing a description of the outcome of the last death test. + static String last_death_test_message_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); +}; + +// Factory interface for death tests. May be mocked out for testing. +class DeathTestFactory { + public: + virtual ~DeathTestFactory() { } + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) = 0; +}; + +// A concrete DeathTestFactory implementation for normal use. +class DefaultDeathTestFactory : public DeathTestFactory { + public: + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); +}; + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +GTEST_API_ bool ExitedUnsuccessfully(int exit_status); + +// Traps C++ exceptions escaping statement and reports them as test +// failures. Note that trapping SEH exceptions is not implemented here. +# if GTEST_HAS_EXCEPTIONS +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } catch (const ::std::exception& gtest_exception) { \ + fprintf(\ + stderr, \ + "\n%s: Caught std::exception-derived exception escaping the " \ + "death test statement. Exception message: %s\n", \ + ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ + gtest_exception.what()); \ + fflush(stderr); \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } catch (...) { \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } + +# else +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) + +# endif + +// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, +// ASSERT_EXIT*, and EXPECT_EXIT*. +# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + const ::testing::internal::RE& gtest_regex = (regex); \ + ::testing::internal::DeathTest* gtest_dt; \ + if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ + __FILE__, __LINE__, >est_dt)) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + if (gtest_dt != NULL) { \ + ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \ + gtest_dt_ptr(gtest_dt); \ + switch (gtest_dt->AssumeRole()) { \ + case ::testing::internal::DeathTest::OVERSEE_TEST: \ + if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + break; \ + case ::testing::internal::DeathTest::EXECUTE_TEST: { \ + ::testing::internal::DeathTest::ReturnSentinel \ + gtest_sentinel(gtest_dt); \ + GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ + gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \ + fail(::testing::internal::DeathTest::LastMessage()) +// The symbol "fail" here expands to something into which a message +// can be streamed. + +// A class representing the parsed contents of the +// --gtest_internal_run_death_test flag, as it existed when +// RUN_ALL_TESTS was called. +class InternalRunDeathTestFlag { + public: + InternalRunDeathTestFlag(const String& a_file, + int a_line, + int an_index, + int a_write_fd) + : file_(a_file), line_(a_line), index_(an_index), + write_fd_(a_write_fd) {} + + ~InternalRunDeathTestFlag() { + if (write_fd_ >= 0) + posix::Close(write_fd_); + } + + String file() const { return file_; } + int line() const { return line_; } + int index() const { return index_; } + int write_fd() const { return write_fd_; } + + private: + String file_; + int line_; + int index_; + int write_fd_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); +}; + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); + +#else // GTEST_HAS_DEATH_TEST + +// This macro is used for implementing macros such as +// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where +// death tests are not supported. Those macros must compile on such systems +// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on +// systems that support death tests. This allows one to write such a macro +// on a system that does not support death tests and be sure that it will +// compile on a death-test supporting system. +// +// Parameters: +// statement - A statement that a macro such as EXPECT_DEATH would test +// for program termination. This macro has to make sure this +// statement is compiled but not executed, to ensure that +// EXPECT_DEATH_IF_SUPPORTED compiles with a certain +// parameter iff EXPECT_DEATH compiles with it. +// regex - A regex that a macro such as EXPECT_DEATH would use to test +// the output of statement. This parameter has to be +// compiled but not evaluated by this macro, to ensure that +// this macro only accepts expressions that a macro such as +// EXPECT_DEATH would accept. +// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED +// and a return statement for ASSERT_DEATH_IF_SUPPORTED. +// This ensures that ASSERT_DEATH_IF_SUPPORTED will not +// compile inside functions where ASSERT_DEATH doesn't +// compile. +// +// The branch that has an always false condition is used to ensure that +// statement and regex are compiled (and thus syntactically correct) but +// never executed. The unreachable code macro protects the terminator +// statement from generating an 'unreachable code' warning in case +// statement unconditionally returns or throws. The Message constructor at +// the end allows the syntax of streaming additional messages into the +// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. +# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_LOG_(WARNING) \ + << "Death tests are not supported on this platform.\n" \ + << "Statement '" #statement "' cannot be verified."; \ + } else if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::RE::PartialMatch(".*", (regex)); \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + terminator; \ + } else \ + ::testing::Message() + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + +namespace testing { + +// This flag controls the style of death tests. Valid values are "threadsafe", +// meaning that the death test child process will re-execute the test binary +// from the start, running only a single death test, or "fast", +// meaning that the child process will execute the test logic immediately +// after forking. +GTEST_DECLARE_string_(death_test_style); + +#if GTEST_HAS_DEATH_TEST + +// The following macros are useful for writing death tests. + +// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is +// executed: +// +// 1. It generates a warning if there is more than one active +// thread. This is because it's safe to fork() or clone() only +// when there is a single thread. +// +// 2. The parent process clone()s a sub-process and runs the death +// test in it; the sub-process exits with code 0 at the end of the +// death test, if it hasn't exited already. +// +// 3. The parent process waits for the sub-process to terminate. +// +// 4. The parent process checks the exit code and error message of +// the sub-process. +// +// Examples: +// +// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); +// for (int i = 0; i < 5; i++) { +// EXPECT_DEATH(server.ProcessRequest(i), +// "Invalid request .* in ProcessRequest()") +// << "Failed to die on request " << i); +// } +// +// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting"); +// +// bool KilledBySIGHUP(int exit_code) { +// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP; +// } +// +// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); +// +// On the regular expressions used in death tests: +// +// On POSIX-compliant systems (*nix), we use the library, +// which uses the POSIX extended regex syntax. +// +// On other platforms (e.g. Windows), we only support a simple regex +// syntax implemented as part of Google Test. This limited +// implementation should be enough most of the time when writing +// death tests; though it lacks many features you can find in PCRE +// or POSIX extended regex syntax. For example, we don't support +// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and +// repetition count ("x{5,7}"), among others. +// +// Below is the syntax that we do support. We chose it to be a +// subset of both PCRE and POSIX extended regex, so it's easy to +// learn wherever you come from. In the following: 'A' denotes a +// literal character, period (.), or a single \\ escape sequence; +// 'x' and 'y' denote regular expressions; 'm' and 'n' are for +// natural numbers. +// +// c matches any literal character c +// \\d matches any decimal digit +// \\D matches any character that's not a decimal digit +// \\f matches \f +// \\n matches \n +// \\r matches \r +// \\s matches any ASCII whitespace, including \n +// \\S matches any character that's not a whitespace +// \\t matches \t +// \\v matches \v +// \\w matches any letter, _, or decimal digit +// \\W matches any character that \\w doesn't match +// \\c matches any literal character c, which must be a punctuation +// . matches any single character except \n +// A? matches 0 or 1 occurrences of A +// A* matches 0 or many occurrences of A +// A+ matches 1 or many occurrences of A +// ^ matches the beginning of a string (not that of each line) +// $ matches the end of a string (not that of each line) +// xy matches x followed by y +// +// If you accidentally use PCRE or POSIX extended regex features +// not implemented by us, you will get a run-time failure. In that +// case, please try to rewrite your regular expression within the +// above syntax. +// +// This implementation is *not* meant to be as highly tuned or robust +// as a compiled regex library, but should perform well enough for a +// death test, which already incurs significant overhead by launching +// a child process. +// +// Known caveats: +// +// A "threadsafe" style death test obtains the path to the test +// program from argv[0] and re-executes it in the sub-process. For +// simplicity, the current implementation doesn't search the PATH +// when launching the sub-process. This means that the user must +// invoke the test program via a path that contains at least one +// path separator (e.g. path/to/foo_test and +// /absolute/path/to/bar_test are fine, but foo_test is not). This +// is rarely a problem as people usually don't put the test binary +// directory in PATH. +// +// TODO(wan@google.com): make thread-safe death tests search the PATH. + +// Asserts that a given statement causes the program to exit, with an +// integer exit status that satisfies predicate, and emitting error output +// that matches regex. +# define ASSERT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) + +// Like ASSERT_EXIT, but continues on to successive tests in the +// test case, if any: +# define EXPECT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) + +// Asserts that a given statement causes the program to exit, either by +// explicitly exiting with a nonzero exit code or being killed by a +// signal, and emitting error output that matches regex. +# define ASSERT_DEATH(statement, regex) \ + ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Like ASSERT_DEATH, but continues on to successive tests in the +// test case, if any: +# define EXPECT_DEATH(statement, regex) \ + EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: + +// Tests that an exit code describes a normal exit with a given exit code. +class GTEST_API_ ExitedWithCode { + public: + explicit ExitedWithCode(int exit_code); + bool operator()(int exit_status) const; + private: + // No implementation - assignment is unsupported. + void operator=(const ExitedWithCode& other); + + const int exit_code_; +}; + +# if !GTEST_OS_WINDOWS +// Tests that an exit code describes an exit due to termination by a +// given signal. +class GTEST_API_ KilledBySignal { + public: + explicit KilledBySignal(int signum); + bool operator()(int exit_status) const; + private: + const int signum_; +}; +# endif // !GTEST_OS_WINDOWS + +// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. +// The death testing framework causes this to have interesting semantics, +// since the sideeffects of the call are only visible in opt mode, and not +// in debug mode. +// +// In practice, this can be used to test functions that utilize the +// LOG(DFATAL) macro using the following style: +// +// int DieInDebugOr12(int* sideeffect) { +// if (sideeffect) { +// *sideeffect = 12; +// } +// LOG(DFATAL) << "death"; +// return 12; +// } +// +// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) { +// int sideeffect = 0; +// // Only asserts in dbg. +// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); +// +// #ifdef NDEBUG +// // opt-mode has sideeffect visible. +// EXPECT_EQ(12, sideeffect); +// #else +// // dbg-mode no visible sideeffect. +// EXPECT_EQ(0, sideeffect); +// #endif +// } +// +// This will assert that DieInDebugReturn12InOpt() crashes in debug +// mode, usually due to a DCHECK or LOG(DFATAL), but returns the +// appropriate fallback value (12 in this case) in opt mode. If you +// need to test that a function has appropriate side-effects in opt +// mode, include assertions against the side-effects. A general +// pattern for this is: +// +// EXPECT_DEBUG_DEATH({ +// // Side-effects here will have an effect after this statement in +// // opt mode, but none in debug mode. +// EXPECT_EQ(12, DieInDebugOr12(&sideeffect)); +// }, "death"); +// +# ifdef NDEBUG + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + do { statement; } while (::testing::internal::AlwaysFalse()) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + do { statement; } while (::testing::internal::AlwaysFalse()) + +# else + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + EXPECT_DEATH(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + ASSERT_DEATH(statement, regex) + +# endif // NDEBUG for EXPECT_DEBUG_DEATH +#endif // GTEST_HAS_DEATH_TEST + +// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and +// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if +// death tests are supported; otherwise they just issue a warning. This is +// useful when you are combining death test assertions with normal test +// assertions in one test. +#if GTEST_HAS_DEATH_TEST +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + EXPECT_DEATH(statement, regex) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + ASSERT_DEATH(statement, regex) +#else +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) +#endif + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the Message class. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! + +#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ + +#include + + +namespace testing { + +// The Message class works like an ostream repeater. +// +// Typical usage: +// +// 1. You stream a bunch of values to a Message object. +// It will remember the text in a stringstream. +// 2. Then you stream the Message object to an ostream. +// This causes the text in the Message to be streamed +// to the ostream. +// +// For example; +// +// testing::Message foo; +// foo << 1 << " != " << 2; +// std::cout << foo; +// +// will print "1 != 2". +// +// Message is not intended to be inherited from. In particular, its +// destructor is not virtual. +// +// Note that stringstream behaves differently in gcc and in MSVC. You +// can stream a NULL char pointer to it in the former, but not in the +// latter (it causes an access violation if you do). The Message +// class hides this difference by treating a NULL char pointer as +// "(null)". +class GTEST_API_ Message { + private: + // The type of basic IO manipulators (endl, ends, and flush) for + // narrow streams. + typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); + + public: + // Constructs an empty Message. + // We allocate the stringstream separately because otherwise each use of + // ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's + // stack frame leading to huge stack frames in some cases; gcc does not reuse + // the stack space. + Message() : ss_(new ::std::stringstream) { + // By default, we want there to be enough precision when printing + // a double to a Message. + *ss_ << std::setprecision(std::numeric_limits::digits10 + 2); + } + + // Copy constructor. + Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT + *ss_ << msg.GetString(); + } + + // Constructs a Message from a C-string. + explicit Message(const char* str) : ss_(new ::std::stringstream) { + *ss_ << str; + } + +#if GTEST_OS_SYMBIAN + // Streams a value (either a pointer or not) to this object. + template + inline Message& operator <<(const T& value) { + StreamHelper(typename internal::is_pointer::type(), value); + return *this; + } +#else + // Streams a non-pointer value to this object. + template + inline Message& operator <<(const T& val) { + ::GTestStreamToHelper(ss_.get(), val); + return *this; + } + + // Streams a pointer value to this object. + // + // This function is an overload of the previous one. When you + // stream a pointer to a Message, this definition will be used as it + // is more specialized. (The C++ Standard, section + // [temp.func.order].) If you stream a non-pointer, then the + // previous definition will be used. + // + // The reason for this overload is that streaming a NULL pointer to + // ostream is undefined behavior. Depending on the compiler, you + // may get "0", "(nil)", "(null)", or an access violation. To + // ensure consistent result across compilers, we always treat NULL + // as "(null)". + template + inline Message& operator <<(T* const& pointer) { // NOLINT + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + ::GTestStreamToHelper(ss_.get(), pointer); + } + return *this; + } +#endif // GTEST_OS_SYMBIAN + + // Since the basic IO manipulators are overloaded for both narrow + // and wide streams, we have to provide this specialized definition + // of operator <<, even though its body is the same as the + // templatized version above. Without this definition, streaming + // endl or other basic IO manipulators to Message will confuse the + // compiler. + Message& operator <<(BasicNarrowIoManip val) { + *ss_ << val; + return *this; + } + + // Instead of 1/0, we want to see true/false for bool values. + Message& operator <<(bool b) { + return *this << (b ? "true" : "false"); + } + + // These two overloads allow streaming a wide C string to a Message + // using the UTF-8 encoding. + Message& operator <<(const wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); + } + Message& operator <<(wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); + } + +#if GTEST_HAS_STD_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::std::wstring& wstr); +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::wstring& wstr); +#endif // GTEST_HAS_GLOBAL_WSTRING + + // Gets the text streamed to this object so far as a String. + // Each '\0' character in the buffer is replaced with "\\0". + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + internal::String GetString() const { + return internal::StringStreamToString(ss_.get()); + } + + private: + +#if GTEST_OS_SYMBIAN + // These are needed as the Nokia Symbian Compiler cannot decide between + // const T& and const T* in a function template. The Nokia compiler _can_ + // decide between class template specializations for T and T*, so a + // tr1::type_traits-like is_pointer works, and we can overload on that. + template + inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) { + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + ::GTestStreamToHelper(ss_.get(), pointer); + } + } + template + inline void StreamHelper(internal::false_type /*dummy*/, const T& value) { + ::GTestStreamToHelper(ss_.get(), value); + } +#endif // GTEST_OS_SYMBIAN + + // We'll hold the text streamed to this object here. + const internal::scoped_ptr< ::std::stringstream> ss_; + + // We declare (but don't implement) this to prevent the compiler + // from implementing the assignment operator. + void operator=(const Message&); +}; + +// Streams a Message to an ostream. +inline std::ostream& operator <<(std::ostream& os, const Message& sb) { + return os << sb.GetString(); +} + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +// This file was GENERATED by command: +// pump.py gtest-param-test.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: vladl@google.com (Vlad Losev) +// +// Macros and functions for implementing parameterized tests +// in Google C++ Testing Framework (Google Test) +// +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ + + +// Value-parameterized tests allow you to test your code with different +// parameters without writing multiple copies of the same test. +// +// Here is how you use value-parameterized tests: + +#if 0 + +// To write value-parameterized tests, first you should define a fixture +// class. It is usually derived from testing::TestWithParam (see below for +// another inheritance scheme that's sometimes useful in more complicated +// class hierarchies), where the type of your parameter values. +// TestWithParam is itself derived from testing::Test. T can be any +// copyable type. If it's a raw pointer, you are responsible for managing the +// lifespan of the pointed values. + +class FooTest : public ::testing::TestWithParam { + // You can implement all the usual class fixture members here. +}; + +// Then, use the TEST_P macro to define as many parameterized tests +// for this fixture as you want. The _P suffix is for "parameterized" +// or "pattern", whichever you prefer to think. + +TEST_P(FooTest, DoesBlah) { + // Inside a test, access the test parameter with the GetParam() method + // of the TestWithParam class: + EXPECT_TRUE(foo.Blah(GetParam())); + ... +} + +TEST_P(FooTest, HasBlahBlah) { + ... +} + +// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test +// case with any set of parameters you want. Google Test defines a number +// of functions for generating test parameters. They return what we call +// (surprise!) parameter generators. Here is a summary of them, which +// are all in the testing namespace: +// +// +// Range(begin, end [, step]) - Yields values {begin, begin+step, +// begin+step+step, ...}. The values do not +// include end. step defaults to 1. +// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. +// ValuesIn(container) - Yields values from a C-style array, an STL +// ValuesIn(begin,end) container, or an iterator range [begin, end). +// Bool() - Yields sequence {false, true}. +// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product +// for the math savvy) of the values generated +// by the N generators. +// +// For more details, see comments at the definitions of these functions below +// in this file. +// +// The following statement will instantiate tests from the FooTest test case +// each with parameter values "meeny", "miny", and "moe". + +INSTANTIATE_TEST_CASE_P(InstantiationName, + FooTest, + Values("meeny", "miny", "moe")); + +// To distinguish different instances of the pattern, (yes, you +// can instantiate it more then once) the first argument to the +// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the +// actual test case name. Remember to pick unique prefixes for different +// instantiations. The tests from the instantiation above will have +// these names: +// +// * InstantiationName/FooTest.DoesBlah/0 for "meeny" +// * InstantiationName/FooTest.DoesBlah/1 for "miny" +// * InstantiationName/FooTest.DoesBlah/2 for "moe" +// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" +// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" +// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" +// +// You can use these names in --gtest_filter. +// +// This statement will instantiate all tests from FooTest again, each +// with parameter values "cat" and "dog": + +const char* pets[] = {"cat", "dog"}; +INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); + +// The tests from the instantiation above will have these names: +// +// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" +// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" +// +// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests +// in the given test case, whether their definitions come before or +// AFTER the INSTANTIATE_TEST_CASE_P statement. +// +// Please also note that generator expressions (including parameters to the +// generators) are evaluated in InitGoogleTest(), after main() has started. +// This allows the user on one hand, to adjust generator parameters in order +// to dynamically determine a set of tests to run and on the other hand, +// give the user a chance to inspect the generated tests with Google Test +// reflection API before RUN_ALL_TESTS() is executed. +// +// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc +// for more examples. +// +// In the future, we plan to publish the API for defining new parameter +// generators. But for now this interface remains part of the internal +// implementation and is subject to change. +// +// +// A parameterized test fixture must be derived from testing::Test and from +// testing::WithParamInterface, where T is the type of the parameter +// values. Inheriting from TestWithParam satisfies that requirement because +// TestWithParam inherits from both Test and WithParamInterface. In more +// complicated hierarchies, however, it is occasionally useful to inherit +// separately from Test and WithParamInterface. For example: + +class BaseTest : public ::testing::Test { + // You can inherit all the usual members for a non-parameterized test + // fixture here. +}; + +class DerivedTest : public BaseTest, public ::testing::WithParamInterface { + // The usual test fixture members go here too. +}; + +TEST_F(BaseTest, HasFoo) { + // This is an ordinary non-parameterized test. +} + +TEST_P(DerivedTest, DoesBlah) { + // GetParam works just the same here as if you inherit from TestWithParam. + EXPECT_TRUE(foo.Blah(GetParam())); +} + +#endif // 0 + + +#if !GTEST_OS_SYMBIAN +# include +#endif + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ + +#include +#include +#include + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2003 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Dan Egnor (egnor@google.com) +// +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). +// +// Bill Gibbons suggested we use something like this. +// +// Thread Safety: +// Unlike other linked_ptr implementations, in this implementation +// a linked_ptr object is thread-safe in the sense that: +// - it's safe to copy linked_ptr objects concurrently, +// - it's safe to copy *from* a linked_ptr and read its underlying +// raw pointer (e.g. via get()) concurrently, and +// - it's safe to write to two linked_ptrs that point to the same +// shared object concurrently. +// TODO(wan@google.com): rename this to safe_linked_ptr to avoid +// confusion with normal linked_ptr. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ + +#include +#include + + +namespace testing { +namespace internal { + +// Protects copying of all linked_ptr objects. +GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr(obj) vs linked_ptr(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Many linked_ptr operations may change p.link_ for some linked_ptr + // variable p in the same circle as this object. Therefore we need + // to prevent two such operations from occurring concurrently. + // + // Note that different types of linked_ptr objects can coexist in a + // circle (e.g. linked_ptr, linked_ptr, and + // linked_ptr). Therefore we must use a single mutex to + // protect all linked_ptr objects. This can create serious + // contention in production code, but is acceptable in a testing + // framework. + + // Join an existing circle. + // L < g_linked_ptr_mutex + void join(linked_ptr_internal const* ptr) { + MutexLock lock(&g_linked_ptr_mutex); + + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) p = p->next_; + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true if we were the + // last member of the circle. Once this is done, you can join() another. + // L < g_linked_ptr_mutex + bool depart() { + MutexLock lock(&g_linked_ptr_mutex); + + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) p = p->next_; + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { // NOLINT + assert(&ptr != this); + copy(&ptr); + } + + // Assignment releases the old value and acquires the new. + template linked_ptr& operator=(linked_ptr const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = NULL) { + depart(); + capture(ptr); + } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template + bool operator==(linked_ptr const& ptr) const { + return value_ == ptr.get(); + } + template + bool operator!=(linked_ptr const& ptr) const { + return value_ != ptr.get(); + } + + private: + template + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template void copy(linked_ptr const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template inline +bool operator==(T* ptr, const linked_ptr& x) { + return ptr == x.get(); +} + +template inline +bool operator!=(T* ptr, const linked_ptr& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr +// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation +// for linked_ptr >(new FooBarBaz(arg)) +template +linked_ptr make_linked_ptr(T* ptr) { + return linked_ptr(ptr); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// A user can teach this function how to print a class type T by +// defining either operator<<() or PrintTo() in the namespace that +// defines T. More specifically, the FIRST defined function in the +// following list will be used (assuming T is defined in namespace +// foo): +// +// 1. foo::PrintTo(const T&, ostream*) +// 2. operator<<(ostream&, const T&) defined in either foo or the +// global namespace. +// +// If none of the above is defined, it will print the debug string of +// the value if it is a protocol buffer, or print the raw bytes in the +// value otherwise. +// +// To aid debugging: when T is a reference type, the address of the +// value is also printed; when T is a (const) char pointer, both the +// pointer value and the NUL-terminated string it points to are +// printed. +// +// We also provide some convenient wrappers: +// +// // Prints a value to a string. For a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// std::string ::testing::PrintToString(const T& value); +// +// // Prints a value tersely: for a reference type, the referenced +// // value (but not the address) is printed; for a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// void ::testing::internal::UniversalTersePrint(const T& value, ostream*); +// +// // Prints value using the type inferred by the compiler. The difference +// // from UniversalTersePrint() is that this function prints both the +// // pointer and the NUL-terminated string for a (const or not) char pointer. +// void ::testing::internal::UniversalPrint(const T& value, ostream*); +// +// // Prints the fields of a tuple tersely to a string vector, one +// // element for each field. Tuple support must be enabled in +// // gtest-port.h. +// std::vector UniversalTersePrintTupleFieldsToStrings( +// const Tuple& value); +// +// Known limitation: +// +// The print primitives print the elements of an STL-style container +// using the compiler-inferred type of *iter where iter is a +// const_iterator of the container. When const_iterator is an input +// iterator but not a forward iterator, this inferred type may not +// match value_type, and the print output may be incorrect. In +// practice, this is rarely a problem as for most containers +// const_iterator is a forward iterator. We'll fix this if there's an +// actual need for it. Note that this fix cannot rely on value_type +// being defined as many user-defined container types don't have +// value_type. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#include // NOLINT +#include +#include +#include +#include + +namespace testing { + +// Definitions in the 'internal' and 'internal2' name spaces are +// subject to change without notice. DO NOT USE THEM IN USER CODE! +namespace internal2 { + +// Prints the given number of bytes in the given object to the given +// ostream. +GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, + size_t count, + ::std::ostream* os); + +// For selecting which printer to use when a given type has neither << +// nor PrintTo(). +enum TypeKind { + kProtobuf, // a protobuf type + kConvertibleToInteger, // a type implicitly convertible to BiggestInt + // (e.g. a named or unnamed enum type) + kOtherType // anything else +}; + +// TypeWithoutFormatter::PrintValue(value, os) is called +// by the universal printer to print a value of type T when neither +// operator<< nor PrintTo() is defined for T, where kTypeKind is the +// "kind" of T as defined by enum TypeKind. +template +class TypeWithoutFormatter { + public: + // This default version is called when kTypeKind is kOtherType. + static void PrintValue(const T& value, ::std::ostream* os) { + PrintBytesInObjectTo(reinterpret_cast(&value), + sizeof(value), os); + } +}; + +// We print a protobuf using its ShortDebugString() when the string +// doesn't exceed this many characters; otherwise we print it using +// DebugString() for better readability. +const size_t kProtobufOneLinerMaxLength = 50; + +template +class TypeWithoutFormatter { + public: + static void PrintValue(const T& value, ::std::ostream* os) { + const ::testing::internal::string short_str = value.ShortDebugString(); + const ::testing::internal::string pretty_str = + short_str.length() <= kProtobufOneLinerMaxLength ? + short_str : ("\n" + value.DebugString()); + *os << ("<" + pretty_str + ">"); + } +}; + +template +class TypeWithoutFormatter { + public: + // Since T has no << operator or PrintTo() but can be implicitly + // converted to BiggestInt, we print it as a BiggestInt. + // + // Most likely T is an enum type (either named or unnamed), in which + // case printing it as an integer is the desired behavior. In case + // T is not an enum, printing it as an integer is the best we can do + // given that it has no user-defined printer. + static void PrintValue(const T& value, ::std::ostream* os) { + const internal::BiggestInt kBigInt = value; + *os << kBigInt; + } +}; + +// Prints the given value to the given ostream. If the value is a +// protocol message, its debug string is printed; if it's an enum or +// of a type implicitly convertible to BiggestInt, it's printed as an +// integer; otherwise the bytes in the value are printed. This is +// what UniversalPrinter::Print() does when it knows nothing about +// type T and T has neither << operator nor PrintTo(). +// +// A user can override this behavior for a class type Foo by defining +// a << operator in the namespace where Foo is defined. +// +// We put this operator in namespace 'internal2' instead of 'internal' +// to simplify the implementation, as much code in 'internal' needs to +// use << in STL, which would conflict with our own << were it defined +// in 'internal'. +// +// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If +// we define it to take an std::ostream instead, we'll get an +// "ambiguous overloads" compiler error when trying to print a type +// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether +// operator<<(std::ostream&, const T&) or +// operator<<(std::basic_stream, const Foo&) is more +// specific. +template +::std::basic_ostream& operator<<( + ::std::basic_ostream& os, const T& x) { + TypeWithoutFormatter::value ? kProtobuf : + internal::ImplicitlyConvertible::value ? + kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); + return os; +} + +} // namespace internal2 +} // namespace testing + +// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up +// magic needed for implementing UniversalPrinter won't work. +namespace testing_internal { + +// Used to print a value that is not an STL-style container when the +// user doesn't define PrintTo() for it. +template +void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { + // With the following statement, during unqualified name lookup, + // testing::internal2::operator<< appears as if it was declared in + // the nearest enclosing namespace that contains both + // ::testing_internal and ::testing::internal2, i.e. the global + // namespace. For more details, refer to the C++ Standard section + // 7.3.4-1 [namespace.udir]. This allows us to fall back onto + // testing::internal2::operator<< in case T doesn't come with a << + // operator. + // + // We cannot write 'using ::testing::internal2::operator<<;', which + // gcc 3.3 fails to compile due to a compiler bug. + using namespace ::testing::internal2; // NOLINT + + // Assuming T is defined in namespace foo, in the next statement, + // the compiler will consider all of: + // + // 1. foo::operator<< (thanks to Koenig look-up), + // 2. ::operator<< (as the current namespace is enclosed in ::), + // 3. testing::internal2::operator<< (thanks to the using statement above). + // + // The operator<< whose type matches T best will be picked. + // + // We deliberately allow #2 to be a candidate, as sometimes it's + // impossible to define #1 (e.g. when foo is ::std, defining + // anything in it is undefined behavior unless you are a compiler + // vendor.). + *os << value; +} + +} // namespace testing_internal + +namespace testing { +namespace internal { + +// UniversalPrinter::Print(value, ostream_ptr) prints the given +// value to the given ostream. The caller must ensure that +// 'ostream_ptr' is not NULL, or the behavior is undefined. +// +// We define UniversalPrinter as a class template (as opposed to a +// function template), as we need to partially specialize it for +// reference types, which cannot be done with function templates. +template +class UniversalPrinter; + +template +void UniversalPrint(const T& value, ::std::ostream* os); + +// Used to print an STL-style container when the user doesn't define +// a PrintTo() for it. +template +void DefaultPrintTo(IsContainer /* dummy */, + false_type /* is not a pointer */, + const C& container, ::std::ostream* os) { + const size_t kMaxCount = 32; // The maximum number of elements to print. + *os << '{'; + size_t count = 0; + for (typename C::const_iterator it = container.begin(); + it != container.end(); ++it, ++count) { + if (count > 0) { + *os << ','; + if (count == kMaxCount) { // Enough has been printed. + *os << " ..."; + break; + } + } + *os << ' '; + // We cannot call PrintTo(*it, os) here as PrintTo() doesn't + // handle *it being a native array. + internal::UniversalPrint(*it, os); + } + + if (count > 0) { + *os << ' '; + } + *os << '}'; +} + +// Used to print a pointer that is neither a char pointer nor a member +// pointer, when the user doesn't define PrintTo() for it. (A member +// variable pointer or member function pointer doesn't really point to +// a location in the address space. Their representation is +// implementation-defined. Therefore they will be printed as raw +// bytes.) +template +void DefaultPrintTo(IsNotContainer /* dummy */, + true_type /* is a pointer */, + T* p, ::std::ostream* os) { + if (p == NULL) { + *os << "NULL"; + } else { + // C++ doesn't allow casting from a function pointer to any object + // pointer. + // + // IsTrue() silences warnings: "Condition is always true", + // "unreachable code". + if (IsTrue(ImplicitlyConvertible::value)) { + // T is not a function type. We just call << to print p, + // relying on ADL to pick up user-defined << for their pointer + // types, if any. + *os << p; + } else { + // T is a function type, so '*os << p' doesn't do what we want + // (it just prints p as bool). We want to print p as a const + // void*. However, we cannot cast it to const void* directly, + // even using reinterpret_cast, as earlier versions of gcc + // (e.g. 3.4.5) cannot compile the cast when p is a function + // pointer. Casting to UInt64 first solves the problem. + *os << reinterpret_cast( + reinterpret_cast(p)); + } + } +} + +// Used to print a non-container, non-pointer value when the user +// doesn't define PrintTo() for it. +template +void DefaultPrintTo(IsNotContainer /* dummy */, + false_type /* is not a pointer */, + const T& value, ::std::ostream* os) { + ::testing_internal::DefaultPrintNonContainerTo(value, os); +} + +// Prints the given value using the << operator if it has one; +// otherwise prints the bytes in it. This is what +// UniversalPrinter::Print() does when PrintTo() is not specialized +// or overloaded for type T. +// +// A user can override this behavior for a class type Foo by defining +// an overload of PrintTo() in the namespace where Foo is defined. We +// give the user this option as sometimes defining a << operator for +// Foo is not desirable (e.g. the coding style may prevent doing it, +// or there is already a << operator but it doesn't do what the user +// wants). +template +void PrintTo(const T& value, ::std::ostream* os) { + // DefaultPrintTo() is overloaded. The type of its first two + // arguments determine which version will be picked. If T is an + // STL-style container, the version for container will be called; if + // T is a pointer, the pointer version will be called; otherwise the + // generic version will be called. + // + // Note that we check for container types here, prior to we check + // for protocol message types in our operator<<. The rationale is: + // + // For protocol messages, we want to give people a chance to + // override Google Mock's format by defining a PrintTo() or + // operator<<. For STL containers, other formats can be + // incompatible with Google Mock's format for the container + // elements; therefore we check for container types here to ensure + // that our format is used. + // + // The second argument of DefaultPrintTo() is needed to bypass a bug + // in Symbian's C++ compiler that prevents it from picking the right + // overload between: + // + // PrintTo(const T& x, ...); + // PrintTo(T* x, ...); + DefaultPrintTo(IsContainerTest(0), is_pointer(), value, os); +} + +// The following list of PrintTo() overloads tells +// UniversalPrinter::Print() how to print standard types (built-in +// types, strings, plain arrays, and pointers). + +// Overloads for various char types. +GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); +GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); +inline void PrintTo(char c, ::std::ostream* os) { + // When printing a plain char, we always treat it as unsigned. This + // way, the output won't be affected by whether the compiler thinks + // char is signed or not. + PrintTo(static_cast(c), os); +} + +// Overloads for other simple built-in types. +inline void PrintTo(bool x, ::std::ostream* os) { + *os << (x ? "true" : "false"); +} + +// Overload for wchar_t type. +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its decimal code (except for L'\0'). +// The L'\0' char is printed as "L'\\0'". The decimal code is printed +// as signed integer when wchar_t is implemented by the compiler +// as a signed type and is printed as an unsigned integer when wchar_t +// is implemented as an unsigned type. +GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); + +// Overloads for C strings. +GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); +inline void PrintTo(char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// signed/unsigned char is often used for representing binary data, so +// we print pointers to it as void* to be safe. +inline void PrintTo(const signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(const unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// MSVC can be configured to define wchar_t as a typedef of unsigned +// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native +// type. When wchar_t is a typedef, defining an overload for const +// wchar_t* would cause unsigned short* be printed as a wide string, +// possibly causing invalid memory accesses. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Overloads for wide C strings +GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); +inline void PrintTo(wchar_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +#endif + +// Overload for C arrays. Multi-dimensional arrays are printed +// properly. + +// Prints the given number of elements in an array, without printing +// the curly braces. +template +void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { + UniversalPrint(a[0], os); + for (size_t i = 1; i != count; i++) { + *os << ", "; + UniversalPrint(a[i], os); + } +} + +// Overloads for ::string and ::std::string. +#if GTEST_HAS_GLOBAL_STRING +GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os); +inline void PrintTo(const ::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); +inline void PrintTo(const ::std::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} + +// Overloads for ::wstring and ::std::wstring. +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_TR1_TUPLE +// Overload for ::std::tr1::tuple. Needed for printing function arguments, +// which are packed as tuples. + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os); + +// Overloaded PrintTo() for tuples of various arities. We support +// tuples of up-to 10 fields. The following implementation works +// regardless of whether tr1::tuple is implemented using the +// non-standard variadic template feature or not. + +inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo( + const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} +#endif // GTEST_HAS_TR1_TUPLE + +// Overload for std::pair. +template +void PrintTo(const ::std::pair& value, ::std::ostream* os) { + *os << '('; + // We cannot use UniversalPrint(value.first, os) here, as T1 may be + // a reference type. The same for printing value.second. + UniversalPrinter::Print(value.first, os); + *os << ", "; + UniversalPrinter::Print(value.second, os); + *os << ')'; +} + +// Implements printing a non-reference type T by letting the compiler +// pick the right overload of PrintTo() for T. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + // Note: we deliberately don't call this PrintTo(), as that name + // conflicts with ::testing::internal::PrintTo in the body of the + // function. + static void Print(const T& value, ::std::ostream* os) { + // By default, ::testing::internal::PrintTo() is used for printing + // the value. + // + // Thanks to Koenig look-up, if T is a class and has its own + // PrintTo() function defined in its namespace, that function will + // be visible here. Since it is more specific than the generic ones + // in ::testing::internal, it will be picked by the compiler in the + // following statement - exactly what we want. + PrintTo(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// UniversalPrintArray(begin, len, os) prints an array of 'len' +// elements, starting at address 'begin'. +template +void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { + if (len == 0) { + *os << "{}"; + } else { + *os << "{ "; + const size_t kThreshold = 18; + const size_t kChunkSize = 8; + // If the array has more than kThreshold elements, we'll have to + // omit some details by printing only the first and the last + // kChunkSize elements. + // TODO(wan@google.com): let the user control the threshold using a flag. + if (len <= kThreshold) { + PrintRawArrayTo(begin, len, os); + } else { + PrintRawArrayTo(begin, kChunkSize, os); + *os << ", ..., "; + PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); + } + *os << " }"; + } +} +// This overload prints a (const) char array compactly. +GTEST_API_ void UniversalPrintArray(const char* begin, + size_t len, + ::std::ostream* os); + +// Implements printing an array type T[N]. +template +class UniversalPrinter { + public: + // Prints the given array, omitting some elements when there are too + // many. + static void Print(const T (&a)[N], ::std::ostream* os) { + UniversalPrintArray(a, N, os); + } +}; + +// Implements printing a reference type T&. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + static void Print(const T& value, ::std::ostream* os) { + // Prints the address of the value. We use reinterpret_cast here + // as static_cast doesn't compile when T is a function type. + *os << "@" << reinterpret_cast(&value) << " "; + + // Then prints the value itself. + UniversalPrint(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// Prints a value tersely: for a reference type, the referenced value +// (but not the address) is printed; for a (const) char pointer, the +// NUL-terminated string (but not the pointer) is printed. +template +void UniversalTersePrint(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); +} +inline void UniversalTersePrint(const char* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(string(str), os); + } +} +inline void UniversalTersePrint(char* str, ::std::ostream* os) { + UniversalTersePrint(static_cast(str), os); +} + +// Prints a value using the type inferred by the compiler. The +// difference between this and UniversalTersePrint() is that for a +// (const) char pointer, this prints both the pointer and the +// NUL-terminated string. +template +void UniversalPrint(const T& value, ::std::ostream* os) { + UniversalPrinter::Print(value, os); +} + +#if GTEST_HAS_TR1_TUPLE +typedef ::std::vector Strings; + +// This helper template allows PrintTo() for tuples and +// UniversalTersePrintTupleFieldsToStrings() to be defined by +// induction on the number of tuple fields. The idea is that +// TuplePrefixPrinter::PrintPrefixTo(t, os) prints the first N +// fields in tuple t, and can be defined in terms of +// TuplePrefixPrinter. + +// The inductive case. +template +struct TuplePrefixPrinter { + // Prints the first N fields of a tuple. + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + TuplePrefixPrinter::PrintPrefixTo(t, os); + *os << ", "; + UniversalPrinter::type> + ::Print(::std::tr1::get(t), os); + } + + // Tersely prints the first N fields of a tuple to a string vector, + // one element for each field. + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + TuplePrefixPrinter::TersePrintPrefixToStrings(t, strings); + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Base cases. +template <> +struct TuplePrefixPrinter<0> { + template + static void PrintPrefixTo(const Tuple&, ::std::ostream*) {} + + template + static void TersePrintPrefixToStrings(const Tuple&, Strings*) {} +}; +// We have to specialize the entire TuplePrefixPrinter<> class +// template here, even though the definition of +// TersePrintPrefixToStrings() is the same as the generic version, as +// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't +// support specializing a method template of a class template. +template <> +struct TuplePrefixPrinter<1> { + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + UniversalPrinter::type>:: + Print(::std::tr1::get<0>(t), os); + } + + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get<0>(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os) { + *os << "("; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + PrintPrefixTo(t, os); + *os << ")"; +} + +// Prints the fields of a tuple tersely to a string vector, one +// element for each field. See the comment before +// UniversalTersePrint() for how we define "tersely". +template +Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { + Strings result; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + TersePrintPrefixToStrings(value, &result); + return result; +} +#endif // GTEST_HAS_TR1_TUPLE + +} // namespace internal + +template +::std::string PrintToString(const T& value) { + ::std::stringstream ss; + internal::UniversalTersePrint(value, &ss); + return ss.str(); +} + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { +namespace internal { + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Outputs a message explaining invalid registration of different +// fixture class for the same test case. This may happen when +// TEST_P macro is used to define two tests with the same name +// but in different namespaces. +GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line); + +template class ParamGeneratorInterface; +template class ParamGenerator; + +// Interface for iterating over elements provided by an implementation +// of ParamGeneratorInterface. +template +class ParamIteratorInterface { + public: + virtual ~ParamIteratorInterface() {} + // A pointer to the base generator instance. + // Used only for the purposes of iterator comparison + // to make sure that two iterators belong to the same generator. + virtual const ParamGeneratorInterface* BaseGenerator() const = 0; + // Advances iterator to point to the next element + // provided by the generator. The caller is responsible + // for not calling Advance() on an iterator equal to + // BaseGenerator()->End(). + virtual void Advance() = 0; + // Clones the iterator object. Used for implementing copy semantics + // of ParamIterator. + virtual ParamIteratorInterface* Clone() const = 0; + // Dereferences the current iterator and provides (read-only) access + // to the pointed value. It is the caller's responsibility not to call + // Current() on an iterator equal to BaseGenerator()->End(). + // Used for implementing ParamGenerator::operator*(). + virtual const T* Current() const = 0; + // Determines whether the given iterator and other point to the same + // element in the sequence generated by the generator. + // Used for implementing ParamGenerator::operator==(). + virtual bool Equals(const ParamIteratorInterface& other) const = 0; +}; + +// Class iterating over elements provided by an implementation of +// ParamGeneratorInterface. It wraps ParamIteratorInterface +// and implements the const forward iterator concept. +template +class ParamIterator { + public: + typedef T value_type; + typedef const T& reference; + typedef ptrdiff_t difference_type; + + // ParamIterator assumes ownership of the impl_ pointer. + ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} + ParamIterator& operator=(const ParamIterator& other) { + if (this != &other) + impl_.reset(other.impl_->Clone()); + return *this; + } + + const T& operator*() const { return *impl_->Current(); } + const T* operator->() const { return impl_->Current(); } + // Prefix version of operator++. + ParamIterator& operator++() { + impl_->Advance(); + return *this; + } + // Postfix version of operator++. + ParamIterator operator++(int /*unused*/) { + ParamIteratorInterface* clone = impl_->Clone(); + impl_->Advance(); + return ParamIterator(clone); + } + bool operator==(const ParamIterator& other) const { + return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); + } + bool operator!=(const ParamIterator& other) const { + return !(*this == other); + } + + private: + friend class ParamGenerator; + explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} + scoped_ptr > impl_; +}; + +// ParamGeneratorInterface is the binary interface to access generators +// defined in other translation units. +template +class ParamGeneratorInterface { + public: + typedef T ParamType; + + virtual ~ParamGeneratorInterface() {} + + // Generator interface definition + virtual ParamIteratorInterface* Begin() const = 0; + virtual ParamIteratorInterface* End() const = 0; +}; + +// Wraps ParamGeneratorInterface and provides general generator syntax +// compatible with the STL Container concept. +// This class implements copy initialization semantics and the contained +// ParamGeneratorInterface instance is shared among all copies +// of the original object. This is possible because that instance is immutable. +template +class ParamGenerator { + public: + typedef ParamIterator iterator; + + explicit ParamGenerator(ParamGeneratorInterface* impl) : impl_(impl) {} + ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} + + ParamGenerator& operator=(const ParamGenerator& other) { + impl_ = other.impl_; + return *this; + } + + iterator begin() const { return iterator(impl_->Begin()); } + iterator end() const { return iterator(impl_->End()); } + + private: + linked_ptr > impl_; +}; + +// Generates values from a range of two comparable values. Can be used to +// generate sequences of user-defined types that implement operator+() and +// operator<(). +// This class is used in the Range() function. +template +class RangeGenerator : public ParamGeneratorInterface { + public: + RangeGenerator(T begin, T end, IncrementT step) + : begin_(begin), end_(end), + step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} + virtual ~RangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, begin_, 0, step_); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, end_, end_index_, step_); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, T value, int index, + IncrementT step) + : base_(base), value_(value), index_(index), step_(step) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + value_ = value_ + step_; + index_++; + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const T* Current() const { return &value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const int other_index = + CheckedDowncastToActualType(&other)->index_; + return index_ == other_index; + } + + private: + Iterator(const Iterator& other) + : ParamIteratorInterface(), + base_(other.base_), value_(other.value_), index_(other.index_), + step_(other.step_) {} + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + T value_; + int index_; + const IncrementT step_; + }; // class RangeGenerator::Iterator + + static int CalculateEndIndex(const T& begin, + const T& end, + const IncrementT& step) { + int end_index = 0; + for (T i = begin; i < end; i = i + step) + end_index++; + return end_index; + } + + // No implementation - assignment is unsupported. + void operator=(const RangeGenerator& other); + + const T begin_; + const T end_; + const IncrementT step_; + // The index for the end() iterator. All the elements in the generated + // sequence are indexed (0-based) to aid iterator comparison. + const int end_index_; +}; // class RangeGenerator + + +// Generates values from a pair of STL-style iterators. Used in the +// ValuesIn() function. The elements are copied from the source range +// since the source can be located on the stack, and the generator +// is likely to persist beyond that stack frame. +template +class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { + public: + template + ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) + : container_(begin, end) {} + virtual ~ValuesInIteratorRangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, container_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, container_.end()); + } + + private: + typedef typename ::std::vector ContainerType; + + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + typename ContainerType::const_iterator iterator) + : base_(base), iterator_(iterator) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + ++iterator_; + value_.reset(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + // We need to use cached value referenced by iterator_ because *iterator_ + // can return a temporary object (and of type other then T), so just + // having "return &*iterator_;" doesn't work. + // value_ is updated here and not in Advance() because Advance() + // can advance iterator_ beyond the end of the range, and we cannot + // detect that fact. The client code, on the other hand, is + // responsible for not calling Current() on an out-of-range iterator. + virtual const T* Current() const { + if (value_.get() == NULL) + value_.reset(new T(*iterator_)); + return value_.get(); + } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + return iterator_ == + CheckedDowncastToActualType(&other)->iterator_; + } + + private: + Iterator(const Iterator& other) + // The explicit constructor call suppresses a false warning + // emitted by gcc when supplied with the -Wextra option. + : ParamIteratorInterface(), + base_(other.base_), + iterator_(other.iterator_) {} + + const ParamGeneratorInterface* const base_; + typename ContainerType::const_iterator iterator_; + // A cached value of *iterator_. We keep it here to allow access by + // pointer in the wrapping iterator's operator->(). + // value_ needs to be mutable to be accessed in Current(). + // Use of scoped_ptr helps manage cached value's lifetime, + // which is bound by the lifespan of the iterator itself. + mutable scoped_ptr value_; + }; // class ValuesInIteratorRangeGenerator::Iterator + + // No implementation - assignment is unsupported. + void operator=(const ValuesInIteratorRangeGenerator& other); + + const ContainerType container_; +}; // class ValuesInIteratorRangeGenerator + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Stores a parameter value and later creates tests parameterized with that +// value. +template +class ParameterizedTestFactory : public TestFactoryBase { + public: + typedef typename TestClass::ParamType ParamType; + explicit ParameterizedTestFactory(ParamType parameter) : + parameter_(parameter) {} + virtual Test* CreateTest() { + TestClass::SetParam(¶meter_); + return new TestClass(); + } + + private: + const ParamType parameter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactoryBase is a base class for meta-factories that create +// test factories for passing into MakeAndRegisterTestInfo function. +template +class TestMetaFactoryBase { + public: + virtual ~TestMetaFactoryBase() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactory creates test factories for passing into +// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives +// ownership of test factory pointer, same factory object cannot be passed +// into that method twice. But ParameterizedTestCaseInfo is going to call +// it for each Test/Parameter value combination. Thus it needs meta factory +// creator class. +template +class TestMetaFactory + : public TestMetaFactoryBase { + public: + typedef typename TestCase::ParamType ParamType; + + TestMetaFactory() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { + return new ParameterizedTestFactory(parameter); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfoBase is a generic interface +// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase +// accumulates test information provided by TEST_P macro invocations +// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations +// and uses that information to register all resulting test instances +// in RegisterTests method. The ParameterizeTestCaseRegistry class holds +// a collection of pointers to the ParameterizedTestCaseInfo objects +// and calls RegisterTests() on each of them when asked. +class ParameterizedTestCaseInfoBase { + public: + virtual ~ParameterizedTestCaseInfoBase() {} + + // Base part of test case name for display purposes. + virtual const string& GetTestCaseName() const = 0; + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const = 0; + // UnitTest class invokes this method to register tests in this + // test case right before running them in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + virtual void RegisterTests() = 0; + + protected: + ParameterizedTestCaseInfoBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P +// macro invocations for a particular test case and generators +// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that +// test case. It registers tests with all values generated by all +// generators when asked. +template +class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { + public: + // ParamType and GeneratorCreationFunc are private types but are required + // for declarations of public methods AddTestPattern() and + // AddTestCaseInstantiation(). + typedef typename TestCase::ParamType ParamType; + // A function that returns an instance of appropriate generator type. + typedef ParamGenerator(GeneratorCreationFunc)(); + + explicit ParameterizedTestCaseInfo(const char* name) + : test_case_name_(name) {} + + // Test case base name for display purposes. + virtual const string& GetTestCaseName() const { return test_case_name_; } + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } + // TEST_P macro uses AddTestPattern() to record information + // about a single test in a LocalTestInfo structure. + // test_case_name is the base name of the test case (without invocation + // prefix). test_base_name is the name of an individual test without + // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is + // test case base name and DoBar is test base name. + void AddTestPattern(const char* test_case_name, + const char* test_base_name, + TestMetaFactoryBase* meta_factory) { + tests_.push_back(linked_ptr(new TestInfo(test_case_name, + test_base_name, + meta_factory))); + } + // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information + // about a generator. + int AddTestCaseInstantiation(const string& instantiation_name, + GeneratorCreationFunc* func, + const char* /* file */, + int /* line */) { + instantiations_.push_back(::std::make_pair(instantiation_name, func)); + return 0; // Return value used only to run this method in namespace scope. + } + // UnitTest class invokes this method to register tests in this test case + // test cases right before running tests in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + // UnitTest has a guard to prevent from calling this method more then once. + virtual void RegisterTests() { + for (typename TestInfoContainer::iterator test_it = tests_.begin(); + test_it != tests_.end(); ++test_it) { + linked_ptr test_info = *test_it; + for (typename InstantiationContainer::iterator gen_it = + instantiations_.begin(); gen_it != instantiations_.end(); + ++gen_it) { + const string& instantiation_name = gen_it->first; + ParamGenerator generator((*gen_it->second)()); + + Message test_case_name_stream; + if ( !instantiation_name.empty() ) + test_case_name_stream << instantiation_name << "/"; + test_case_name_stream << test_info->test_case_base_name; + + int i = 0; + for (typename ParamGenerator::iterator param_it = + generator.begin(); + param_it != generator.end(); ++param_it, ++i) { + Message test_name_stream; + test_name_stream << test_info->test_base_name << "/" << i; + MakeAndRegisterTestInfo( + test_case_name_stream.GetString().c_str(), + test_name_stream.GetString().c_str(), + NULL, // No type parameter. + PrintToString(*param_it).c_str(), + GetTestCaseTypeId(), + TestCase::SetUpTestCase, + TestCase::TearDownTestCase, + test_info->test_meta_factory->CreateTestFactory(*param_it)); + } // for param_it + } // for gen_it + } // for test_it + } // RegisterTests + + private: + // LocalTestInfo structure keeps information about a single test registered + // with TEST_P macro. + struct TestInfo { + TestInfo(const char* a_test_case_base_name, + const char* a_test_base_name, + TestMetaFactoryBase* a_test_meta_factory) : + test_case_base_name(a_test_case_base_name), + test_base_name(a_test_base_name), + test_meta_factory(a_test_meta_factory) {} + + const string test_case_base_name; + const string test_base_name; + const scoped_ptr > test_meta_factory; + }; + typedef ::std::vector > TestInfoContainer; + // Keeps pairs of + // received from INSTANTIATE_TEST_CASE_P macros. + typedef ::std::vector > + InstantiationContainer; + + const string test_case_name_; + TestInfoContainer tests_; + InstantiationContainer instantiations_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo); +}; // class ParameterizedTestCaseInfo + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase +// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P +// macros use it to locate their corresponding ParameterizedTestCaseInfo +// descriptors. +class ParameterizedTestCaseRegistry { + public: + ParameterizedTestCaseRegistry() {} + ~ParameterizedTestCaseRegistry() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + delete *it; + } + } + + // Looks up or creates and returns a structure containing information about + // tests and instantiations of a particular test case. + template + ParameterizedTestCaseInfo* GetTestCasePatternHolder( + const char* test_case_name, + const char* file, + int line) { + ParameterizedTestCaseInfo* typed_test_info = NULL; + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + if ((*it)->GetTestCaseName() == test_case_name) { + if ((*it)->GetTestCaseTypeId() != GetTypeId()) { + // Complain about incorrect usage of Google Test facilities + // and terminate the program since we cannot guaranty correct + // test case setup and tear-down in this case. + ReportInvalidTestCaseType(test_case_name, file, line); + posix::Abort(); + } else { + // At this point we are sure that the object we found is of the same + // type we are looking for, so we downcast it to that type + // without further checks. + typed_test_info = CheckedDowncastToActualType< + ParameterizedTestCaseInfo >(*it); + } + break; + } + } + if (typed_test_info == NULL) { + typed_test_info = new ParameterizedTestCaseInfo(test_case_name); + test_case_infos_.push_back(typed_test_info); + } + return typed_test_info; + } + void RegisterTests() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + (*it)->RegisterTests(); + } + } + + private: + typedef ::std::vector TestCaseInfoContainer; + + TestCaseInfoContainer test_case_infos_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry); +}; + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +// This file was GENERATED by command: +// pump.py gtest-param-util-generated.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently Google Test supports at most 50 arguments in Values, +// and at most 10 arguments in Combine. Please contact +// googletestframework@googlegroups.com if you need more. +// Please note that the number of arguments to Combine is limited +// by the maximum arity of the implementation of tr1::tuple which is +// currently set at 10. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Forward declarations of ValuesIn(), which is implemented in +// include/gtest/gtest-param-test.h. +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end); + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]); + +template +internal::ParamGenerator ValuesIn( + const Container& container); + +namespace internal { + +// Used in the Values() function to provide polymorphic capabilities. +template +class ValueArray1 { + public: + explicit ValueArray1(T1 v1) : v1_(v1) {} + + template + operator ParamGenerator() const { return ValuesIn(&v1_, &v1_ + 1); } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray1& other); + + const T1 v1_; +}; + +template +class ValueArray2 { + public: + ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray2& other); + + const T1 v1_; + const T2 v2_; +}; + +template +class ValueArray3 { + public: + ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray3& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; +}; + +template +class ValueArray4 { + public: + ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray4& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; +}; + +template +class ValueArray5 { + public: + ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray5& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; +}; + +template +class ValueArray6 { + public: + ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray6& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; +}; + +template +class ValueArray7 { + public: + ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray7& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; +}; + +template +class ValueArray8 { + public: + ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray8& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; +}; + +template +class ValueArray9 { + public: + ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray9& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; +}; + +template +class ValueArray10 { + public: + ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray10& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; +}; + +template +class ValueArray11 { + public: + ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray11& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; +}; + +template +class ValueArray12 { + public: + ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray12& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; +}; + +template +class ValueArray13 { + public: + ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray13& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; +}; + +template +class ValueArray14 { + public: + ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray14& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; +}; + +template +class ValueArray15 { + public: + ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray15& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; +}; + +template +class ValueArray16 { + public: + ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray16& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; +}; + +template +class ValueArray17 { + public: + ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray17& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; +}; + +template +class ValueArray18 { + public: + ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray18& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; +}; + +template +class ValueArray19 { + public: + ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray19& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; +}; + +template +class ValueArray20 { + public: + ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray20& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; +}; + +template +class ValueArray21 { + public: + ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray21& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; +}; + +template +class ValueArray22 { + public: + ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray22& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; +}; + +template +class ValueArray23 { + public: + ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, + v23_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray23& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; +}; + +template +class ValueArray24 { + public: + ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray24& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; +}; + +template +class ValueArray25 { + public: + ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray25& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; +}; + +template +class ValueArray26 { + public: + ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray26& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; +}; + +template +class ValueArray27 { + public: + ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray27& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; +}; + +template +class ValueArray28 { + public: + ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray28& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; +}; + +template +class ValueArray29 { + public: + ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray29& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; +}; + +template +class ValueArray30 { + public: + ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray30& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; +}; + +template +class ValueArray31 { + public: + ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray31& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; +}; + +template +class ValueArray32 { + public: + ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray32& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; +}; + +template +class ValueArray33 { + public: + ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray33& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; +}; + +template +class ValueArray34 { + public: + ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray34& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; +}; + +template +class ValueArray35 { + public: + ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, + v35_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray35& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; +}; + +template +class ValueArray36 { + public: + ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray36& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; +}; + +template +class ValueArray37 { + public: + ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray37& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; +}; + +template +class ValueArray38 { + public: + ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray38& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; +}; + +template +class ValueArray39 { + public: + ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray39& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; +}; + +template +class ValueArray40 { + public: + ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray40& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; +}; + +template +class ValueArray41 { + public: + ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray41& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; +}; + +template +class ValueArray42 { + public: + ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray42& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; +}; + +template +class ValueArray43 { + public: + ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), + v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray43& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; +}; + +template +class ValueArray44 { + public: + ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), + v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), + v43_(v43), v44_(v44) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray44& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; +}; + +template +class ValueArray45 { + public: + ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), + v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray45& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; +}; + +template +class ValueArray46 { + public: + ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray46& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; +}; + +template +class ValueArray47 { + public: + ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), + v47_(v47) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, + v47_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray47& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; +}; + +template +class ValueArray48 { + public: + ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), + v46_(v46), v47_(v47), v48_(v48) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_, + v48_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray48& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; +}; + +template +class ValueArray49 { + public: + ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, + T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_, + v48_, v49_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray49& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; +}; + +template +class ValueArray50 { + public: + ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, + T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_, + v48_, v49_, v50_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray50& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; + const T50 v50_; +}; + +# if GTEST_HAS_COMBINE +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Generates values from the Cartesian product of values produced +// by the argument generators. +// +template +class CartesianProductGenerator2 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator2(const ParamGenerator& g1, + const ParamGenerator& g2) + : g1_(g1), g2_(g2) {} + virtual ~CartesianProductGenerator2() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current2_; + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + ParamType current_value_; + }; // class CartesianProductGenerator2::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator2& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; +}; // class CartesianProductGenerator2 + + +template +class CartesianProductGenerator3 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator3(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + virtual ~CartesianProductGenerator3() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current3_; + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + ParamType current_value_; + }; // class CartesianProductGenerator3::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator3& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; +}; // class CartesianProductGenerator3 + + +template +class CartesianProductGenerator4 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator4(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + virtual ~CartesianProductGenerator4() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current4_; + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + ParamType current_value_; + }; // class CartesianProductGenerator4::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator4& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; +}; // class CartesianProductGenerator4 + + +template +class CartesianProductGenerator5 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator5(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + virtual ~CartesianProductGenerator5() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current5_; + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + ParamType current_value_; + }; // class CartesianProductGenerator5::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator5& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; +}; // class CartesianProductGenerator5 + + +template +class CartesianProductGenerator6 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator6(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + virtual ~CartesianProductGenerator6() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current6_; + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + ParamType current_value_; + }; // class CartesianProductGenerator6::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator6& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; +}; // class CartesianProductGenerator6 + + +template +class CartesianProductGenerator7 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator7(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + virtual ~CartesianProductGenerator7() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current7_; + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + ParamType current_value_; + }; // class CartesianProductGenerator7::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator7& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; +}; // class CartesianProductGenerator7 + + +template +class CartesianProductGenerator8 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator8(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + virtual ~CartesianProductGenerator8() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current8_; + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + ParamType current_value_; + }; // class CartesianProductGenerator8::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator8& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; +}; // class CartesianProductGenerator8 + + +template +class CartesianProductGenerator9 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator9(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + virtual ~CartesianProductGenerator9() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current9_; + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + ParamType current_value_; + }; // class CartesianProductGenerator9::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator9& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; +}; // class CartesianProductGenerator9 + + +template +class CartesianProductGenerator10 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator10(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9, + const ParamGenerator& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + virtual ~CartesianProductGenerator10() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end(), g10_, g10_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9, + const ParamGenerator& g10, + const typename ParamGenerator::iterator& current10) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9), + begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current10_; + if (current10_ == end10_) { + current10_ = begin10_; + ++current9_; + } + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_ && + current10_ == typed_other->current10_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_), + begin10_(other.begin10_), + end10_(other.end10_), + current10_(other.current10_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_, *current10_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_ || + current10_ == end10_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + const typename ParamGenerator::iterator begin10_; + const typename ParamGenerator::iterator end10_; + typename ParamGenerator::iterator current10_; + ParamType current_value_; + }; // class CartesianProductGenerator10::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator10& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; + const ParamGenerator g10_; +}; // class CartesianProductGenerator10 + + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Helper classes providing Combine() with polymorphic features. They allow +// casting CartesianProductGeneratorN to ParamGenerator if T is +// convertible to U. +// +template +class CartesianProductHolder2 { + public: +CartesianProductHolder2(const Generator1& g1, const Generator2& g2) + : g1_(g1), g2_(g2) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator2( + static_cast >(g1_), + static_cast >(g2_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder2& other); + + const Generator1 g1_; + const Generator2 g2_; +}; // class CartesianProductHolder2 + +template +class CartesianProductHolder3 { + public: +CartesianProductHolder3(const Generator1& g1, const Generator2& g2, + const Generator3& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator3( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder3& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; +}; // class CartesianProductHolder3 + +template +class CartesianProductHolder4 { + public: +CartesianProductHolder4(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator4( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder4& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; +}; // class CartesianProductHolder4 + +template +class CartesianProductHolder5 { + public: +CartesianProductHolder5(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator5( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder5& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; +}; // class CartesianProductHolder5 + +template +class CartesianProductHolder6 { + public: +CartesianProductHolder6(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator6( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder6& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; +}; // class CartesianProductHolder6 + +template +class CartesianProductHolder7 { + public: +CartesianProductHolder7(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator7( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder7& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; +}; // class CartesianProductHolder7 + +template +class CartesianProductHolder8 { + public: +CartesianProductHolder8(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator8( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder8& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; +}; // class CartesianProductHolder8 + +template +class CartesianProductHolder9 { + public: +CartesianProductHolder9(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator9( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder9& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; +}; // class CartesianProductHolder9 + +template +class CartesianProductHolder10 { + public: +CartesianProductHolder10(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9, const Generator10& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator10( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_), + static_cast >(g10_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder10& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; + const Generator10 g10_; +}; // class CartesianProductHolder10 + +# endif // GTEST_HAS_COMBINE + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Functions producing parameter generators. +// +// Google Test uses these generators to produce parameters for value- +// parameterized tests. When a parameterized test case is instantiated +// with a particular generator, Google Test creates and runs tests +// for each element in the sequence produced by the generator. +// +// In the following sample, tests from test case FooTest are instantiated +// each three times with parameter values 3, 5, and 8: +// +// class FooTest : public TestWithParam { ... }; +// +// TEST_P(FooTest, TestThis) { +// } +// TEST_P(FooTest, TestThat) { +// } +// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); +// + +// Range() returns generators providing sequences of values in a range. +// +// Synopsis: +// Range(start, end) +// - returns a generator producing a sequence of values {start, start+1, +// start+2, ..., }. +// Range(start, end, step) +// - returns a generator producing a sequence of values {start, start+step, +// start+step+step, ..., }. +// Notes: +// * The generated sequences never include end. For example, Range(1, 5) +// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) +// returns a generator producing {1, 3, 5, 7}. +// * start and end must have the same type. That type may be any integral or +// floating-point type or a user defined type satisfying these conditions: +// * It must be assignable (have operator=() defined). +// * It must have operator+() (operator+(int-compatible type) for +// two-operand version). +// * It must have operator<() defined. +// Elements in the resulting sequences will also have that type. +// * Condition start < end must be satisfied in order for resulting sequences +// to contain any elements. +// +template +internal::ParamGenerator Range(T start, T end, IncrementT step) { + return internal::ParamGenerator( + new internal::RangeGenerator(start, end, step)); +} + +template +internal::ParamGenerator Range(T start, T end) { + return Range(start, end, 1); +} + +// ValuesIn() function allows generation of tests with parameters coming from +// a container. +// +// Synopsis: +// ValuesIn(const T (&array)[N]) +// - returns a generator producing sequences with elements from +// a C-style array. +// ValuesIn(const Container& container) +// - returns a generator producing sequences with elements from +// an STL-style container. +// ValuesIn(Iterator begin, Iterator end) +// - returns a generator producing sequences with elements from +// a range [begin, end) defined by a pair of STL-style iterators. These +// iterators can also be plain C pointers. +// +// Please note that ValuesIn copies the values from the containers +// passed in and keeps them to generate tests in RUN_ALL_TESTS(). +// +// Examples: +// +// This instantiates tests from test case StringTest +// each with C-string values of "foo", "bar", and "baz": +// +// const char* strings[] = {"foo", "bar", "baz"}; +// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); +// +// This instantiates tests from test case StlStringTest +// each with STL strings with values "a" and "b": +// +// ::std::vector< ::std::string> GetParameterStrings() { +// ::std::vector< ::std::string> v; +// v.push_back("a"); +// v.push_back("b"); +// return v; +// } +// +// INSTANTIATE_TEST_CASE_P(CharSequence, +// StlStringTest, +// ValuesIn(GetParameterStrings())); +// +// +// This will also instantiate tests from CharTest +// each with parameter values 'a' and 'b': +// +// ::std::list GetParameterChars() { +// ::std::list list; +// list.push_back('a'); +// list.push_back('b'); +// return list; +// } +// ::std::list l = GetParameterChars(); +// INSTANTIATE_TEST_CASE_P(CharSequence2, +// CharTest, +// ValuesIn(l.begin(), l.end())); +// +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end) { + typedef typename ::testing::internal::IteratorTraits + ::value_type ParamType; + return internal::ParamGenerator( + new internal::ValuesInIteratorRangeGenerator(begin, end)); +} + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]) { + return ValuesIn(array, array + N); +} + +template +internal::ParamGenerator ValuesIn( + const Container& container) { + return ValuesIn(container.begin(), container.end()); +} + +// Values() allows generating tests from explicitly specified list of +// parameters. +// +// Synopsis: +// Values(T v1, T v2, ..., T vN) +// - returns a generator producing sequences with elements v1, v2, ..., vN. +// +// For example, this instantiates tests from test case BarTest each +// with values "one", "two", and "three": +// +// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); +// +// This instantiates tests from test case BazTest each with values 1, 2, 3.5. +// The exact type of values will depend on the type of parameter in BazTest. +// +// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); +// +// Currently, Values() supports from 1 to 50 parameters. +// +template +internal::ValueArray1 Values(T1 v1) { + return internal::ValueArray1(v1); +} + +template +internal::ValueArray2 Values(T1 v1, T2 v2) { + return internal::ValueArray2(v1, v2); +} + +template +internal::ValueArray3 Values(T1 v1, T2 v2, T3 v3) { + return internal::ValueArray3(v1, v2, v3); +} + +template +internal::ValueArray4 Values(T1 v1, T2 v2, T3 v3, T4 v4) { + return internal::ValueArray4(v1, v2, v3, v4); +} + +template +internal::ValueArray5 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5) { + return internal::ValueArray5(v1, v2, v3, v4, v5); +} + +template +internal::ValueArray6 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6) { + return internal::ValueArray6(v1, v2, v3, v4, v5, v6); +} + +template +internal::ValueArray7 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7) { + return internal::ValueArray7(v1, v2, v3, v4, v5, + v6, v7); +} + +template +internal::ValueArray8 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) { + return internal::ValueArray8(v1, v2, v3, v4, + v5, v6, v7, v8); +} + +template +internal::ValueArray9 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) { + return internal::ValueArray9(v1, v2, v3, + v4, v5, v6, v7, v8, v9); +} + +template +internal::ValueArray10 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) { + return internal::ValueArray10(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10); +} + +template +internal::ValueArray11 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) { + return internal::ValueArray11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); +} + +template +internal::ValueArray12 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) { + return internal::ValueArray12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); +} + +template +internal::ValueArray13 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) { + return internal::ValueArray13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); +} + +template +internal::ValueArray14 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) { + return internal::ValueArray14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14); +} + +template +internal::ValueArray15 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) { + return internal::ValueArray15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15); +} + +template +internal::ValueArray16 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16) { + return internal::ValueArray16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16); +} + +template +internal::ValueArray17 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17) { + return internal::ValueArray17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17); +} + +template +internal::ValueArray18 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18) { + return internal::ValueArray18(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18); +} + +template +internal::ValueArray19 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) { + return internal::ValueArray19(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19); +} + +template +internal::ValueArray20 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) { + return internal::ValueArray20(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20); +} + +template +internal::ValueArray21 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) { + return internal::ValueArray21(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21); +} + +template +internal::ValueArray22 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22) { + return internal::ValueArray22(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22); +} + +template +internal::ValueArray23 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23) { + return internal::ValueArray23(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23); +} + +template +internal::ValueArray24 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24) { + return internal::ValueArray24(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24); +} + +template +internal::ValueArray25 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) { + return internal::ValueArray25(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25); +} + +template +internal::ValueArray26 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) { + return internal::ValueArray26(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26); +} + +template +internal::ValueArray27 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) { + return internal::ValueArray27(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27); +} + +template +internal::ValueArray28 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) { + return internal::ValueArray28(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28); +} + +template +internal::ValueArray29 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) { + return internal::ValueArray29(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29); +} + +template +internal::ValueArray30 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) { + return internal::ValueArray30(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30); +} + +template +internal::ValueArray31 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) { + return internal::ValueArray31(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31); +} + +template +internal::ValueArray32 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32) { + return internal::ValueArray32(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32); +} + +template +internal::ValueArray33 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33) { + return internal::ValueArray33(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33); +} + +template +internal::ValueArray34 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34) { + return internal::ValueArray34(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34); +} + +template +internal::ValueArray35 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) { + return internal::ValueArray35(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35); +} + +template +internal::ValueArray36 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) { + return internal::ValueArray36(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36); +} + +template +internal::ValueArray37 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37) { + return internal::ValueArray37(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37); +} + +template +internal::ValueArray38 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38) { + return internal::ValueArray38(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, + v33, v34, v35, v36, v37, v38); +} + +template +internal::ValueArray39 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38, T39 v39) { + return internal::ValueArray39(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, + v32, v33, v34, v35, v36, v37, v38, v39); +} + +template +internal::ValueArray40 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, + T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, + T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) { + return internal::ValueArray40(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, + v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40); +} + +template +internal::ValueArray41 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) { + return internal::ValueArray41(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, + v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41); +} + +template +internal::ValueArray42 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) { + return internal::ValueArray42(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, + v42); +} + +template +internal::ValueArray43 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) { + return internal::ValueArray43(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, + v41, v42, v43); +} + +template +internal::ValueArray44 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) { + return internal::ValueArray44(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, + v40, v41, v42, v43, v44); +} + +template +internal::ValueArray45 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) { + return internal::ValueArray45(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, + v39, v40, v41, v42, v43, v44, v45); +} + +template +internal::ValueArray46 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) { + return internal::ValueArray46(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46); +} + +template +internal::ValueArray47 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) { + return internal::ValueArray47(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46, v47); +} + +template +internal::ValueArray48 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, + T48 v48) { + return internal::ValueArray48(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, + v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48); +} + +template +internal::ValueArray49 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, + T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, + T47 v47, T48 v48, T49 v49) { + return internal::ValueArray49(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, + v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49); +} + +template +internal::ValueArray50 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, + T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, + T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) { + return internal::ValueArray50(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, + v48, v49, v50); +} + +// Bool() allows generating tests with parameters in a set of (false, true). +// +// Synopsis: +// Bool() +// - returns a generator producing sequences with elements {false, true}. +// +// It is useful when testing code that depends on Boolean flags. Combinations +// of multiple flags can be tested when several Bool()'s are combined using +// Combine() function. +// +// In the following example all tests in the test case FlagDependentTest +// will be instantiated twice with parameters false and true. +// +// class FlagDependentTest : public testing::TestWithParam { +// virtual void SetUp() { +// external_flag = GetParam(); +// } +// } +// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); +// +inline internal::ParamGenerator Bool() { + return Values(false, true); +} + +# if GTEST_HAS_COMBINE +// Combine() allows the user to combine two or more sequences to produce +// values of a Cartesian product of those sequences' elements. +// +// Synopsis: +// Combine(gen1, gen2, ..., genN) +// - returns a generator producing sequences with elements coming from +// the Cartesian product of elements from the sequences generated by +// gen1, gen2, ..., genN. The sequence elements will have a type of +// tuple where T1, T2, ..., TN are the types +// of elements from sequences produces by gen1, gen2, ..., genN. +// +// Combine can have up to 10 arguments. This number is currently limited +// by the maximum number of elements in the tuple implementation used by Google +// Test. +// +// Example: +// +// This will instantiate tests in test case AnimalTest each one with +// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), +// tuple("dog", BLACK), and tuple("dog", WHITE): +// +// enum Color { BLACK, GRAY, WHITE }; +// class AnimalTest +// : public testing::TestWithParam > {...}; +// +// TEST_P(AnimalTest, AnimalLooksNice) {...} +// +// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, +// Combine(Values("cat", "dog"), +// Values(BLACK, WHITE))); +// +// This will instantiate tests in FlagDependentTest with all variations of two +// Boolean flags: +// +// class FlagDependentTest +// : public testing::TestWithParam > { +// virtual void SetUp() { +// // Assigns external_flag_1 and external_flag_2 values from the tuple. +// tie(external_flag_1, external_flag_2) = GetParam(); +// } +// }; +// +// TEST_P(FlagDependentTest, TestFeature1) { +// // Test your code using external_flag_1 and external_flag_2 here. +// } +// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, +// Combine(Bool(), Bool())); +// +template +internal::CartesianProductHolder2 Combine( + const Generator1& g1, const Generator2& g2) { + return internal::CartesianProductHolder2( + g1, g2); +} + +template +internal::CartesianProductHolder3 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3) { + return internal::CartesianProductHolder3( + g1, g2, g3); +} + +template +internal::CartesianProductHolder4 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4) { + return internal::CartesianProductHolder4( + g1, g2, g3, g4); +} + +template +internal::CartesianProductHolder5 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5) { + return internal::CartesianProductHolder5( + g1, g2, g3, g4, g5); +} + +template +internal::CartesianProductHolder6 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6) { + return internal::CartesianProductHolder6( + g1, g2, g3, g4, g5, g6); +} + +template +internal::CartesianProductHolder7 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7) { + return internal::CartesianProductHolder7( + g1, g2, g3, g4, g5, g6, g7); +} + +template +internal::CartesianProductHolder8 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8) { + return internal::CartesianProductHolder8( + g1, g2, g3, g4, g5, g6, g7, g8); +} + +template +internal::CartesianProductHolder9 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9) { + return internal::CartesianProductHolder9( + g1, g2, g3, g4, g5, g6, g7, g8, g9); +} + +template +internal::CartesianProductHolder10 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9, + const Generator10& g10) { + return internal::CartesianProductHolder10( + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10); +} +# endif // GTEST_HAS_COMBINE + + + +# define TEST_P(test_case_name, test_name) \ + class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + : public test_case_name { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ + virtual void TestBody(); \ + private: \ + static int AddToRegistry() { \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ + #test_case_name, \ + #test_name, \ + new ::testing::internal::TestMetaFactory< \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ + return 0; \ + } \ + static int gtest_registering_dummy_; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ + }; \ + int GTEST_TEST_CLASS_NAME_(test_case_name, \ + test_name)::gtest_registering_dummy_ = \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ + void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ + ::testing::internal::ParamGenerator \ + gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ + int gtest_##prefix##test_case_name##_dummy_ = \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ + #prefix, \ + >est_##prefix##test_case_name##_EvalGenerator_, \ + __FILE__, __LINE__) + +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +// Copyright 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// Google C++ Testing Framework definitions useful in production code. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ + +// When you need to test the private or protected members of a class, +// use the FRIEND_TEST macro to declare your tests as friends of the +// class. For example: +// +// class MyClass { +// private: +// void MyMethod(); +// FRIEND_TEST(MyClassTest, MyMethod); +// }; +// +// class MyClassTest : public testing::Test { +// // ... +// }; +// +// TEST_F(MyClassTest, MyMethod) { +// // Can call MyClass::MyMethod() here. +// } + +#define FRIEND_TEST(test_case_name, test_name)\ +friend class test_case_name##_##test_name##_Test + +#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: mheule@google.com (Markus Heule) +// + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ + +#include +#include + +namespace testing { + +// A copyable object representing the result of a test part (i.e. an +// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). +// +// Don't inherit from TestPartResult as its destructor is not virtual. +class GTEST_API_ TestPartResult { + public: + // The possible outcomes of a test part (i.e. an assertion or an + // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). + enum Type { + kSuccess, // Succeeded. + kNonFatalFailure, // Failed but the test can continue. + kFatalFailure // Failed and the test should be terminated. + }; + + // C'tor. TestPartResult does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestPartResult object. + TestPartResult(Type a_type, + const char* a_file_name, + int a_line_number, + const char* a_message) + : type_(a_type), + file_name_(a_file_name), + line_number_(a_line_number), + summary_(ExtractSummary(a_message)), + message_(a_message) { + } + + // Gets the outcome of the test part. + Type type() const { return type_; } + + // Gets the name of the source file where the test part took place, or + // NULL if it's unknown. + const char* file_name() const { return file_name_.c_str(); } + + // Gets the line in the source file where the test part took place, + // or -1 if it's unknown. + int line_number() const { return line_number_; } + + // Gets the summary of the failure message. + const char* summary() const { return summary_.c_str(); } + + // Gets the message associated with the test part. + const char* message() const { return message_.c_str(); } + + // Returns true iff the test part passed. + bool passed() const { return type_ == kSuccess; } + + // Returns true iff the test part failed. + bool failed() const { return type_ != kSuccess; } + + // Returns true iff the test part non-fatally failed. + bool nonfatally_failed() const { return type_ == kNonFatalFailure; } + + // Returns true iff the test part fatally failed. + bool fatally_failed() const { return type_ == kFatalFailure; } + private: + Type type_; + + // Gets the summary of the failure message by omitting the stack + // trace in it. + static internal::String ExtractSummary(const char* message); + + // The name of the source file where the test part took place, or + // NULL if the source file is unknown. + internal::String file_name_; + // The line in the source file where the test part took place, or -1 + // if the line number is unknown. + int line_number_; + internal::String summary_; // The test failure summary. + internal::String message_; // The test failure message. +}; + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result); + +// An array of TestPartResult objects. +// +// Don't inherit from TestPartResultArray as its destructor is not +// virtual. +class GTEST_API_ TestPartResultArray { + public: + TestPartResultArray() {} + + // Appends the given TestPartResult to the array. + void Append(const TestPartResult& result); + + // Returns the TestPartResult at the given index (0-based). + const TestPartResult& GetTestPartResult(int index) const; + + // Returns the number of TestPartResult objects in the array. + int size() const; + + private: + std::vector array_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); +}; + +// This interface knows how to report a test part result. +class TestPartResultReporterInterface { + public: + virtual ~TestPartResultReporterInterface() {} + + virtual void ReportTestPartResult(const TestPartResult& result) = 0; +}; + +namespace internal { + +// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a +// statement generates new fatal failures. To do so it registers itself as the +// current test part result reporter. Besides checking if fatal failures were +// reported, it only delegates the reporting to the former result reporter. +// The original result reporter is restored in the destructor. +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +class GTEST_API_ HasNewFatalFailureHelper + : public TestPartResultReporterInterface { + public: + HasNewFatalFailureHelper(); + virtual ~HasNewFatalFailureHelper(); + virtual void ReportTestPartResult(const TestPartResult& result); + bool has_new_fatal_failure() const { return has_new_fatal_failure_; } + private: + bool has_new_fatal_failure_; + TestPartResultReporterInterface* original_reporter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); +}; + +} // namespace internal + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// This header implements typed tests and type-parameterized tests. + +// Typed (aka type-driven) tests repeat the same test for types in a +// list. You must know which types you want to test with when writing +// typed tests. Here's how you do it: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + public: + ... + typedef std::list List; + static T shared_; + T value_; +}; + +// Next, associate a list of types with the test case, which will be +// repeated for each type in the list. The typedef is necessary for +// the macro to parse correctly. +typedef testing::Types MyTypes; +TYPED_TEST_CASE(FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// TYPED_TEST_CASE(FooTest, int); + +// Then, use TYPED_TEST() instead of TEST_F() to define as many typed +// tests for this test case as you want. +TYPED_TEST(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + // Since we are inside a derived class template, C++ requires use to + // visit the members of FooTest via 'this'. + TypeParam n = this->value_; + + // To visit static members of the fixture, add the TestFixture:: + // prefix. + n += TestFixture::shared_; + + // To refer to typedefs in the fixture, add the "typename + // TestFixture::" prefix. + typename TestFixture::List values; + values.push_back(n); + ... +} + +TYPED_TEST(FooTest, HasPropertyA) { ... } + +#endif // 0 + +// Type-parameterized tests are abstract test patterns parameterized +// by a type. Compared with typed tests, type-parameterized tests +// allow you to define the test pattern without knowing what the type +// parameters are. The defined pattern can be instantiated with +// different types any number of times, in any number of translation +// units. +// +// If you are designing an interface or concept, you can define a +// suite of type-parameterized tests to verify properties that any +// valid implementation of the interface/concept should have. Then, +// each implementation can easily instantiate the test suite to verify +// that it conforms to the requirements, without having to write +// similar tests repeatedly. Here's an example: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + ... +}; + +// Next, declare that you will define a type-parameterized test case +// (the _P suffix is for "parameterized" or "pattern", whichever you +// prefer): +TYPED_TEST_CASE_P(FooTest); + +// Then, use TYPED_TEST_P() to define as many type-parameterized tests +// for this type-parameterized test case as you want. +TYPED_TEST_P(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + TypeParam n = 0; + ... +} + +TYPED_TEST_P(FooTest, HasPropertyA) { ... } + +// Now the tricky part: you need to register all test patterns before +// you can instantiate them. The first argument of the macro is the +// test case name; the rest are the names of the tests in this test +// case. +REGISTER_TYPED_TEST_CASE_P(FooTest, + DoesBlah, HasPropertyA); + +// Finally, you are free to instantiate the pattern with the types you +// want. If you put the above code in a header file, you can #include +// it in multiple C++ source files and instantiate it multiple times. +// +// To distinguish different instances of the pattern, the first +// argument to the INSTANTIATE_* macro is a prefix that will be added +// to the actual test case name. Remember to pick unique prefixes for +// different instances. +typedef testing::Types MyTypes; +INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); + +#endif // 0 + + +// Implements typed tests. + +#if GTEST_HAS_TYPED_TEST + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the typedef for the type parameters of the +// given test case. +# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define TYPED_TEST_CASE(CaseName, Types) \ + typedef ::testing::internal::TypeList< Types >::type \ + GTEST_TYPE_PARAMS_(CaseName) + +# define TYPED_TEST(CaseName, TestName) \ + template \ + class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ + : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTest< \ + CaseName, \ + ::testing::internal::TemplateSel< \ + GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ + GTEST_TYPE_PARAMS_(CaseName)>::Register(\ + "", #CaseName, #TestName, 0); \ + template \ + void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() + +#endif // GTEST_HAS_TYPED_TEST + +// Implements type-parameterized tests. + +#if GTEST_HAS_TYPED_TEST_P + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the namespace name that the type-parameterized tests for +// the given type-parameterized test case are defined in. The exact +// name of the namespace is subject to change without notice. +# define GTEST_CASE_NAMESPACE_(TestCaseName) \ + gtest_case_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the variable used to remember the names of +// the defined tests in the given test case. +# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ + gtest_typed_test_case_p_state_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. +// +// Expands to the name of the variable used to remember the names of +// the registered tests in the given test case. +# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ + gtest_registered_test_names_##TestCaseName##_ + +// The variables defined in the type-parameterized test macros are +// static as typically these macros are used in a .h file that can be +// #included in multiple translation units linked together. +# define TYPED_TEST_CASE_P(CaseName) \ + static ::testing::internal::TypedTestCasePState \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) + +# define TYPED_TEST_P(CaseName, TestName) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + template \ + class TestName : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ + __FILE__, __LINE__, #CaseName, #TestName); \ + } \ + template \ + void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() + +# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ + __FILE__, __LINE__, #__VA_ARGS__) + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ + bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTestCase::type>::Register(\ + #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) + +#endif // GTEST_HAS_TYPED_TEST_P + +#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// Depending on the platform, different string classes are available. +// On Linux, in addition to ::std::string, Google also makes use of +// class ::string, which has the same interface as ::std::string, but +// has a different implementation. +// +// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that +// ::string is available AND is a distinct type to ::std::string, or +// define it to 0 to indicate otherwise. +// +// If the user's ::std::string and ::string are the same class due to +// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. +// +// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined +// heuristically. + +namespace testing { + +// Declares the flags. + +// This flag temporary enables the disabled tests. +GTEST_DECLARE_bool_(also_run_disabled_tests); + +// This flag brings the debugger on an assertion failure. +GTEST_DECLARE_bool_(break_on_failure); + +// This flag controls whether Google Test catches all test-thrown exceptions +// and logs them as failures. +GTEST_DECLARE_bool_(catch_exceptions); + +// This flag enables using colors in terminal output. Available values are +// "yes" to enable colors, "no" (disable colors), or "auto" (the default) +// to let Google Test decide. +GTEST_DECLARE_string_(color); + +// This flag sets up the filter to select by name using a glob pattern +// the tests to run. If the filter is not given all tests are executed. +GTEST_DECLARE_string_(filter); + +// This flag causes the Google Test to list tests. None of the tests listed +// are actually run if the flag is provided. +GTEST_DECLARE_bool_(list_tests); + +// This flag controls whether Google Test emits a detailed XML report to a file +// in addition to its normal textual output. +GTEST_DECLARE_string_(output); + +// This flags control whether Google Test prints the elapsed time for each +// test. +GTEST_DECLARE_bool_(print_time); + +// This flag specifies the random number seed. +GTEST_DECLARE_int32_(random_seed); + +// This flag sets how many times the tests are repeated. The default value +// is 1. If the value is -1 the tests are repeating forever. +GTEST_DECLARE_int32_(repeat); + +// This flag controls whether Google Test includes Google Test internal +// stack frames in failure stack traces. +GTEST_DECLARE_bool_(show_internal_stack_frames); + +// When this flag is specified, tests' order is randomized on every iteration. +GTEST_DECLARE_bool_(shuffle); + +// This flag specifies the maximum number of stack frames to be +// printed in a failure message. +GTEST_DECLARE_int32_(stack_trace_depth); + +// When this flag is specified, a failed assertion will throw an +// exception if exceptions are enabled, or exit the program with a +// non-zero code otherwise. +GTEST_DECLARE_bool_(throw_on_failure); + +// When this flag is set with a "host:port" string, on supported +// platforms test results are streamed to the specified port on +// the specified host machine. +GTEST_DECLARE_string_(stream_result_to); + +// The upper limit for valid stack trace depths. +const int kMaxStackTraceDepth = 100; + +namespace internal { + +class AssertHelper; +class DefaultGlobalTestPartResultReporter; +class ExecDeathTest; +class NoExecDeathTest; +class FinalSuccessChecker; +class GTestFlagSaver; +class TestResultAccessor; +class TestEventListenersAccessor; +class TestEventRepeater; +class WindowsDeathTest; +class UnitTestImpl* GetUnitTestImpl(); +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const String& message); + +// Converts a streamable value to a String. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". +// Declared in gtest-internal.h but defined here, so that it has access +// to the definition of the Message class, required by the ARM +// compiler. +template +String StreamableToString(const T& streamable) { + return (Message() << streamable).GetString(); +} + +} // namespace internal + +// The friend relationship of some of these classes is cyclic. +// If we don't forward declare them the compiler might confuse the classes +// in friendship clauses with same named classes on the scope. +class Test; +class TestCase; +class TestInfo; +class UnitTest; + +// A class for indicating whether an assertion was successful. When +// the assertion wasn't successful, the AssertionResult object +// remembers a non-empty message that describes how it failed. +// +// To create an instance of this class, use one of the factory functions +// (AssertionSuccess() and AssertionFailure()). +// +// This class is useful for two purposes: +// 1. Defining predicate functions to be used with Boolean test assertions +// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts +// 2. Defining predicate-format functions to be +// used with predicate assertions (ASSERT_PRED_FORMAT*, etc). +// +// For example, if you define IsEven predicate: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5))) +// will print the message +// +// Value of: IsEven(Fib(5)) +// Actual: false (5 is odd) +// Expected: true +// +// instead of a more opaque +// +// Value of: IsEven(Fib(5)) +// Actual: false +// Expected: true +// +// in case IsEven is a simple Boolean predicate. +// +// If you expect your predicate to be reused and want to support informative +// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up +// about half as often as positive ones in our tests), supply messages for +// both success and failure cases: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess() << n << " is even"; +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print +// +// Value of: IsEven(Fib(6)) +// Actual: true (8 is even) +// Expected: false +// +// NB: Predicates that support negative Boolean assertions have reduced +// performance in positive ones so be careful not to use them in tests +// that have lots (tens of thousands) of positive Boolean assertions. +// +// To use this class with EXPECT_PRED_FORMAT assertions such as: +// +// // Verifies that Foo() returns an even number. +// EXPECT_PRED_FORMAT1(IsEven, Foo()); +// +// you need to define: +// +// testing::AssertionResult IsEven(const char* expr, int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() +// << "Expected: " << expr << " is even\n Actual: it's " << n; +// } +// +// If Foo() returns 5, you will see the following message: +// +// Expected: Foo() is even +// Actual: it's 5 +// +class GTEST_API_ AssertionResult { + public: + // Copy constructor. + // Used in EXPECT_TRUE/FALSE(assertion_result). + AssertionResult(const AssertionResult& other); + // Used in the EXPECT_TRUE/FALSE(bool_expression). + explicit AssertionResult(bool success) : success_(success) {} + + // Returns true iff the assertion succeeded. + operator bool() const { return success_; } // NOLINT + + // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. + AssertionResult operator!() const; + + // Returns the text streamed into this AssertionResult. Test assertions + // use it when they fail (i.e., the predicate's outcome doesn't match the + // assertion's expectation). When nothing has been streamed into the + // object, returns an empty string. + const char* message() const { + return message_.get() != NULL ? message_->c_str() : ""; + } + // TODO(vladl@google.com): Remove this after making sure no clients use it. + // Deprecated; please use message() instead. + const char* failure_message() const { return message(); } + + // Streams a custom failure message into this object. + template AssertionResult& operator<<(const T& value) { + AppendMessage(Message() << value); + return *this; + } + + // Allows streaming basic output manipulators such as endl or flush into + // this object. + AssertionResult& operator<<( + ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) { + AppendMessage(Message() << basic_manipulator); + return *this; + } + + private: + // Appends the contents of message to message_. + void AppendMessage(const Message& a_message) { + if (message_.get() == NULL) + message_.reset(new ::std::string); + message_->append(a_message.GetString().c_str()); + } + + // Stores result of the assertion predicate. + bool success_; + // Stores the message describing the condition in case the expectation + // construct is not satisfied with the predicate's outcome. + // Referenced via a pointer to avoid taking too much stack frame space + // with test assertions. + internal::scoped_ptr< ::std::string> message_; + + GTEST_DISALLOW_ASSIGN_(AssertionResult); +}; + +// Makes a successful assertion result. +GTEST_API_ AssertionResult AssertionSuccess(); + +// Makes a failed assertion result. +GTEST_API_ AssertionResult AssertionFailure(); + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << msg. +GTEST_API_ AssertionResult AssertionFailure(const Message& msg); + +// The abstract class that all tests inherit from. +// +// In Google Test, a unit test program contains one or many TestCases, and +// each TestCase contains one or many Tests. +// +// When you define a test using the TEST macro, you don't need to +// explicitly derive from Test - the TEST macro automatically does +// this for you. +// +// The only time you derive from Test is when defining a test fixture +// to be used a TEST_F. For example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { ... } +// virtual void TearDown() { ... } +// ... +// }; +// +// TEST_F(FooTest, Bar) { ... } +// TEST_F(FooTest, Baz) { ... } +// +// Test is not copyable. +class GTEST_API_ Test { + public: + friend class TestInfo; + + // Defines types for pointers to functions that set up and tear down + // a test case. + typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc; + typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc; + + // The d'tor is virtual as we intend to inherit from Test. + virtual ~Test(); + + // Sets up the stuff shared by all tests in this test case. + // + // Google Test will call Foo::SetUpTestCase() before running the first + // test in test case Foo. Hence a sub-class can define its own + // SetUpTestCase() method to shadow the one defined in the super + // class. + static void SetUpTestCase() {} + + // Tears down the stuff shared by all tests in this test case. + // + // Google Test will call Foo::TearDownTestCase() after running the last + // test in test case Foo. Hence a sub-class can define its own + // TearDownTestCase() method to shadow the one defined in the super + // class. + static void TearDownTestCase() {} + + // Returns true iff the current test has a fatal failure. + static bool HasFatalFailure(); + + // Returns true iff the current test has a non-fatal failure. + static bool HasNonfatalFailure(); + + // Returns true iff the current test has a (either fatal or + // non-fatal) failure. + static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } + + // Logs a property for the current test. Only the last value for a given + // key is remembered. + // These are public static so they can be called from utility functions + // that are not members of the test fixture. + // The arguments are const char* instead strings, as Google Test is used + // on platforms where string doesn't compile. + // + // Note that a driving consideration for these RecordProperty methods + // was to produce xml output suited to the Greenspan charting utility, + // which at present will only chart values that fit in a 32-bit int. It + // is the user's responsibility to restrict their values to 32-bit ints + // if they intend them to be used with Greenspan. + static void RecordProperty(const char* key, const char* value); + static void RecordProperty(const char* key, int value); + + protected: + // Creates a Test object. + Test(); + + // Sets up the test fixture. + virtual void SetUp(); + + // Tears down the test fixture. + virtual void TearDown(); + + private: + // Returns true iff the current test has the same fixture class as + // the first test in the current test case. + static bool HasSameFixtureClass(); + + // Runs the test after the test fixture has been set up. + // + // A sub-class must implement this to define the test logic. + // + // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. + // Instead, use the TEST or TEST_F macro. + virtual void TestBody() = 0; + + // Sets up, executes, and tears down the test. + void Run(); + + // Deletes self. We deliberately pick an unusual name for this + // internal method to avoid clashing with names used in user TESTs. + void DeleteSelf_() { delete this; } + + // Uses a GTestFlagSaver to save and restore all Google Test flags. + const internal::GTestFlagSaver* const gtest_flag_saver_; + + // Often a user mis-spells SetUp() as Setup() and spends a long time + // wondering why it is never called by Google Test. The declaration of + // the following method is solely for catching such an error at + // compile time: + // + // - The return type is deliberately chosen to be not void, so it + // will be a conflict if a user declares void Setup() in his test + // fixture. + // + // - This method is private, so it will be another compiler error + // if a user calls it from his test fixture. + // + // DO NOT OVERRIDE THIS FUNCTION. + // + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } + + // We disallow copying Tests. + GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); +}; + +typedef internal::TimeInMillis TimeInMillis; + +// A copyable object representing a user specified test property which can be +// output as a key/value string pair. +// +// Don't inherit from TestProperty as its destructor is not virtual. +class TestProperty { + public: + // C'tor. TestProperty does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestProperty object. + TestProperty(const char* a_key, const char* a_value) : + key_(a_key), value_(a_value) { + } + + // Gets the user supplied key. + const char* key() const { + return key_.c_str(); + } + + // Gets the user supplied value. + const char* value() const { + return value_.c_str(); + } + + // Sets a new value, overriding the one supplied in the constructor. + void SetValue(const char* new_value) { + value_ = new_value; + } + + private: + // The key supplied by the user. + internal::String key_; + // The value supplied by the user. + internal::String value_; +}; + +// The result of a single Test. This includes a list of +// TestPartResults, a list of TestProperties, a count of how many +// death tests there are in the Test, and how much time it took to run +// the Test. +// +// TestResult is not copyable. +class GTEST_API_ TestResult { + public: + // Creates an empty TestResult. + TestResult(); + + // D'tor. Do not inherit from TestResult. + ~TestResult(); + + // Gets the number of all test parts. This is the sum of the number + // of successful test parts and the number of failed test parts. + int total_part_count() const; + + // Returns the number of the test properties. + int test_property_count() const; + + // Returns true iff the test passed (i.e. no test part failed). + bool Passed() const { return !Failed(); } + + // Returns true iff the test failed. + bool Failed() const; + + // Returns true iff the test fatally failed. + bool HasFatalFailure() const; + + // Returns true iff the test has a non-fatal failure. + bool HasNonfatalFailure() const; + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test part result among all the results. i can range + // from 0 to test_property_count() - 1. If i is not in that range, aborts + // the program. + const TestPartResult& GetTestPartResult(int i) const; + + // Returns the i-th test property. i can range from 0 to + // test_property_count() - 1. If i is not in that range, aborts the + // program. + const TestProperty& GetTestProperty(int i) const; + + private: + friend class TestInfo; + friend class UnitTest; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::ExecDeathTest; + friend class internal::TestResultAccessor; + friend class internal::UnitTestImpl; + friend class internal::WindowsDeathTest; + + // Gets the vector of TestPartResults. + const std::vector& test_part_results() const { + return test_part_results_; + } + + // Gets the vector of TestProperties. + const std::vector& test_properties() const { + return test_properties_; + } + + // Sets the elapsed time. + void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } + + // Adds a test property to the list. The property is validated and may add + // a non-fatal failure if invalid (e.g., if it conflicts with reserved + // key names). If a property is already recorded for the same key, the + // value will be updated, rather than storing multiple values for the same + // key. + void RecordProperty(const TestProperty& test_property); + + // Adds a failure if the key is a reserved attribute of Google Test + // testcase tags. Returns true if the property is valid. + // TODO(russr): Validate attribute names are legal and human readable. + static bool ValidateTestProperty(const TestProperty& test_property); + + // Adds a test part result to the list. + void AddTestPartResult(const TestPartResult& test_part_result); + + // Returns the death test count. + int death_test_count() const { return death_test_count_; } + + // Increments the death test count, returning the new count. + int increment_death_test_count() { return ++death_test_count_; } + + // Clears the test part results. + void ClearTestPartResults(); + + // Clears the object. + void Clear(); + + // Protects mutable state of the property vector and of owned + // properties, whose values may be updated. + internal::Mutex test_properites_mutex_; + + // The vector of TestPartResults + std::vector test_part_results_; + // The vector of TestProperties + std::vector test_properties_; + // Running count of death tests. + int death_test_count_; + // The elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestResult. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); +}; // class TestResult + +// A TestInfo object stores the following information about a test: +// +// Test case name +// Test name +// Whether the test should be run +// A function pointer that creates the test object when invoked +// Test result +// +// The constructor of TestInfo registers itself with the UnitTest +// singleton such that the RUN_ALL_TESTS() macro knows which tests to +// run. +class GTEST_API_ TestInfo { + public: + // Destructs a TestInfo object. This function is not virtual, so + // don't inherit from TestInfo. + ~TestInfo(); + + // Returns the test case name. + const char* test_case_name() const { return test_case_name_.c_str(); } + + // Returns the test name. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a typed + // or a type-parameterized test. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns the text representation of the value parameter, or NULL if this + // is not a value-parameterized test. + const char* value_param() const { + if (value_param_.get() != NULL) + return value_param_->c_str(); + return NULL; + } + + // Returns true if this test should run, that is if the test is not disabled + // (or it is disabled but the also_run_disabled_tests flag has been specified) + // and its full name matches the user-specified filter. + // + // Google Test allows the user to filter the tests by their full names. + // The full name of a test Bar in test case Foo is defined as + // "Foo.Bar". Only the tests that match the filter will run. + // + // A filter is a colon-separated list of glob (not regex) patterns, + // optionally followed by a '-' and a colon-separated list of + // negative patterns (tests to exclude). A test is run if it + // matches one of the positive patterns and does not match any of + // the negative patterns. + // + // For example, *A*:Foo.* is a filter that matches any string that + // contains the character 'A' or starts with "Foo.". + bool should_run() const { return should_run_; } + + // Returns the result of the test. + const TestResult* result() const { return &result_; } + + private: + +#if GTEST_HAS_DEATH_TEST + friend class internal::DefaultDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + friend class Test; + friend class TestCase; + friend class internal::UnitTestImpl; + friend TestInfo* internal::MakeAndRegisterTestInfo( + const char* test_case_name, const char* name, + const char* type_param, + const char* value_param, + internal::TypeId fixture_class_id, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + internal::TestFactoryBase* factory); + + // Constructs a TestInfo object. The newly constructed instance assumes + // ownership of the factory object. + TestInfo(const char* test_case_name, const char* name, + const char* a_type_param, + const char* a_value_param, + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory); + + // Increments the number of death tests encountered in this test so + // far. + int increment_death_test_count() { + return result_.increment_death_test_count(); + } + + // Creates the test object, runs it, records its result, and then + // deletes it. + void Run(); + + static void ClearTestResult(TestInfo* test_info) { + test_info->result_.Clear(); + } + + // These fields are immutable properties of the test. + const std::string test_case_name_; // Test case name + const std::string name_; // Test name + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // Text representation of the value parameter, or NULL if this is not a + // value-parameterized test. + const internal::scoped_ptr value_param_; + const internal::TypeId fixture_class_id_; // ID of the test fixture class + bool should_run_; // True iff this test should run + bool is_disabled_; // True iff this test is disabled + bool matches_filter_; // True if this test matches the + // user-specified filter. + internal::TestFactoryBase* const factory_; // The factory that creates + // the test object + + // This field is mutable and needs to be reset before running the + // test for the second time. + TestResult result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); +}; + +// A test case, which consists of a vector of TestInfos. +// +// TestCase is not copyable. +class GTEST_API_ TestCase { + public: + // Creates a TestCase with the given name. + // + // TestCase does NOT have a default constructor. Always use this + // constructor to create a TestCase object. + // + // Arguments: + // + // name: name of the test case + // a_type_param: the name of the test's type parameter, or NULL if + // this is not a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase(const char* name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Destructor of TestCase. + virtual ~TestCase(); + + // Gets the name of the TestCase. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a + // type-parameterized test case. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns true if any test in this test case should run. + bool should_run() const { return should_run_; } + + // Gets the number of successful tests in this test case. + int successful_test_count() const; + + // Gets the number of failed tests in this test case. + int failed_test_count() const; + + // Gets the number of disabled tests in this test case. + int disabled_test_count() const; + + // Get the number of tests in this test case that should run. + int test_to_run_count() const; + + // Gets the number of all tests in this test case. + int total_test_count() const; + + // Returns true iff the test case passed. + bool Passed() const { return !Failed(); } + + // Returns true iff the test case failed. + bool Failed() const { return failed_test_count() > 0; } + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + const TestInfo* GetTestInfo(int i) const; + + private: + friend class Test; + friend class internal::UnitTestImpl; + + // Gets the (mutable) vector of TestInfos in this TestCase. + std::vector& test_info_list() { return test_info_list_; } + + // Gets the (immutable) vector of TestInfos in this TestCase. + const std::vector& test_info_list() const { + return test_info_list_; + } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + TestInfo* GetMutableTestInfo(int i); + + // Sets the should_run member. + void set_should_run(bool should) { should_run_ = should; } + + // Adds a TestInfo to this test case. Will delete the TestInfo upon + // destruction of the TestCase object. + void AddTestInfo(TestInfo * test_info); + + // Clears the results of all tests in this test case. + void ClearResult(); + + // Clears the results of all tests in the given test case. + static void ClearTestCaseResult(TestCase* test_case) { + test_case->ClearResult(); + } + + // Runs every test in this TestCase. + void Run(); + + // Runs SetUpTestCase() for this TestCase. This wrapper is needed + // for catching exceptions thrown from SetUpTestCase(). + void RunSetUpTestCase() { (*set_up_tc_)(); } + + // Runs TearDownTestCase() for this TestCase. This wrapper is + // needed for catching exceptions thrown from TearDownTestCase(). + void RunTearDownTestCase() { (*tear_down_tc_)(); } + + // Returns true iff test passed. + static bool TestPassed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Passed(); + } + + // Returns true iff test failed. + static bool TestFailed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Failed(); + } + + // Returns true iff test is disabled. + static bool TestDisabled(const TestInfo* test_info) { + return test_info->is_disabled_; + } + + // Returns true if the given test should run. + static bool ShouldRunTest(const TestInfo* test_info) { + return test_info->should_run(); + } + + // Shuffles the tests in this test case. + void ShuffleTests(internal::Random* random); + + // Restores the test order to before the first shuffle. + void UnshuffleTests(); + + // Name of the test case. + internal::String name_; + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // The vector of TestInfos in their original order. It owns the + // elements in the vector. + std::vector test_info_list_; + // Provides a level of indirection for the test list to allow easy + // shuffling and restoring the test order. The i-th element in this + // vector is the index of the i-th test in the shuffled test list. + std::vector test_indices_; + // Pointer to the function that sets up the test case. + Test::SetUpTestCaseFunc set_up_tc_; + // Pointer to the function that tears down the test case. + Test::TearDownTestCaseFunc tear_down_tc_; + // True iff any test in this test case should run. + bool should_run_; + // Elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestCases. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); +}; + +// An Environment object is capable of setting up and tearing down an +// environment. The user should subclass this to define his own +// environment(s). +// +// An Environment object does the set-up and tear-down in virtual +// methods SetUp() and TearDown() instead of the constructor and the +// destructor, as: +// +// 1. You cannot safely throw from a destructor. This is a problem +// as in some cases Google Test is used where exceptions are enabled, and +// we may want to implement ASSERT_* using exceptions where they are +// available. +// 2. You cannot use ASSERT_* directly in a constructor or +// destructor. +class Environment { + public: + // The d'tor is virtual as we need to subclass Environment. + virtual ~Environment() {} + + // Override this to define how to set up the environment. + virtual void SetUp() {} + + // Override this to define how to tear down the environment. + virtual void TearDown() {} + private: + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } +}; + +// The interface for tracing execution of tests. The methods are organized in +// the order the corresponding events are fired. +class TestEventListener { + public: + virtual ~TestEventListener() {} + + // Fired before any test activity starts. + virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; + + // Fired before each iteration of tests starts. There may be more than + // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration + // index, starting from 0. + virtual void OnTestIterationStart(const UnitTest& unit_test, + int iteration) = 0; + + // Fired before environment set-up for each iteration of tests starts. + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; + + // Fired after environment set-up for each iteration of tests ends. + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; + + // Fired before the test case starts. + virtual void OnTestCaseStart(const TestCase& test_case) = 0; + + // Fired before the test starts. + virtual void OnTestStart(const TestInfo& test_info) = 0; + + // Fired after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; + + // Fired after the test ends. + virtual void OnTestEnd(const TestInfo& test_info) = 0; + + // Fired after the test case ends. + virtual void OnTestCaseEnd(const TestCase& test_case) = 0; + + // Fired before environment tear-down for each iteration of tests starts. + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; + + // Fired after environment tear-down for each iteration of tests ends. + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; + + // Fired after each iteration of tests finishes. + virtual void OnTestIterationEnd(const UnitTest& unit_test, + int iteration) = 0; + + // Fired after all test activities have ended. + virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; +}; + +// The convenience class for users who need to override just one or two +// methods and are not concerned that a possible change to a signature of +// the methods they override will not be caught during the build. For +// comments about each method please see the definition of TestEventListener +// above. +class EmptyTestEventListener : public TestEventListener { + public: + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} + virtual void OnTestStart(const TestInfo& /*test_info*/) {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} +}; + +// TestEventListeners lets users add listeners to track events in Google Test. +class GTEST_API_ TestEventListeners { + public: + TestEventListeners(); + ~TestEventListeners(); + + // Appends an event listener to the end of the list. Google Test assumes + // the ownership of the listener (i.e. it will delete the listener when + // the test program finishes). + void Append(TestEventListener* listener); + + // Removes the given event listener from the list and returns it. It then + // becomes the caller's responsibility to delete the listener. Returns + // NULL if the listener is not found in the list. + TestEventListener* Release(TestEventListener* listener); + + // Returns the standard listener responsible for the default console + // output. Can be removed from the listeners list to shut down default + // console output. Note that removing this object from the listener list + // with Release transfers its ownership to the caller and makes this + // function return NULL the next time. + TestEventListener* default_result_printer() const { + return default_result_printer_; + } + + // Returns the standard listener responsible for the default XML output + // controlled by the --gtest_output=xml flag. Can be removed from the + // listeners list by users who want to shut down the default XML output + // controlled by this flag and substitute it with custom one. Note that + // removing this object from the listener list with Release transfers its + // ownership to the caller and makes this function return NULL the next + // time. + TestEventListener* default_xml_generator() const { + return default_xml_generator_; + } + + private: + friend class TestCase; + friend class TestInfo; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::NoExecDeathTest; + friend class internal::TestEventListenersAccessor; + friend class internal::UnitTestImpl; + + // Returns repeater that broadcasts the TestEventListener events to all + // subscribers. + TestEventListener* repeater(); + + // Sets the default_result_printer attribute to the provided listener. + // The listener is also added to the listener list and previous + // default_result_printer is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultResultPrinter(TestEventListener* listener); + + // Sets the default_xml_generator attribute to the provided listener. The + // listener is also added to the listener list and previous + // default_xml_generator is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultXmlGenerator(TestEventListener* listener); + + // Controls whether events will be forwarded by the repeater to the + // listeners in the list. + bool EventForwardingEnabled() const; + void SuppressEventForwarding(); + + // The actual list of listeners. + internal::TestEventRepeater* repeater_; + // Listener responsible for the standard result output. + TestEventListener* default_result_printer_; + // Listener responsible for the creation of the XML output file. + TestEventListener* default_xml_generator_; + + // We disallow copying TestEventListeners. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); +}; + +// A UnitTest consists of a vector of TestCases. +// +// This is a singleton class. The only instance of UnitTest is +// created when UnitTest::GetInstance() is first called. This +// instance is never deleted. +// +// UnitTest is not copyable. +// +// This class is thread-safe as long as the methods are called +// according to their specification. +class GTEST_API_ UnitTest { + public: + // Gets the singleton UnitTest object. The first time this method + // is called, a UnitTest object is constructed and returned. + // Consecutive calls will return the same object. + static UnitTest* GetInstance(); + + // Runs all tests in this UnitTest object and prints the result. + // Returns 0 if successful, or 1 otherwise. + // + // This method can only be called from the main thread. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + int Run() GTEST_MUST_USE_RESULT_; + + // Returns the working directory when the first TEST() or TEST_F() + // was executed. The UnitTest object owns the string. + const char* original_working_dir() const; + + // Returns the TestCase object for the test that's currently running, + // or NULL if no test is running. + const TestCase* current_test_case() const; + + // Returns the TestInfo object for the test that's currently running, + // or NULL if no test is running. + const TestInfo* current_test_info() const; + + // Returns the random seed used at the start of the current test run. + int random_seed() const; + +#if GTEST_HAS_PARAM_TEST + // Returns the ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry(); +#endif // GTEST_HAS_PARAM_TEST + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const; + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const; + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const; + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const; + + // Returns the list of event listeners that can be used to track events + // inside Google Test. + TestEventListeners& listeners(); + + private: + // Registers and returns a global test environment. When a test + // program is run, all global test environments will be set-up in + // the order they were registered. After all tests in the program + // have finished, all global test environments will be torn-down in + // the *reverse* order they were registered. + // + // The UnitTest object takes ownership of the given environment. + // + // This method can only be called from the main thread. + Environment* AddEnvironment(Environment* env); + + // Adds a TestPartResult to the current TestResult object. All + // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) + // eventually call this to report their results. The user code + // should use the assertion macros instead of calling this directly. + void AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const internal::String& message, + const internal::String& os_stack_trace); + + // Adds a TestProperty to the current TestResult object. If the result already + // contains a property with the same key, the value will be updated. + void RecordPropertyForCurrentTest(const char* key, const char* value); + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i); + + // Accessors for the implementation object. + internal::UnitTestImpl* impl() { return impl_; } + const internal::UnitTestImpl* impl() const { return impl_; } + + // These classes and funcions are friends as they need to access private + // members of UnitTest. + friend class Test; + friend class internal::AssertHelper; + friend class internal::ScopedTrace; + friend Environment* AddGlobalTestEnvironment(Environment* env); + friend internal::UnitTestImpl* internal::GetUnitTestImpl(); + friend void internal::ReportFailureInUnknownLocation( + TestPartResult::Type result_type, + const internal::String& message); + + // Creates an empty UnitTest. + UnitTest(); + + // D'tor + virtual ~UnitTest(); + + // Pushes a trace defined by SCOPED_TRACE() on to the per-thread + // Google Test trace stack. + void PushGTestTrace(const internal::TraceInfo& trace); + + // Pops a trace from the per-thread Google Test trace stack. + void PopGTestTrace(); + + // Protects mutable state in *impl_. This is mutable as some const + // methods need to lock it too. + mutable internal::Mutex mutex_; + + // Opaque implementation object. This field is never changed once + // the object is constructed. We don't mark it as const here, as + // doing so will cause a warning in the constructor of UnitTest. + // Mutable state in *impl_ is protected by mutex_. + internal::UnitTestImpl* impl_; + + // We disallow copying UnitTest. + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest); +}; + +// A convenient wrapper for adding an environment for the test +// program. +// +// You should call this before RUN_ALL_TESTS() is called, probably in +// main(). If you use gtest_main, you need to call this before main() +// starts for it to take effect. For example, you can define a global +// variable like this: +// +// testing::Environment* const foo_env = +// testing::AddGlobalTestEnvironment(new FooEnvironment); +// +// However, we strongly recommend you to write your own main() and +// call AddGlobalTestEnvironment() there, as relying on initialization +// of global variables makes the code harder to read and may cause +// problems when you register multiple environments from different +// translation units and the environments have dependencies among them +// (remember that the compiler doesn't guarantee the order in which +// global variables from different translation units are initialized). +inline Environment* AddGlobalTestEnvironment(Environment* env) { + return UnitTest::GetInstance()->AddEnvironment(env); +} + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +GTEST_API_ void InitGoogleTest(int* argc, char** argv); + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); + +namespace internal { + +// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) +// operand to be used in a failure message. The type (but not value) +// of the other operand may affect the format. This allows us to +// print a char* as a raw pointer when it is compared against another +// char*, and print it as a C string when it is compared against an +// std::string object, for example. +// +// The default implementation ignores the type of the other operand. +// Some specialized versions are used to handle formatting wide or +// narrow C strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +String FormatForComparisonFailureMessage(const T1& value, + const T2& /* other_operand */) { + // C++Builder compiles this incorrectly if the namespace isn't explicitly + // given. + return ::testing::PrintToString(value); +} + +// The helper function for {ASSERT|EXPECT}_EQ. +template +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4389) // Temporarily disables warning on + // signed/unsigned mismatch. +#endif + + if (expected == actual) { + return AssertionSuccess(); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// With this overloaded version, we allow anonymous enums to be used +// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums +// can be implicitly cast to BiggestInt. +GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual); + +// The helper class for {ASSERT|EXPECT}_EQ. The template argument +// lhs_is_null_literal is true iff the first argument to ASSERT_EQ() +// is a null pointer literal. The following default implementation is +// for lhs_is_null_literal being false. +template +class EqHelper { + public: + // This templatized version is for the general case. + template + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // With this overloaded version, we allow anonymous enums to be used + // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous + // enums can be implicitly cast to BiggestInt. + // + // Even though its body looks the same as the above version, we + // cannot merge the two, as it will make anonymous enums unhappy. + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } +}; + +// This specialization is used when the first argument to ASSERT_EQ() +// is a null pointer literal, like NULL, false, or 0. +template <> +class EqHelper { + public: + // We define two overloaded versions of Compare(). The first + // version will be picked when the second argument to ASSERT_EQ() is + // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or + // EXPECT_EQ(false, a_bool). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual, + // The following line prevents this overload from being considered if T2 + // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr) + // expands to Compare("", "", NULL, my_ptr), which requires a conversion + // to match the Secret* in the other overload, which would otherwise make + // this template match better. + typename EnableIf::value>::type* = 0) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // This version will be picked when the second argument to ASSERT_EQ() is a + // pointer, e.g. ASSERT_EQ(NULL, a_pointer). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + // We used to have a second template parameter instead of Secret*. That + // template parameter would deduce to 'long', making this a better match + // than the first overload even without the first overload's EnableIf. + // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to + // non-pointer argument" (even a deduced integral argument), so the old + // implementation caused warnings in user code. + Secret* /* expected (NULL) */, + T* actual) { + // We already know that 'expected' is a null pointer. + return CmpHelperEQ(expected_expression, actual_expression, + static_cast(NULL), actual); + } +}; + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste +// of similar code. +// +// For each templatized helper function, we also define an overloaded +// version for BiggestInt in order to reduce code bloat and allow +// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled +// with gcc 4. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +template \ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + const T1& val1, const T2& val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +}\ +GTEST_API_ AssertionResult CmpHelper##op_name(\ + const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) + +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// Implements the helper function for {ASSERT|EXPECT}_NE +GTEST_IMPL_CMP_HELPER_(NE, !=); +// Implements the helper function for {ASSERT|EXPECT}_LE +GTEST_IMPL_CMP_HELPER_(LE, <=); +// Implements the helper function for {ASSERT|EXPECT}_LT +GTEST_IMPL_CMP_HELPER_(LT, < ); +// Implements the helper function for {ASSERT|EXPECT}_GE +GTEST_IMPL_CMP_HELPER_(GE, >=); +// Implements the helper function for {ASSERT|EXPECT}_GT +GTEST_IMPL_CMP_HELPER_(GT, > ); + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRNE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + + +// Helper function for *_STREQ on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual); + +// Helper function for *_STRNE on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2); + +} // namespace internal + +// IsSubstring() and IsNotSubstring() are intended to be used as the +// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by +// themselves. They check whether needle is a substring of haystack +// (NULL is considered a substring of itself only), and return an +// appropriate error message when they fail. +// +// The {needle,haystack}_expr arguments are the stringified +// expressions that generated the two real arguments. +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +// Helper template function for comparing floating-points. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression, + const char* actual_expression, + RawType expected, + RawType actual) { + const FloatingPoint lhs(expected), rhs(actual); + + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + ::std::stringstream expected_ss; + expected_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << expected; + + ::std::stringstream actual_ss; + actual_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << actual; + + return EqFailure(expected_expression, + actual_expression, + StringStreamToString(&expected_ss), + StringStreamToString(&actual_ss), + false); +} + +// Helper function for implementing ASSERT_NEAR. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error); + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// A class that enables one to stream messages to assertion macros +class GTEST_API_ AssertHelper { + public: + // Constructor. + AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message); + ~AssertHelper(); + + // Message assignment is a semantic trick to enable assertion + // streaming; see the GTEST_MESSAGE_ macro below. + void operator=(const Message& message) const; + + private: + // We put our data in a struct so that the size of the AssertHelper class can + // be as small as possible. This is important because gcc is incapable of + // re-using stack space even for temporary variables, so every EXPECT_EQ + // reserves stack space for another AssertHelper. + struct AssertHelperData { + AssertHelperData(TestPartResult::Type t, + const char* srcfile, + int line_num, + const char* msg) + : type(t), file(srcfile), line(line_num), message(msg) { } + + TestPartResult::Type const type; + const char* const file; + int const line; + String const message; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); + }; + + AssertHelperData* const data_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); +}; + +} // namespace internal + +#if GTEST_HAS_PARAM_TEST +// The pure interface class that all value-parameterized tests inherit from. +// A value-parameterized class must inherit from both ::testing::Test and +// ::testing::WithParamInterface. In most cases that just means inheriting +// from ::testing::TestWithParam, but more complicated test hierarchies +// may need to inherit from Test and WithParamInterface at different levels. +// +// This interface has support for accessing the test parameter value via +// the GetParam() method. +// +// Use it with one of the parameter generator defining functions, like Range(), +// Values(), ValuesIn(), Bool(), and Combine(). +// +// class FooTest : public ::testing::TestWithParam { +// protected: +// FooTest() { +// // Can use GetParam() here. +// } +// virtual ~FooTest() { +// // Can use GetParam() here. +// } +// virtual void SetUp() { +// // Can use GetParam() here. +// } +// virtual void TearDown { +// // Can use GetParam() here. +// } +// }; +// TEST_P(FooTest, DoesBar) { +// // Can use GetParam() method here. +// Foo foo; +// ASSERT_TRUE(foo.DoesBar(GetParam())); +// } +// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); + +template +class WithParamInterface { + public: + typedef T ParamType; + virtual ~WithParamInterface() {} + + // The current parameter value. Is also available in the test fixture's + // constructor. This member function is non-static, even though it only + // references static data, to reduce the opportunity for incorrect uses + // like writing 'WithParamInterface::GetParam()' for a test that + // uses a fixture whose parameter type is int. + const ParamType& GetParam() const { return *parameter_; } + + private: + // Sets parameter value. The caller is responsible for making sure the value + // remains alive and unchanged throughout the current test. + static void SetParam(const ParamType* parameter) { + parameter_ = parameter; + } + + // Static value used for accessing parameter during a test lifetime. + static const ParamType* parameter_; + + // TestClass must be a subclass of WithParamInterface and Test. + template friend class internal::ParameterizedTestFactory; +}; + +template +const T* WithParamInterface::parameter_ = NULL; + +// Most value-parameterized classes can ignore the existence of +// WithParamInterface, and can just inherit from ::testing::TestWithParam. + +template +class TestWithParam : public Test, public WithParamInterface { +}; + +#endif // GTEST_HAS_PARAM_TEST + +// Macros for indicating success/failure in test code. + +// ADD_FAILURE unconditionally adds a failure to the current test. +// SUCCEED generates a success - it doesn't automatically make the +// current test successful, as a test is only successful when it has +// no failure. +// +// EXPECT_* verifies that a certain condition is satisfied. If not, +// it behaves like ADD_FAILURE. In particular: +// +// EXPECT_TRUE verifies that a Boolean condition is true. +// EXPECT_FALSE verifies that a Boolean condition is false. +// +// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except +// that they will also abort the current function on failure. People +// usually want the fail-fast behavior of FAIL and ASSERT_*, but those +// writing data-driven tests often find themselves using ADD_FAILURE +// and EXPECT_* more. +// +// Examples: +// +// EXPECT_TRUE(server.StatusIsOK()); +// ASSERT_FALSE(server.HasPendingRequest(port)) +// << "There are still pending requests " << "on port " << port; + +// Generates a nonfatal failure with a generic message. +#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") + +// Generates a nonfatal failure at the given source file location with +// a generic message. +#define ADD_FAILURE_AT(file, line) \ + GTEST_MESSAGE_AT_(file, line, "Failed", \ + ::testing::TestPartResult::kNonFatalFailure) + +// Generates a fatal failure with a generic message. +#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") + +// Define this macro to 1 to omit the definition of FAIL(), which is a +// generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_FAIL +# define FAIL() GTEST_FAIL() +#endif + +// Generates a success with a generic message. +#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") + +// Define this macro to 1 to omit the definition of SUCCEED(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_SUCCEED +# define SUCCEED() GTEST_SUCCEED() +#endif + +// Macros for testing exceptions. +// +// * {ASSERT|EXPECT}_THROW(statement, expected_exception): +// Tests that the statement throws the expected exception. +// * {ASSERT|EXPECT}_NO_THROW(statement): +// Tests that the statement doesn't throw any exception. +// * {ASSERT|EXPECT}_ANY_THROW(statement): +// Tests that the statement throws an exception. + +#define EXPECT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_) +#define EXPECT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define EXPECT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define ASSERT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_) +#define ASSERT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_) +#define ASSERT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) + +// Boolean assertions. Condition can be either a Boolean expression or an +// AssertionResult. For more information on how to use AssertionResult with +// these macros see comments on that class. +#define EXPECT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_NONFATAL_FAILURE_) +#define EXPECT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_NONFATAL_FAILURE_) +#define ASSERT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_FATAL_FAILURE_) +#define ASSERT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_FATAL_FAILURE_) + +// Includes the auto-generated header that implements a family of +// generic predicate assertion macros. +// Copyright 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file is AUTOMATICALLY GENERATED on 09/24/2010 by command +// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! +// +// Implements a family of generic predicate assertion macros. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Makes sure this header is not included before gtest.h. +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +# error Do not include gtest_pred_impl.h directly. Include gtest.h instead. +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ + +// This header implements a family of generic predicate assertion +// macros: +// +// ASSERT_PRED_FORMAT1(pred_format, v1) +// ASSERT_PRED_FORMAT2(pred_format, v1, v2) +// ... +// +// where pred_format is a function or functor that takes n (in the +// case of ASSERT_PRED_FORMATn) values and their source expression +// text, and returns a testing::AssertionResult. See the definition +// of ASSERT_EQ in gtest.h for an example. +// +// If you don't care about formatting, you can use the more +// restrictive version: +// +// ASSERT_PRED1(pred, v1) +// ASSERT_PRED2(pred, v1, v2) +// ... +// +// where pred is an n-ary function or functor that returns bool, +// and the values v1, v2, ..., must support the << operator for +// streaming to std::ostream. +// +// We also define the EXPECT_* variations. +// +// For now we only support predicates whose arity is at most 5. +// Please email googletestframework@googlegroups.com if you need +// support for higher arities. + +// GTEST_ASSERT_ is the basic statement to which all of the assertions +// in this file reduce. Don't use this in your code. + +#define GTEST_ASSERT_(expression, on_failure) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar = (expression)) \ + ; \ + else \ + on_failure(gtest_ar.failure_message()) + + +// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +template +AssertionResult AssertPred1Helper(const char* pred_text, + const char* e1, + Pred pred, + const T1& v1) { + if (pred(v1)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. +// Don't use this in your code. +#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, v1),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +#define GTEST_PRED1_(pred, v1, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \ + #v1, \ + pred, \ + v1), on_failure) + +// Unary predicate assertion macros. +#define EXPECT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +template +AssertionResult AssertPred2Helper(const char* pred_text, + const char* e1, + const char* e2, + Pred pred, + const T1& v1, + const T2& v2) { + if (pred(v1, v2)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. +// Don't use this in your code. +#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +#define GTEST_PRED2_(pred, v1, v2, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \ + #v1, \ + #v2, \ + pred, \ + v1, \ + v2), on_failure) + +// Binary predicate assertion macros. +#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +template +AssertionResult AssertPred3Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3) { + if (pred(v1, v2, v3)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. +// Don't use this in your code. +#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + pred, \ + v1, \ + v2, \ + v3), on_failure) + +// Ternary predicate assertion macros. +#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +template +AssertionResult AssertPred4Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4) { + if (pred(v1, v2, v3, v4)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. +// Don't use this in your code. +#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4), on_failure) + +// 4-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +template +AssertionResult AssertPred5Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + const char* e5, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4, + const T5& v5) { + if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ", " + << e5 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4 + << "\n" << e5 << " evaluates to " << v5; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. +// Don't use this in your code. +#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + #v5, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4, \ + v5), on_failure) + +// 5-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) + + + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Macros for testing equalities and inequalities. +// +// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual +// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 +// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 +// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 +// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 +// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 +// +// When they are not, Google Test prints both the tested expressions and +// their actual values. The values must be compatible built-in types, +// or you will get a compiler error. By "compatible" we mean that the +// values can be compared by the respective operator. +// +// Note: +// +// 1. It is possible to make a user-defined type work with +// {ASSERT|EXPECT}_??(), but that requires overloading the +// comparison operators and is thus discouraged by the Google C++ +// Usage Guide. Therefore, you are advised to use the +// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are +// equal. +// +// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on +// pointers (in particular, C strings). Therefore, if you use it +// with two C strings, you are testing how their locations in memory +// are related, not how their content is related. To compare two C +// strings by content, use {ASSERT|EXPECT}_STR*(). +// +// 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to +// {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you +// what the actual value is when it fails, and similarly for the +// other comparisons. +// +// 4. Do not depend on the order in which {ASSERT|EXPECT}_??() +// evaluate their arguments, which is undefined. +// +// 5. These macros evaluate their arguments exactly once. +// +// Examples: +// +// EXPECT_NE(5, Foo()); +// EXPECT_EQ(NULL, a_pointer); +// ASSERT_LT(i, array_size); +// ASSERT_GT(records.size(), 0) << "There is no record left."; + +#define EXPECT_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define EXPECT_NE(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual) +#define EXPECT_LE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define EXPECT_LT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define EXPECT_GE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define EXPECT_GT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +#define GTEST_ASSERT_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define GTEST_ASSERT_NE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) +#define GTEST_ASSERT_LE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define GTEST_ASSERT_LT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define GTEST_ASSERT_GE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define GTEST_ASSERT_GT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of +// ASSERT_XY(), which clashes with some users' own code. + +#if !GTEST_DONT_DEFINE_ASSERT_EQ +# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_NE +# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LE +# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LT +# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GE +# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GT +# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2) +#endif + +// C String Comparisons. All tests treat NULL and any non-NULL string +// as different. Two NULLs are equal. +// +// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 +// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 +// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case +// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case +// +// For wide or narrow string objects, you can use the +// {ASSERT|EXPECT}_??() macros. +// +// Don't depend on the order in which the arguments are evaluated, +// which is undefined. +// +// These macros evaluate their arguments exactly once. + +#define EXPECT_STREQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define EXPECT_STRNE(s1, s2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define EXPECT_STRCASEEQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define EXPECT_STRCASENE(s1, s2)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +#define ASSERT_STREQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define ASSERT_STRNE(s1, s2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define ASSERT_STRCASEEQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define ASSERT_STRCASENE(s1, s2)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +// Macros for comparing floating-point numbers. +// +// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual): +// Tests that two float values are almost equal. +// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual): +// Tests that two double values are almost equal. +// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): +// Tests that v1 and v2 are within the given distance to each other. +// +// Google Test uses ULP-based comparison to automatically pick a default +// error bound that is appropriate for the operands. See the +// FloatingPoint template class in gtest-internal.h if you are +// interested in the implementation details. + +#define EXPECT_FLOAT_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_DOUBLE_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_FLOAT_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_DOUBLE_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_NEAR(val1, val2, abs_error)\ + EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +#define ASSERT_NEAR(val1, val2, abs_error)\ + ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +// These predicate format functions work on floating-point values, and +// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g. +// +// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0); + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2); +GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2); + + +#if GTEST_OS_WINDOWS + +// Macros that test for HRESULT failure and success, these are only useful +// on Windows, and rely on Windows SDK macros and APIs to compile. +// +// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr) +// +// When expr unexpectedly fails or succeeds, Google Test prints the +// expected result and the actual result with both a human-readable +// string representation of the error, if available, as well as the +// hex result code. +# define EXPECT_HRESULT_SUCCEEDED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define ASSERT_HRESULT_SUCCEEDED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define EXPECT_HRESULT_FAILED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +# define ASSERT_HRESULT_FAILED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +#endif // GTEST_OS_WINDOWS + +// Macros that execute statement and check that it doesn't generate new fatal +// failures in the current thread. +// +// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement); +// +// Examples: +// +// EXPECT_NO_FATAL_FAILURE(Process()); +// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; +// +#define ASSERT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) +#define EXPECT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) + +// Causes a trace (including the source file path, the current line +// number, and the given message) to be included in every test failure +// message generated by code in the current scope. The effect is +// undone when the control leaves the current scope. +// +// The message argument can be anything streamable to std::ostream. +// +// In the implementation, we include the current line number as part +// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s +// to appear in the same block - as long as they are on different +// lines. +#define SCOPED_TRACE(message) \ + ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ + __FILE__, __LINE__, ::testing::Message() << (message)) + +// Compile-time assertion for type equality. +// StaticAssertTypeEq() compiles iff type1 and type2 are +// the same type. The value it returns is not interesting. +// +// Instead of making StaticAssertTypeEq a class template, we make it a +// function template that invokes a helper class template. This +// prevents a user from misusing StaticAssertTypeEq by +// defining objects of that type. +// +// CAVEAT: +// +// When used inside a method of a class template, +// StaticAssertTypeEq() is effective ONLY IF the method is +// instantiated. For example, given: +// +// template class Foo { +// public: +// void Bar() { testing::StaticAssertTypeEq(); } +// }; +// +// the code: +// +// void Test1() { Foo foo; } +// +// will NOT generate a compiler error, as Foo::Bar() is never +// actually instantiated. Instead, you need: +// +// void Test2() { Foo foo; foo.Bar(); } +// +// to cause a compiler error. +template +bool StaticAssertTypeEq() { + (void)internal::StaticAssertTypeEqHelper(); + return true; +} + +// Defines a test. +// +// The first parameter is the name of the test case, and the second +// parameter is the name of the test within the test case. +// +// The convention is to end the test case name with "Test". For +// example, a test case for the Foo class can be named FooTest. +// +// The user should put his test code between braces after using this +// macro. Example: +// +// TEST(FooTest, InitializesCorrectly) { +// Foo foo; +// EXPECT_TRUE(foo.StatusIsOK()); +// } + +// Note that we call GetTestTypeId() instead of GetTypeId< +// ::testing::Test>() here to get the type ID of testing::Test. This +// is to work around a suspected linker bug when using Google Test as +// a framework on Mac OS X. The bug causes GetTypeId< +// ::testing::Test>() to return different values depending on whether +// the call is from the Google Test framework itself or from user test +// code. GetTestTypeId() is guaranteed to always return the same +// value, as it always calls GetTypeId<>() from the Google Test +// framework. +#define GTEST_TEST(test_case_name, test_name)\ + GTEST_TEST_(test_case_name, test_name, \ + ::testing::Test, ::testing::internal::GetTestTypeId()) + +// Define this macro to 1 to omit the definition of TEST(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_TEST +# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) +#endif + +// Defines a test that uses a test fixture. +// +// The first parameter is the name of the test fixture class, which +// also doubles as the test case name. The second parameter is the +// name of the test within the test case. +// +// A test fixture class must be declared earlier. The user should put +// his test code between braces after using this macro. Example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { b_.AddElement(3); } +// +// Foo a_; +// Foo b_; +// }; +// +// TEST_F(FooTest, InitializesCorrectly) { +// EXPECT_TRUE(a_.StatusIsOK()); +// } +// +// TEST_F(FooTest, ReturnsElementCountCorrectly) { +// EXPECT_EQ(0, a_.size()); +// EXPECT_EQ(1, b_.size()); +// } + +#define TEST_F(test_fixture, test_name)\ + GTEST_TEST_(test_fixture, test_name, test_fixture, \ + ::testing::internal::GetTypeId()) + +// Use this macro in main() to run all tests. It returns 0 if all +// tests are successful, or 1 otherwise. +// +// RUN_ALL_TESTS() should be invoked after the command line has been +// parsed by InitGoogleTest(). + +#define RUN_ALL_TESTS()\ + (::testing::UnitTest::GetInstance()->Run()) + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/Makefile b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/Makefile new file mode 100644 index 00000000..5c154e20 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/Makefile @@ -0,0 +1,81 @@ + +BUILD_DIR = ../build + +FFF_TEST_CPP_OBJS += \ +$(BUILD_DIR)/fff_test_cpp.o \ +$(BUILD_DIR)/gtest-all.o \ +$(BUILD_DIR)/gtest-main.o + +FFF_TEST_GLOBAL_CPP_OBJS += \ +$(BUILD_DIR)/fff_test_global_cpp.o \ +$(BUILD_DIR)/global_fakes.o \ +$(BUILD_DIR)/gtest-all.o \ +$(BUILD_DIR)/gtest-main.o + +FFF_TEST_C_OBJS = $(BUILD_DIR)/fff_test_c.o + +FFF_TEST_GLOBAL_C_OBJS += \ +$(BUILD_DIR)/global_fakes.o \ +$(BUILD_DIR)/fff_test_global_c.o + +FFF_TEST_CPP_TARGET = $(BUILD_DIR)/fff_test_cpp +FFF_TEST_C_TARGET = $(BUILD_DIR)/fff_test_c +FFF_TEST_GLOBAL_C_TARGET = $(BUILD_DIR)/fff_test_glob_c +FFF_TEST_GLOBAL_CPP_TARGET = $(BUILD_DIR)/fff_test_glob_cpp + +LIBS := -lpthread +# All Target +all: $(FFF_TEST_CPP_TARGET) $(FFF_TEST_C_TARGET) $(FFF_TEST_GLOBAL_C_TARGET) $(FFF_TEST_GLOBAL_CPP_TARGET) + + +# Each subdirectory must supply rules for building sources it contributes +$(BUILD_DIR)/%.o: %.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + g++ -I../ -O0 -g3 -Wall -DGTEST_USE_OWN_TR1_TUPLE=1 -c -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + +$(BUILD_DIR)/%.o: %.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + gcc -I../ -O0 -g3 -Wall -std=c99 -c -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + +# Link targets +$(FFF_TEST_CPP_TARGET): $(FFF_TEST_CPP_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C++ Linker' + g++ -o "$(FFF_TEST_CPP_TARGET)" $(FFF_TEST_CPP_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +$(FFF_TEST_C_TARGET): $(FFF_TEST_C_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C Linker' + gcc -o "$(FFF_TEST_C_TARGET)" $(FFF_TEST_C_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +$(FFF_TEST_GLOBAL_C_TARGET): $(FFF_TEST_GLOBAL_C_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C++ Linker' + g++ -o "$(FFF_TEST_GLOBAL_C_TARGET)" $(FFF_TEST_GLOBAL_C_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +$(FFF_TEST_GLOBAL_CPP_TARGET): $(FFF_TEST_GLOBAL_CPP_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C++ Linker' + g++ -o "$(FFF_TEST_GLOBAL_CPP_TARGET)" $(FFF_TEST_GLOBAL_CPP_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(FFF_TEST_CPP_OBJS) $(FFF_TEST_GLOBAL_C_OBJS) $(FFF_TEST_C_OBJS) \ + $(FFF_TEST_CPP_TARGET) $(FFF_TEST_C_TARGET) $(FFF_TEST_GLOBAL_CPP_TARGET) $(FFF_TEST_GLOBAL_C_TARGET) + -@echo ' ' + diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/c_test_framework.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/c_test_framework.h new file mode 100644 index 00000000..ce7ad89d --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/c_test_framework.h @@ -0,0 +1,15 @@ +#ifndef C_TEST_FRAMEWORK_H_ +#define C_TEST_FRAMEWORK_H_ + +#include +#include +#include + +/* Test Framework :-) */ +void setup(); +#define TEST_F(SUITE, NAME) void NAME() +#define RUN_TEST(SUITE, TESTNAME) printf(" Running %s.%s: \n", #SUITE, #TESTNAME); setup(); TESTNAME(); printf(" SUCCESS\n"); +#define ASSERT_EQ(A, B) assert((A) == (B)) +#define ASSERT_TRUE(A) assert((A)) + +#endif /* C_TEST_FRAMEWORK_H_ */ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_c.c b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_c.c new file mode 100644 index 00000000..a4de6edc --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_c.c @@ -0,0 +1,108 @@ + +// Want to keep the argument history for 13 calls +#define OVERRIDE_ARG_HIST_LEN 13u +#define FFF_ARG_HISTORY_LEN OVERRIDE_ARG_HIST_LEN +// Want to keep the call sequence history for 17 function calls +#define OVERRIDE_CALL_HIST_LEN 17u +#define FFF_CALL_HISTORY_LEN OVERRIDE_CALL_HIST_LEN + +#include "../fff.h" +#include "c_test_framework.h" + +#include +#include +#include + + + +enum MYBOOL { FALSE = 899, TRUE }; +struct MyStruct { + int x; + int y; +}; + + +FAKE_VOID_FUNC(voidfunc1, int); +FAKE_VOID_FUNC(voidfunc2, char, char); +FAKE_VALUE_FUNC(long, longfunc0); +FAKE_VALUE_FUNC(enum MYBOOL, enumfunc0); +FAKE_VALUE_FUNC(struct MyStruct, structfunc0); +FAKE_VOID_FUNC3_VARARG(voidfunc3var, char *, int, ...); +FAKE_VALUE_FUNC(int, strlcpy3, char* const, const char* const, const size_t); +FAKE_VOID_FUNC(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); + +void setup() +{ + RESET_FAKE(voidfunc1); + RESET_FAKE(voidfunc2); + RESET_FAKE(longfunc0); + RESET_FAKE(enumfunc0); + RESET_FAKE(structfunc0); + RESET_FAKE(voidfunc3var); + RESET_FAKE(strlcpy3); + FFF_RESET_HISTORY(); +} + + +#include "test_cases.include" + +TEST_F(FFFTestSuite, default_constants_can_be_overridden) +{ + unsigned sizeCallHistory = (sizeof fff.call_history) / (sizeof fff.call_history[0]); + ASSERT_EQ(OVERRIDE_CALL_HIST_LEN, sizeCallHistory); + ASSERT_EQ(OVERRIDE_ARG_HIST_LEN, voidfunc2_fake.arg_history_len); +} + +DEFINE_FFF_GLOBALS; +int main() +{ + setbuf(stdout, NULL); + fprintf(stdout, "-------------\n"); + fprintf(stdout, "Running Tests\n"); + fprintf(stdout, "-------------\n\n"); + fflush(0); + + /* Run tests */ + RUN_TEST(FFFTestSuite, when_void_func_never_called_then_callcount_is_zero); + RUN_TEST(FFFTestSuite, when_void_func_called_once_then_callcount_is_one); + RUN_TEST(FFFTestSuite, when_void_func_called_once_and_reset_then_callcount_is_zero); + RUN_TEST(FFFTestSuite, when_void_func_with_1_integer_arg_called_then_last_arg_captured); + RUN_TEST(FFFTestSuite, when_void_func_with_1_integer_arg_called_twice_then_last_arg_captured); + RUN_TEST(FFFTestSuite, when_void_func_with_1_integer_arg_called_and_reset_then_captured_arg_is_zero); + RUN_TEST(FFFTestSuite, when_void_func_with_2_char_args_called_then_last_args_captured); + RUN_TEST(FFFTestSuite, when_void_func_with_2_char_args_called_twice_then_last_args_captured); + RUN_TEST(FFFTestSuite, when_void_func_with_2_char_args_called_and_reset_then_captured_arg_is_zero); + RUN_TEST(FFFTestSuite, when_fake_func_called_then_const_arguments_captured); + + RUN_TEST(FFFTestSuite, when_fake_func_created_default_history_is_fifty_calls); + RUN_TEST(FFFTestSuite, when_fake_func_called_then_arguments_captured_in_history); + RUN_TEST(FFFTestSuite, argument_history_is_reset_when_RESET_FAKE_called); + RUN_TEST(FFFTestSuite, when_fake_func_called_max_times_then_no_argument_histories_dropped); + RUN_TEST(FFFTestSuite, when_fake_func_called_max_times_plus_one_then_one_argument_history_dropped); + + RUN_TEST(FFFTestSuite, value_func_will_return_zero_by_default); + RUN_TEST(FFFTestSuite, value_func_will_return_value_given); + RUN_TEST(FFFTestSuite, value_func_will_return_zero_after_reset); + RUN_TEST(FFFTestSuite, register_call_macro_registers_one_call); + RUN_TEST(FFFTestSuite, register_call_macro_registers_two_calls); + RUN_TEST(FFFTestSuite, reset_call_history_resets_call_history); + RUN_TEST(FFFTestSuite, call_history_will_not_write_past_array_bounds); + RUN_TEST(FFFTestSuite, calling_fake_registers_one_call); + + RUN_TEST(FFFTestSuite, return_value_sequences_not_exhausted); + RUN_TEST(FFFTestSuite, return_value_sequences_exhausted); + RUN_TEST(FFFTestSuite, default_constants_can_be_overridden); + + RUN_TEST(FFFTestSuite, can_register_custom_fake); + RUN_TEST(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_return_value); + + RUN_TEST(FFFTestSuite, use_vararg_fake_with_different_number_of_arguments); + + RUN_TEST(FFFTestSuite, can_capture_upto_20_arguments_correctly); + + printf("\n-------------\n"); + printf("Complete\n"); + printf("-------------\n\n"); + + return 0; +} diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_cpp.cpp b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_cpp.cpp new file mode 100644 index 00000000..dcd28892 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_cpp.cpp @@ -0,0 +1,45 @@ +/* + * fff_test.cpp + * + * Created on: Dec 20, 2010 + * Author: mlong + */ + +// Want to keep the argument history for 13 calls +#define OVERRIDE_ARG_HIST_LEN 13u +#define FFF_ARG_HISTORY_LEN OVERRIDE_ARG_HIST_LEN +// Want to keep the call sequence history for 17 function calls +#define OVERRIDE_CALL_HIST_LEN 17u +#define FFF_CALL_HISTORY_LEN OVERRIDE_CALL_HIST_LEN + +#include "../fff.h" +#include + +DEFINE_FFF_GLOBALS + +FAKE_VOID_FUNC(voidfunc1, int); +FAKE_VOID_FUNC(voidfunc2, char, char); +FAKE_VALUE_FUNC(long, longfunc0); +FAKE_VOID_FUNC(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); + +class FFFTestSuite: public testing::Test +{ +public: + void SetUp() + { + RESET_FAKE(voidfunc1); + RESET_FAKE(voidfunc2); + RESET_FAKE(longfunc0); + FFF_RESET_HISTORY(); + } +}; + +#include "test_cases.include" + +TEST_F(FFFTestSuite, default_constants_can_be_overridden) +{ + unsigned sizeCallHistory = (sizeof fff.call_history) / (sizeof fff.call_history[0]); + ASSERT_EQ(OVERRIDE_CALL_HIST_LEN, sizeCallHistory); + ASSERT_EQ(OVERRIDE_ARG_HIST_LEN, voidfunc2_fake.arg_history_len); +} + diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_global_c.c b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_global_c.c new file mode 100644 index 00000000..01112baa --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_global_c.c @@ -0,0 +1,76 @@ + +#include "global_fakes.h" +#include "c_test_framework.h" + + + +DEFINE_FFF_GLOBALS; + +void setup() +{ + RESET_FAKE(voidfunc1); + RESET_FAKE(voidfunc2); + RESET_FAKE(longfunc0); + RESET_FAKE(enumfunc0); + RESET_FAKE(structfunc0); + RESET_FAKE(voidfunc3var); + RESET_FAKE(strlcpy3); + + FFF_RESET_HISTORY(); +} + + +#include "test_cases.include" + + +int main() +{ + setbuf(stdout, NULL); + fprintf(stdout, "-------------\n"); + fprintf(stdout, "Running Tests\n"); + fprintf(stdout, "-------------\n\n"); + fflush(0); + + /* Run tests */ + RUN_TEST(FFFTestSuite, when_void_func_never_called_then_callcount_is_zero); + RUN_TEST(FFFTestSuite, when_void_func_called_once_then_callcount_is_one); + RUN_TEST(FFFTestSuite, when_void_func_called_once_and_reset_then_callcount_is_zero); + RUN_TEST(FFFTestSuite, when_void_func_with_1_integer_arg_called_then_last_arg_captured); + RUN_TEST(FFFTestSuite, when_void_func_with_1_integer_arg_called_twice_then_last_arg_captured); + RUN_TEST(FFFTestSuite, when_void_func_with_1_integer_arg_called_and_reset_then_captured_arg_is_zero); + RUN_TEST(FFFTestSuite, when_void_func_with_2_char_args_called_then_last_args_captured); + RUN_TEST(FFFTestSuite, when_void_func_with_2_char_args_called_twice_then_last_args_captured); + RUN_TEST(FFFTestSuite, when_void_func_with_2_char_args_called_and_reset_then_captured_arg_is_zero); + RUN_TEST(FFFTestSuite, when_fake_func_called_then_const_arguments_captured); + + RUN_TEST(FFFTestSuite, when_fake_func_created_default_history_is_fifty_calls); + RUN_TEST(FFFTestSuite, when_fake_func_called_then_arguments_captured_in_history); + RUN_TEST(FFFTestSuite, argument_history_is_reset_when_RESET_FAKE_called); + RUN_TEST(FFFTestSuite, when_fake_func_called_max_times_then_no_argument_histories_dropped); + RUN_TEST(FFFTestSuite, when_fake_func_called_max_times_plus_one_then_one_argument_history_dropped); + + RUN_TEST(FFFTestSuite, value_func_will_return_zero_by_default); + RUN_TEST(FFFTestSuite, value_func_will_return_value_given); + RUN_TEST(FFFTestSuite, value_func_will_return_zero_after_reset); + RUN_TEST(FFFTestSuite, register_call_macro_registers_one_call); + RUN_TEST(FFFTestSuite, register_call_macro_registers_two_calls); + RUN_TEST(FFFTestSuite, reset_call_history_resets_call_history); + RUN_TEST(FFFTestSuite, call_history_will_not_write_past_array_bounds); + RUN_TEST(FFFTestSuite, calling_fake_registers_one_call); + + RUN_TEST(FFFTestSuite, return_value_sequences_not_exhausted); + RUN_TEST(FFFTestSuite, return_value_sequences_exhausted); + + RUN_TEST(FFFTestSuite, can_register_custom_fake); + RUN_TEST(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_return_value); + + RUN_TEST(FFFTestSuite, use_vararg_fake_with_different_number_of_arguments); + + RUN_TEST(FFFTestSuite, can_capture_upto_20_arguments_correctly); + + printf("\n-------------\n"); + printf("Complete\n"); + printf("-------------\n\n"); + + return 0; +} diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_global_cpp.cpp b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_global_cpp.cpp new file mode 100644 index 00000000..dfe1e88d --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/fff_test_global_cpp.cpp @@ -0,0 +1,23 @@ + +extern "C"{ + #include "global_fakes.h" +} +#include + +DEFINE_FFF_GLOBALS; + +class FFFTestSuite: public testing::Test +{ +public: + void SetUp() + { + RESET_FAKE(voidfunc1); + RESET_FAKE(voidfunc2); + RESET_FAKE(longfunc0); + FFF_RESET_HISTORY(); + } +}; + +#include "test_cases.include" + + diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/global_fakes.c b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/global_fakes.c new file mode 100644 index 00000000..a727096d --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/global_fakes.c @@ -0,0 +1,13 @@ +#include "global_fakes.h" +#include // for memcpy + +DEFINE_FAKE_VOID_FUNC1(voidfunc1, int); +DEFINE_FAKE_VOID_FUNC2(voidfunc2, char, char); +DEFINE_FAKE_VALUE_FUNC0(long, longfunc0); +DEFINE_FAKE_VALUE_FUNC0(enum MYBOOL, enumfunc0); +DEFINE_FAKE_VALUE_FUNC0(struct MyStruct, structfunc0); +DEFINE_FAKE_VOID_FUNC3_VARARG(voidfunc3var, const char *, int, ...); +#ifndef __cplusplus +DEFINE_FAKE_VALUE_FUNC3(int, strlcpy3, char* const, const char* const, const size_t); +#endif /* __cplusplus */ +DEFINE_FAKE_VOID_FUNC20(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/global_fakes.h b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/global_fakes.h new file mode 100644 index 00000000..d4cf017c --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/global_fakes.h @@ -0,0 +1,37 @@ + +#ifndef GLOBAL_FAKES_H_ +#define GLOBAL_FAKES_H_ + +#include "../fff.h" +#include "string.h" + + +//// Imaginary production code header file /// +void voidfunc1(int); +void voidfunc2(char, char); +long longfunc0(); +void voidfunc3var(const char *fmt, int argc, ...); +void voidfunc20(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); + +enum MYBOOL { FALSE = 899, TRUE }; +struct MyStruct { + int x; + int y; +}; +enum MYBOOL enumfunc(); +struct MyStruct structfunc(); +//// End Imaginary production code header file /// + +DECLARE_FAKE_VOID_FUNC1(voidfunc1, int); +DECLARE_FAKE_VOID_FUNC2(voidfunc2, char, char); +DECLARE_FAKE_VALUE_FUNC0(long, longfunc0); +DECLARE_FAKE_VALUE_FUNC0(enum MYBOOL, enumfunc0); +DECLARE_FAKE_VALUE_FUNC0(struct MyStruct, structfunc0); +DECLARE_FAKE_VOID_FUNC3_VARARG(voidfunc3var, const char *, int, ...); +DECLARE_FAKE_VOID_FUNC20(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); + +#ifndef __cplusplus +int strlcpy3(char* const, const char* const, const size_t); +DECLARE_FAKE_VALUE_FUNC3(int, strlcpy3, char* const, const char* const, const size_t); +#endif /* __cplusplus */ +#endif /* GLOBAL_FAKES_H_ */ diff --git a/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/test_cases.include b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/test_cases.include new file mode 100644 index 00000000..b5ba7931 --- /dev/null +++ b/tools/vendor/ceedling/plugins/fake_function_framework/vendor/fff/test/test_cases.include @@ -0,0 +1,276 @@ + + +TEST_F(FFFTestSuite, when_void_func_never_called_then_callcount_is_zero) +{ + ASSERT_EQ(voidfunc1_fake.call_count, 0u); +} + +TEST_F(FFFTestSuite, when_void_func_called_once_then_callcount_is_one) +{ + voidfunc1(66); + ASSERT_EQ(voidfunc1_fake.call_count, 1u); +} + +TEST_F(FFFTestSuite, when_void_func_called_once_and_reset_then_callcount_is_zero) +{ + voidfunc1(66); + RESET_FAKE(voidfunc1); + ASSERT_EQ(voidfunc1_fake.call_count, 0u); +} + +// Single Argument +TEST_F(FFFTestSuite, when_void_func_with_1_integer_arg_called_then_last_arg_captured) +{ + voidfunc1(77); + ASSERT_EQ(voidfunc1_fake.arg0_val, 77); +} + +TEST_F(FFFTestSuite, when_void_func_with_1_integer_arg_called_twice_then_last_arg_captured) +{ + voidfunc1(77); + voidfunc1(12); + ASSERT_EQ(voidfunc1_fake.arg0_val, 12); +} + +TEST_F(FFFTestSuite, when_void_func_with_1_integer_arg_called_and_reset_then_captured_arg_is_zero) +{ + voidfunc1(11); + RESET_FAKE(voidfunc1); + ASSERT_EQ(voidfunc1_fake.arg0_val, 0); +} + +// Two Arguments +TEST_F(FFFTestSuite, when_void_func_with_2_char_args_called_then_last_args_captured) +{ + voidfunc2('a', 'b'); + ASSERT_EQ(voidfunc2_fake.arg0_val, 'a'); + ASSERT_EQ(voidfunc2_fake.arg1_val, 'b'); +} + +TEST_F(FFFTestSuite, when_void_func_with_2_char_args_called_twice_then_last_args_captured) +{ + voidfunc2('a', 'b'); + voidfunc2('c', 'd'); + ASSERT_EQ(voidfunc2_fake.arg0_val, 'c'); + ASSERT_EQ(voidfunc2_fake.arg1_val, 'd'); +} + +TEST_F(FFFTestSuite, when_void_func_with_2_char_args_called_and_reset_then_captured_arg_is_zero) +{ + voidfunc2('e', 'f'); + RESET_FAKE(voidfunc2); + ASSERT_EQ(voidfunc2_fake.arg0_val, 0); + ASSERT_EQ(voidfunc2_fake.arg1_val, 0); +} + +#ifndef __cplusplus +TEST_F(FFFTestSuite, when_fake_func_called_then_const_arguments_captured) +{ + char dst[80]; + strlcpy3(dst, __FUNCTION__, sizeof(__FUNCTION__)); +} +#endif /* __cplusplus */ + +// Argument history +TEST_F(FFFTestSuite, when_fake_func_created_default_history_is_fifty_calls) +{ + ASSERT_EQ(FFF_ARG_HISTORY_LEN, (sizeof voidfunc2_fake.arg0_history) / (sizeof voidfunc2_fake.arg0_history[0])); + ASSERT_EQ(FFF_ARG_HISTORY_LEN, (sizeof voidfunc2_fake.arg1_history) / (sizeof voidfunc2_fake.arg1_history[0])); +} + +TEST_F(FFFTestSuite, when_fake_func_called_then_arguments_captured_in_history) +{ + voidfunc2('g', 'h'); + ASSERT_EQ('g', voidfunc2_fake.arg0_history[0]); + ASSERT_EQ('h', voidfunc2_fake.arg1_history[0]); +} + +TEST_F(FFFTestSuite, argument_history_is_reset_when_RESET_FAKE_called) +{ + //given + voidfunc2('g', 'h'); + ASSERT_EQ('g', voidfunc2_fake.arg0_history[0]); + ASSERT_EQ('h', voidfunc2_fake.arg1_history[0]); + //when + RESET_FAKE(voidfunc2); + //then + ASSERT_EQ('\0', voidfunc2_fake.arg0_history[0]); + ASSERT_EQ('\0', voidfunc2_fake.arg1_history[0]); +} + +TEST_F(FFFTestSuite, when_fake_func_called_max_times_then_no_argument_histories_dropped) +{ + unsigned int i; + for (i = 0; i < FFF_ARG_HISTORY_LEN; i++) + { + voidfunc2('1' + i, '2' + i); + } + ASSERT_EQ(0u, voidfunc2_fake.arg_histories_dropped); +} + +TEST_F(FFFTestSuite, when_fake_func_called_max_times_plus_one_then_one_argument_history_dropped) +{ + unsigned int i; + for (i = 0; i < FFF_ARG_HISTORY_LEN; i++) + { + voidfunc2('1' + i, '2' + i); + } + voidfunc2('1', '2'); + ASSERT_EQ(1u, voidfunc2_fake.arg_histories_dropped); + // or in other words.. + ASSERT_TRUE(voidfunc2_fake.call_count > voidfunc2_fake.arg_history_len); +} + +// Return values +TEST_F(FFFTestSuite, value_func_will_return_zero_by_default) +{ + ASSERT_EQ(0l, longfunc0()); +} + +TEST_F(FFFTestSuite, value_func_will_return_value_given) +{ + longfunc0_fake.return_val = 99l; + ASSERT_EQ(99l, longfunc0()); +} + +TEST_F(FFFTestSuite, value_func_will_return_zero_after_reset) +{ + longfunc0_fake.return_val = 99l; + RESET_FAKE(longfunc0); + ASSERT_EQ(0l, longfunc0()); +} + +TEST_F(FFFTestSuite, register_call_macro_registers_one_call) +{ + REGISTER_CALL(longfunc0); + ASSERT_EQ(fff.call_history[0], (void *)longfunc0); +} + +TEST_F(FFFTestSuite, register_call_macro_registers_two_calls) +{ + REGISTER_CALL(longfunc0); + REGISTER_CALL(voidfunc2); + + ASSERT_EQ(fff.call_history[0], (void *)longfunc0); + ASSERT_EQ(fff.call_history[1], (void *)voidfunc2); +} + +TEST_F(FFFTestSuite, reset_call_history_resets_call_history) +{ + REGISTER_CALL(longfunc0); + FFF_RESET_HISTORY(); + REGISTER_CALL(voidfunc2); + + ASSERT_EQ(1u, fff.call_history_idx); + ASSERT_EQ(fff.call_history[0], (void *)voidfunc2); +} + +TEST_F(FFFTestSuite, call_history_will_not_write_past_array_bounds) +{ + for (unsigned int i = 0; i < FFF_CALL_HISTORY_LEN + 1; i++) + { + REGISTER_CALL(longfunc0); + } + ASSERT_EQ(FFF_CALL_HISTORY_LEN, fff.call_history_idx); +} + +TEST_F(FFFTestSuite, calling_fake_registers_one_call) +{ + longfunc0(); + ASSERT_EQ(fff.call_history_idx, 1u); + ASSERT_EQ(fff.call_history[0], (void *)longfunc0); +} + +TEST_F(FFFTestSuite, return_value_sequences_not_exhausted) +{ + long myReturnVals[3] = { 3, 7, 9 }; + SET_RETURN_SEQ(longfunc0, myReturnVals, 3); + ASSERT_EQ(myReturnVals[0], longfunc0()); + ASSERT_EQ(myReturnVals[1], longfunc0()); + ASSERT_EQ(myReturnVals[2], longfunc0()); +} + + +TEST_F(FFFTestSuite, return_value_sequences_exhausted) +{ + long myReturnVals[3] = { 3, 7, 9 }; + SET_RETURN_SEQ(longfunc0, myReturnVals, 3); + ASSERT_EQ(myReturnVals[0], longfunc0()); + ASSERT_EQ(myReturnVals[1], longfunc0()); + ASSERT_EQ(myReturnVals[2], longfunc0()); + ASSERT_EQ(myReturnVals[2], longfunc0()); + ASSERT_EQ(myReturnVals[2], longfunc0()); +} + +TEST_F(FFFTestSuite, return_value_sequences_reset) +{ + long myReturnVals[3] = { 3, 7, 9 }; + SET_RETURN_SEQ(longfunc0, myReturnVals, 3); + ASSERT_EQ(myReturnVals[0], longfunc0()); + ASSERT_EQ(myReturnVals[1], longfunc0()); + RESET_FAKE(longfunc0); + ASSERT_EQ(0, longfunc0()); +} + +static int my_custom_fake_called = 0; +void my_custom_fake(char a, char b) +{ + my_custom_fake_called++; +} + +TEST_F(FFFTestSuite, can_register_custom_fake) +{ + voidfunc2_fake.custom_fake = my_custom_fake; + voidfunc2('a', 'b'); + ASSERT_EQ(1, my_custom_fake_called); +} + +//DECLARE_FAKE_VALUE_FUNC0(long, longfunc0); +#define MEANING_OF_LIFE 42 +long my_custom_value_fake(void) +{ + return MEANING_OF_LIFE; +} +TEST_F(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_return_value) +{ + longfunc0_fake.custom_fake = my_custom_value_fake; + long retval = longfunc0(); + ASSERT_EQ(MEANING_OF_LIFE, retval); +} + +#ifndef __cplusplus +TEST_F(FFFTestSuite, use_vararg_fake_with_different_number_of_arguments) +{ + voidfunc3var("0 parameters", 0); + voidfunc3var("1 parameter", 1, 10); + voidfunc3var("2 parameters", 2, 10, 20); + voidfunc3var("3 parameters", 3, 10, 20, 30); +} +#endif /* __cplusplus */ + +TEST_F(FFFTestSuite, can_capture_upto_20_arguments_correctly) +{ + voidfunc20(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19); + ASSERT_EQ(0, voidfunc20_fake.arg0_val); + ASSERT_EQ(1, voidfunc20_fake.arg1_val); + ASSERT_EQ(2, voidfunc20_fake.arg2_val); + ASSERT_EQ(3, voidfunc20_fake.arg3_val); + ASSERT_EQ(4, voidfunc20_fake.arg4_val); + ASSERT_EQ(5, voidfunc20_fake.arg5_val); + ASSERT_EQ(6, voidfunc20_fake.arg6_val); + ASSERT_EQ(7, voidfunc20_fake.arg7_val); + ASSERT_EQ(8, voidfunc20_fake.arg8_val); + ASSERT_EQ(9, voidfunc20_fake.arg9_val); + ASSERT_EQ(10, voidfunc20_fake.arg10_val); + ASSERT_EQ(11, voidfunc20_fake.arg11_val); + ASSERT_EQ(12, voidfunc20_fake.arg12_val); + ASSERT_EQ(13, voidfunc20_fake.arg13_val); + ASSERT_EQ(14, voidfunc20_fake.arg14_val); + ASSERT_EQ(15, voidfunc20_fake.arg15_val); + ASSERT_EQ(16, voidfunc20_fake.arg16_val); + ASSERT_EQ(17, voidfunc20_fake.arg17_val); + ASSERT_EQ(18, voidfunc20_fake.arg18_val); + ASSERT_EQ(19, voidfunc20_fake.arg19_val); +} + + diff --git a/tools/vendor/ceedling/plugins/gcov/README.md b/tools/vendor/ceedling/plugins/gcov/README.md index b144e3b7..57d56651 100644 --- a/tools/vendor/ceedling/plugins/gcov/README.md +++ b/tools/vendor/ceedling/plugins/gcov/README.md @@ -4,15 +4,25 @@ ceedling-gcov # Plugin Overview Plugin for integrating GNU GCov code coverage tool into Ceedling projects. -Currently only designed for the gcov command (like LCOV for example). In the -future we could configure this to work with other code coverage tools. -This plugin currently uses [gcovr](https://www.gcovr.com/) and / or -[ReportGenerator](https://danielpalme.github.io/ReportGenerator/) -as utilities to generate HTML, XML, JSON, or Text reports. The normal gcov -plugin _must_ be run first for these reports to generate. +In its simplest usage, this plugin outputs coverage statistics to the +console for each source file exercised by a test after the standard +Ceedling test results summary. For more advanced visualization and +reporting, this plugin also supports a variety of report generation +options. -## Installation +Advanced report generation uses [gcovr](https://www.gcovr.com/) and / or +[ReportGenerator](https://reportgenerator.io) +as utilities to generate HTML, XML, JSON, or Text reports. + +In the default configuration, if reports are configured, this plugin +automatically generates reports after each execution of a `gcov:` task. +An optional setting documented below disables automatic report +generation, providing a separate Ceedling task instead. + +## Installation of Report Generation Tools + +[gcovr](https://www.gcovr.com/) is available on any platform supported by Python. gcovr can be installed via pip like so: @@ -20,16 +30,19 @@ gcovr can be installed via pip like so: pip install gcovr ``` -ReportGenerator can be installed via .NET Core like so: +[ReportGenerator](https://reportgenerator.io) is available on any platform supported by .Net. + +It can be installed via .NET Core like so: ```sh dotnet tool install -g dotnet-reportgenerator-globaltool ``` It is not required to install both `gcovr` and `ReportGenerator`. Either utility -may be installed to create reports. +may be installed, or both utilities may be used. If reports are configured but +no `utilities:` section exists, `gcovr` is the default tool. -## Configuration +## Plugin Configuration The gcov plugin supports configuration options via your `project.yml` provided by Ceedling. @@ -47,9 +60,54 @@ Gcovr and / or ReportGenerator may be enabled to create coverage reports. ### Reports +By default, if report generation is configured, this plugin automatically +generates reports after any `gcov:` task is executed. To disable this behavior, +add `:report_task: TRUE` to your `:gcov:` configuration. + +With this setting enabled, an additional Ceedling task `report:gcov` is created. +It may be executed after `gcov:` tasks to generate the configured reports. + +For small projects, the default behavior is likely preferred. Alternatively, this +setting allows large or complex projects to execute potentially time intensive +report generation only when desired. + +```yaml +:gcov: + :report_task: [TRUE|FALSE] +``` + +## Example Usage +_Note_: Basic coverage statistics are always printed to the console regardless of +report generation options. + +### With automatic coverage report generation (default) +If coverage report generation is configured, the plugin defaults to running +reports after any `gcov:` task. + +```sh +ceedling gcov:all +``` + +### With coverage report generation configured as an additional task +If the `:report_task:` configuration option is enabled, reports are not +automatically generaed after test suite coverage builds. Instead, report generation +is triggered by the `report:gcov` task. + +```sh +ceedling gcov:all report:gcov +``` + +```sh +ceedling gcov:all +ceedling report:gcov +``` + +## Report Generation Configuration + Various reports are available and may be enabled with the following -configuration item. See the specific report sections in this README -for additional options and information. All generated reports will be found in `build/artifacts/gcov`. +configuration items. See the specific report sections that follow +for additional options and information. All generated reports will be +found in `build/artifacts/gcov`. ```yaml :gcov: @@ -155,7 +213,6 @@ Generation of Gcovr HTML reports may be modified with the following configuratio # Deprecated - See the :reports: configuration option. :html_report_type: [basic|detailed] - :gcovr: # HTML report filename. :html_artifact_filename: @@ -195,7 +252,6 @@ Generation of Cobertura XML reports may be modified with the following configura # Deprecated - See the :reports: configuration option. :xml_report: [true|false] - :gcovr: # Set to 'true' to pretty-print the Cobertura XML report, otherwise set to 'false'. # Defaults to disabled. (gcovr --xml-pretty) @@ -345,18 +401,7 @@ default behaviors of gcovr: :delete: [true|false] # Set the number of threads to use in parallel. (gcovr -j). - :num_parallel_threads: - - # When scanning the code coverage, if any files are found that do not have - # associated coverage data, the command will abort with an error message. - :abort_on_uncovered: true - - # When using the ``abort_on_uncovered`` option, the files in this list will not - # trigger a failure. - # Ceedling globs described in the Ceedling packet ``Path`` section can be used - # when directories are placed on the list. Globs are limited to matching directories - # and not files. - :uncovered_ignore_list: [] + :threads: ``` ### ReportGenerator Configuration @@ -405,7 +450,7 @@ All generated reports may be found in `build/artifacts/gcov/ReportGenerator`. :gcov_executable: # Optionally set the number of threads to use in parallel. Defaults to 1. - :num_parallel_threads: + :threads: # Optional list of one or more command line arguments to pass to Report Generator. # Useful for configuring Risk Hotspots and Other Settings. @@ -415,12 +460,24 @@ All generated reports may be found in `build/artifacts/gcov/ReportGenerator`. - ``` -## Example Usage - -```sh -ceedling gcov:all utils:gcov +## Known issues +### Empty Gcovr report with Gcovr 4.2+ +- If you are facing an empty gcovr report with version 4.2+ try to specify the folder you want to get a coverage. +```bash +├── Includes +├── Sources +└── UnitTestFramework + └──project.yml ``` +```yaml +:gcov: + :gcovr: + # Keep only source files that match this filter. (gcovr --filter). + :report_include: "^../Sources.*" + ``` + + ## To-Do list - Generate overall report (combined statistics from all files with coverage) diff --git a/tools/vendor/ceedling/plugins/gcov/config/defaults_gcov.rb b/tools/vendor/ceedling/plugins/gcov/config/defaults_gcov.rb index e3ce340d..ed4e756e 100644 --- a/tools/vendor/ceedling/plugins/gcov/config/defaults_gcov.rb +++ b/tools/vendor/ceedling/plugins/gcov/config/defaults_gcov.rb @@ -1,118 +1,112 @@ DEFAULT_GCOV_COMPILER_TOOL = { - :executable => ENV['CC'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CC'].split[0], - :name => 'default_gcov_compiler'.freeze, - :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, - :optional => false.freeze, - :arguments => [ - "-g".freeze, - "-fprofile-arcs".freeze, - "-ftest-coverage".freeze, - ENV['CC'].nil? ? "" : ENV['CC'].split[1..-1], - ENV['CPPFLAGS'].nil? ? "" : ENV['CPPFLAGS'].split, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, - {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, - {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, - "-DGCOV_COMPILER".freeze, - "-DCODE_COVERAGE".freeze, - ENV['CFLAGS'].nil? ? "" : ENV['CFLAGS'].split, - "-c \"${1}\"".freeze, - "-o \"${2}\"".freeze - ].freeze - } - + :executable => ENV['CC'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CC'].split[0], + :name => 'default_gcov_compiler'.freeze, + :stderr_redirect => StdErrRedirect::NONE.freeze, + :optional => false.freeze, + :arguments => [ + "-g".freeze, + "-fprofile-arcs".freeze, + "-ftest-coverage".freeze, + ENV['CC'].nil? ? "" : ENV['CC'].split[1..-1], + ENV['CPPFLAGS'].nil? ? "" : ENV['CPPFLAGS'].split, + "-I\"${5}\"".freeze, # Per-test executable search paths + "-D\"${6}\"".freeze, # Per-test executable defines + "-DGCOV_COMPILER".freeze, + "-DCODE_COVERAGE".freeze, + ENV['CFLAGS'].nil? ? "" : ENV['CFLAGS'].split, + "-c \"${1}\"".freeze, + "-o \"${2}\"".freeze, + # gcc's list file output options are complex; no use of ${3} parameter in default config + "-MMD".freeze, + "-MF \"${4}\"".freeze, + ].freeze + } DEFAULT_GCOV_LINKER_TOOL = { - :executable => ENV['CCLD'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CCLD'].split[0], - :name => 'default_gcov_linker'.freeze, - :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, - :optional => false.freeze, - :arguments => [ - "-g".freeze, - "-fprofile-arcs".freeze, - "-ftest-coverage".freeze, - ENV['CCLD'].nil? ? "" : ENV['CCLD'].split[1..-1], - ENV['CFLAGS'].nil? ? "" : ENV['CFLAGS'].split, - ENV['LDFLAGS'].nil? ? "" : ENV['LDFLAGS'].split, - "\"${1}\"".freeze, - "-o \"${2}\"".freeze, - "${4}".freeze, - "${5}".freeze, - ENV['LDLIBS'].nil? ? "" : ENV['LDLIBS'].split - ].freeze - } + :executable => ENV['CCLD'].nil? ? FilePathUtils.os_executable_ext('gcc').freeze : ENV['CCLD'].split[0], + :name => 'default_gcov_linker'.freeze, + :stderr_redirect => StdErrRedirect::NONE.freeze, + :optional => false.freeze, + :arguments => [ + "-g".freeze, + "-fprofile-arcs".freeze, + "-ftest-coverage".freeze, + ENV['CCLD'].nil? ? "" : ENV['CCLD'].split[1..-1], + ENV['CFLAGS'].nil? ? "" : ENV['CFLAGS'].split, + ENV['LDFLAGS'].nil? ? "" : ENV['LDFLAGS'].split, + "${1}".freeze, + "${5}".freeze, + "-o \"${2}\"".freeze, + "${4}".freeze, + ENV['LDLIBS'].nil? ? "" : ENV['LDLIBS'].split + ].freeze + } DEFAULT_GCOV_FIXTURE_TOOL = { - :executable => '${1}'.freeze, - :name => 'default_gcov_fixture'.freeze, - :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, - :optional => false.freeze, - :arguments => [].freeze - } + :executable => '${1}'.freeze, + :name => 'default_gcov_fixture'.freeze, + :stderr_redirect => StdErrRedirect::AUTO.freeze, + :optional => false.freeze, + :arguments => [].freeze + } DEFAULT_GCOV_REPORT_TOOL = { - :executable => ENV['GCOV'].nil? ? FilePathUtils.os_executable_ext('gcov').freeze : ENV['GCOV'].split[0], - :name => 'default_gcov_report'.freeze, - :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, - :optional => false.freeze, - :arguments => [ - "-n".freeze, - "-p".freeze, - "-b".freeze, - {"-o \"$\"" => 'GCOV_BUILD_OUTPUT_PATH'}.freeze, - "\"${1}\"".freeze - ].freeze - } + :executable => ENV['GCOV'].nil? ? FilePathUtils.os_executable_ext('gcov').freeze : ENV['GCOV'].split[0], + :name => 'default_gcov_report'.freeze, + :stderr_redirect => StdErrRedirect::NONE.freeze, + :optional => false.freeze, + :arguments => [ + "-n".freeze, + "-p".freeze, + "-b".freeze, + "-o \"${2}\"".freeze, + "\"${1}\"".freeze + ].freeze + } DEFAULT_GCOV_GCOV_POST_REPORT_TOOL = { - :executable => ENV['GCOV'].nil? ? FilePathUtils.os_executable_ext('gcov').freeze : ENV['GCOV'].split[0], - :name => 'default_gcov_gcov_post_report'.freeze, - :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, - :optional => true.freeze, - :arguments => [ - "-b".freeze, - "-c".freeze, - "-r".freeze, - "-x".freeze, - "${1}".freeze - ].freeze - } + :executable => ENV['GCOV'].nil? ? FilePathUtils.os_executable_ext('gcov').freeze : ENV['GCOV'].split[0], + :name => 'default_gcov_gcov_post_report'.freeze, + :stderr_redirect => StdErrRedirect::NONE.freeze, + :optional => true.freeze, + :arguments => [ + "-b".freeze, + "-c".freeze, + "-r".freeze, + "-x".freeze, + "${1}".freeze + ].freeze + } DEFAULT_GCOV_GCOVR_POST_REPORT_TOOL = { - :executable => 'gcovr'.freeze, - :name => 'default_gcov_gcovr_post_report'.freeze, - :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, - :optional => true.freeze, - :arguments => [ - "${1}".freeze - ].freeze - } + :executable => 'gcovr'.freeze, + :name => 'default_gcov_gcovr_post_report'.freeze, + :stderr_redirect => StdErrRedirect::NONE.freeze, + :optional => true.freeze, + :arguments => [ + "${1}".freeze + ].freeze + } DEFAULT_GCOV_REPORTGENERATOR_POST_REPORT = { - :executable => 'reportgenerator'.freeze, - :name => 'default_gcov_reportgenerator_post_report'.freeze, - :stderr_redirect => StdErrRedirect::NONE.freeze, - :background_exec => BackgroundExec::NONE.freeze, - :optional => true.freeze, - :arguments => [ - "${1}".freeze - ].freeze - } + :executable => 'reportgenerator'.freeze, + :name => 'default_gcov_reportgenerator_post_report'.freeze, + :stderr_redirect => StdErrRedirect::NONE.freeze, + :optional => true.freeze, + :arguments => [ + "${1}".freeze + ].freeze + } def get_default_config - return :tools => { - :gcov_compiler => DEFAULT_GCOV_COMPILER_TOOL, - :gcov_linker => DEFAULT_GCOV_LINKER_TOOL, - :gcov_fixture => DEFAULT_GCOV_FIXTURE_TOOL, - :gcov_report => DEFAULT_GCOV_REPORT_TOOL, - :gcov_gcov_post_report => DEFAULT_GCOV_GCOV_POST_REPORT_TOOL, - :gcov_gcovr_post_report => DEFAULT_GCOV_GCOVR_POST_REPORT_TOOL, - :gcov_reportgenerator_post_report => DEFAULT_GCOV_REPORTGENERATOR_POST_REPORT - } + return :tools => { + :gcov_compiler => DEFAULT_GCOV_COMPILER_TOOL, + :gcov_linker => DEFAULT_GCOV_LINKER_TOOL, + :gcov_fixture => DEFAULT_GCOV_FIXTURE_TOOL, + :gcov_report => DEFAULT_GCOV_REPORT_TOOL, + :gcov_gcov_post_report => DEFAULT_GCOV_GCOV_POST_REPORT_TOOL, + :gcov_gcovr_post_report => DEFAULT_GCOV_GCOVR_POST_REPORT_TOOL, + :gcov_reportgenerator_post_report => DEFAULT_GCOV_REPORTGENERATOR_POST_REPORT + } end diff --git a/tools/vendor/ceedling/plugins/gcov/gcov.rake b/tools/vendor/ceedling/plugins/gcov/gcov.rake index 1467564a..3c85aac1 100644 --- a/tools/vendor/ceedling/plugins/gcov/gcov.rake +++ b/tools/vendor/ceedling/plugins/gcov/gcov.rake @@ -14,74 +14,28 @@ CLEAN.include(File.join(GCOV_DEPENDENCIES_PATH, '*')) CLOBBER.include(File.join(GCOV_BUILD_PATH, '**/*')) rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_OBJECT}$/ => [ - proc do |task_name| - @ceedling[:file_finder].find_compilation_input_file(task_name) - end - ]) do |object| - - if File.basename(object.source) =~ /^(#{PROJECT_TEST_FILE_PREFIX}|#{CMOCK_MOCK_PREFIX})|(#{VENDORS_FILES.map{|source| '\b' + source + '\b'}.join('|')})/ - @ceedling[:generator].generate_object_file( - TOOLS_GCOV_COMPILER, - OPERATION_COMPILE_SYM, - GCOV_SYM, - object.source, - object.name, - @ceedling[:file_path_utils].form_test_build_list_filepath(object.name) - ) - else - @ceedling[GCOV_SYM].generate_coverage_object_file(object.source, object.name) - end -end - -rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_EXECUTABLE}$/) do |bin_file| - lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments() - lib_paths = @ceedling[:test_invoker].get_library_paths_to_arguments() - @ceedling[:generator].generate_executable_file( - TOOLS_GCOV_LINKER, - GCOV_SYM, - bin_file.prerequisites, - bin_file.name, - @ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name), - lib_args, - lib_paths - ) -end - -rule(/#{GCOV_RESULTS_PATH}\/#{'.+\\' + EXTENSION_TESTPASS}$/ => [ - proc do |task_name| - @ceedling[:file_path_utils].form_test_executable_filepath(task_name) - end - ]) do |test_result| - @ceedling[:generator].generate_test_results(TOOLS_GCOV_FIXTURE, GCOV_SYM, test_result.source, test_result.name) -end + proc do |task_name| + _, object = (task_name.split('+')) + @ceedling[:file_finder].find_compilation_input_file(object) + end + ]) do |target| + test, object = (target.name.split('+')) -rule(/#{GCOV_DEPENDENCIES_PATH}\/#{'.+\\' + EXTENSION_DEPENDENCIES}$/ => [ - proc do |task_name| - @ceedling[:file_finder].find_compilation_input_file(task_name) - end - ]) do |dep| - @ceedling[:generator].generate_dependencies_file( - TOOLS_TEST_DEPENDENCIES_GENERATOR, - GCOV_SYM, - dep.source, - File.join(GCOV_BUILD_OUTPUT_PATH, File.basename(dep.source).ext(EXTENSION_OBJECT)), - dep.name - ) -end + @ceedling[GCOV_SYM].generate_coverage_object_file(test.to_sym, target.source, object) + end task directories: [GCOV_BUILD_OUTPUT_PATH, GCOV_RESULTS_PATH, GCOV_DEPENDENCIES_PATH, GCOV_ARTIFACTS_PATH] namespace GCOV_SYM do - task source_coverage: COLLECTION_ALL_SOURCE.pathmap("#{GCOV_BUILD_OUTPUT_PATH}/%n#{@ceedling[:configurator].extension_object}") desc 'Run code coverage for all tests' task all: [:test_deps] do @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) - @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, GCOV_SYM) + @ceedling[:test_invoker].setup_and_invoke(tests:COLLECTION_ALL_TESTS, context:GCOV_SYM, options:TOOL_COLLECTION_GCOV_TASKS) @ceedling[:configurator].restore_config end - desc 'Run single test w/ coverage ([*] real test or source file name, no path).' + desc 'Run single test w/ coverage ([*] test or source file name, no path).' task :* do message = "\nOops! '#{GCOV_ROOT_NAME}:*' isn't a real task. " \ "Use a real test or source file name (no path) in place of the wildcard.\n" \ @@ -100,7 +54,7 @@ namespace GCOV_SYM do if !matches.empty? @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) - @ceedling[:test_invoker].setup_and_invoke(matches, GCOV_SYM, force_run: false) + @ceedling[:test_invoker].setup_and_invoke(tests:matches, context:GCOV_SYM, options:{ force_run: false }.merge(TOOL_COLLECTION_GCOV_TASKS)) @ceedling[:configurator].restore_config else @ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.") @@ -117,20 +71,13 @@ namespace GCOV_SYM do if !matches.empty? @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) - @ceedling[:test_invoker].setup_and_invoke(matches, GCOV_SYM, force_run: false) + @ceedling[:test_invoker].setup_and_invoke(tests:matches, context:GCOV_SYM, options:{ force_run: false }.merge(TOOL_COLLECTION_GCOV_TASKS)) @ceedling[:configurator].restore_config else @ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.") end end - desc 'Run code coverage for changed files' - task delta: [:test_deps] do - @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) - @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, GCOV_SYM, force_run: false) - @ceedling[:configurator].restore_config - end - # use a rule to increase efficiency for large projects # gcov test tasks by regex rule(/^#{GCOV_TASK_ROOT}\S+$/ => [ @@ -142,68 +89,20 @@ namespace GCOV_SYM do ]) do |test| @ceedling[:rake_wrapper][:test_deps].invoke @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) - @ceedling[:test_invoker].setup_and_invoke([test.source], GCOV_SYM) + @ceedling[:test_invoker].setup_and_invoke(tests:[test.source], context:GCOV_SYM, options:TOOL_COLLECTION_GCOV_TASKS) @ceedling[:configurator].restore_config end end -if PROJECT_USE_DEEP_DEPENDENCIES - namespace REFRESH_SYM do - task GCOV_SYM do - @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) - @ceedling[:test_invoker].refresh_deep_dependencies - @ceedling[:configurator].restore_config - end - end -end - -namespace UTILS_SYM do - # Report Creation Utilities - UTILITY_NAME_GCOVR = "gcovr" - UTILITY_NAME_REPORT_GENERATOR = "ReportGenerator" - UTILITY_NAMES = [UTILITY_NAME_GCOVR, UTILITY_NAME_REPORT_GENERATOR] - - # Returns true is the given utility is enabled, otherwise returns false. - def is_utility_enabled(opts, utility_name) - return !(opts.nil?) && !(opts[:gcov_utilities].nil?) && (opts[:gcov_utilities].map(&:upcase).include? utility_name.upcase) - end - - - desc "Create gcov code coverage html/xml/json/text report(s). (Note: Must run 'ceedling gcov' first)." +# If gcov config enables separate report generation task, create the task +if @ceedling[GCOV_SYM].automatic_reporting_disabled? +namespace GCOV_REPORT_NAMESPACE_SYM do + desc "Generate reports from coverage results (Note: a #{GCOV_SYM}: task must be executed first)" task GCOV_SYM do - # Get the gcov options from project.yml. - opts = @ceedling[:configurator].project_config_hash - - # Create the artifacts output directory. - if !File.directory? GCOV_ARTIFACTS_PATH - FileUtils.mkdir_p GCOV_ARTIFACTS_PATH - end - - # Remove unsupported reporting utilities. - if !(opts[:gcov_utilities].nil?) - opts[:gcov_utilities].reject! { |item| !(UTILITY_NAMES.map(&:upcase).include? item.upcase) } - end - - # Default to gcovr when no reporting utilities are specified. - if opts[:gcov_utilities].nil? || opts[:gcov_utilities].empty? - opts[:gcov_utilities] = [UTILITY_NAME_GCOVR] - end - - if opts[:gcov_reports].nil? - opts[:gcov_reports] = [] - end - - gcovr_reportinator = GcovrReportinator.new(@ceedling) - gcovr_reportinator.support_deprecated_options(opts) - - if is_utility_enabled(opts, UTILITY_NAME_GCOVR) - gcovr_reportinator.make_reports(opts) - end - - if is_utility_enabled(opts, UTILITY_NAME_REPORT_GENERATOR) - reportgenerator_reportinator = ReportGeneratorReportinator.new(@ceedling) - reportgenerator_reportinator.make_reports(opts) - end - + @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) + @ceedling[:gcov].generate_coverage_reports() + @ceedling[:configurator].restore_config end end +end + diff --git a/tools/vendor/ceedling/plugins/gcov/lib/gcov.rb b/tools/vendor/ceedling/plugins/gcov/lib/gcov.rb index 30c6326b..8d2882f7 100644 --- a/tools/vendor/ceedling/plugins/gcov/lib/gcov.rb +++ b/tools/vendor/ceedling/plugins/gcov/lib/gcov.rb @@ -1,6 +1,8 @@ require 'ceedling/plugin' require 'ceedling/constants' require 'gcov_constants' +require 'gcovr_reportinator' +require 'reportgenerator_reportinator' class Gcov < Plugin attr_reader :config @@ -9,31 +11,38 @@ def setup @result_list = [] @config = { - project_test_build_output_path: GCOV_BUILD_OUTPUT_PATH, - project_test_build_output_c_path: GCOV_BUILD_OUTPUT_PATH, - project_test_results_path: GCOV_RESULTS_PATH, - project_test_dependencies_path: GCOV_DEPENDENCIES_PATH, - defines_test: DEFINES_TEST + ['CODE_COVERAGE'], gcov_html_report_filter: GCOV_FILTER_EXCLUDE } @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) @coverage_template_all = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb')) + + config = @ceedling[:configurator].project_config_hash + @reports_enabled = reports_enabled?( config[:gcov_reports] ) + + # This may raise an exception because of configuration or tool installation issues. + # Best to complain about it before allowing any tasks to run. + @reportinators = build_reportinators( config[:gcov_utilities], @reports_enabled ) end - def generate_coverage_object_file(source, object) - lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments() - compile_command = - @ceedling[:tool_executor].build_command_line( - TOOLS_GCOV_COMPILER, - @ceedling[:flaginator].flag_down(OPERATION_COMPILE_SYM, GCOV_SYM, source), - source, - object, - @ceedling[:file_path_utils].form_test_build_list_filepath(object), - lib_args + def generate_coverage_object_file(test, source, object) + tool = TOOLS_TEST_COMPILER + msg = nil + + # If a source file (not unity, mocks, etc.) is to be compiled use code coverage compiler + if @ceedling[:configurator].collection_all_source.to_a.include?(source) + tool = TOOLS_GCOV_COMPILER + msg = "Compiling #{File.basename(source)} with coverage..." + end + + @ceedling[:test_invoker].compile_test_component( + tool: tool, + context: GCOV_SYM, + test: test, + source: source, + object: object, + msg: msg ) - @ceedling[:streaminator].stdout_puts("Compiling #{File.basename(source)} with coverage...") - @ceedling[:tool_executor].exec(compile_command[:line], compile_command[:options]) end def post_test_fixture_execute(arg_hash) @@ -45,29 +54,34 @@ def post_test_fixture_execute(arg_hash) end def post_build + # Do nothing unless a gcov: task was used return unless @ceedling[:task_invoker].invoked?(/^#{GCOV_TASK_ROOT}/) - # test results + # Assemble test results results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list) hash = { header: GCOV_ROOT_NAME.upcase, results: results } + # Print unit test suite results @ceedling[:plugin_reportinator].run_test_results_report(hash) do message = '' message = 'Unit test failures.' if results[:counts][:failed] > 0 message end - report_per_file_coverage_results(@ceedling[:test_invoker].sources) + # Prinnt a short report of coverage results for each source file exercised by a test + report_per_file_coverage_results() + + # Run coverage report generation + generate_coverage_reports() if not automatic_reporting_disabled? end def summary result_list = @ceedling[:file_path_utils].form_pass_results_filelist(GCOV_RESULTS_PATH, COLLECTION_ALL_TESTS) - # test results - # get test results for only those tests in our configuration and of those only tests with results on disk + # Get test results for only those tests in our configuration and for those only tests with results on disk hash = { header: GCOV_ROOT_NAME.upcase, results: @ceedling[:plugin_reportinator].assemble_test_results(result_list, boom: false) @@ -76,57 +90,125 @@ def summary @ceedling[:plugin_reportinator].run_test_results_report(hash) end + def automatic_reporting_disabled? + config = @ceedling[:configurator].project_config_hash + + task = config[:gcov_report_task] + + return task if not task.nil? + + return false + end + + def generate_coverage_reports + return if (not @reports_enabled) or @reportinators.empty? + + # Create the artifacts output directory. + @ceedling[:file_wrapper].mkdir( GCOV_ARTIFACTS_PATH ) + + @reportinators.each do |reportinator| + reportinator.make_reports( @ceedling[:configurator].project_config_hash ) + end + end + private ################################### - def report_per_file_coverage_results(sources) - banner = @ceedling[:plugin_reportinator].generate_banner "#{GCOV_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY" + def report_per_file_coverage_results() + banner = @ceedling[:plugin_reportinator].generate_banner( "#{GCOV_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY" ) @ceedling[:streaminator].stdout_puts "\n" + banner - coverage_sources = @ceedling[:project_config_manager].filter_internal_sources(sources) - coverage_sources.each do |source| - basename = File.basename(source) - command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_REPORT, [], [basename]) - shell_results = @ceedling[:tool_executor].exec(command[:line], command[:options]) - coverage_results = shell_results[:output] + # Iterate over each test run and its list of source files + @ceedling[:test_invoker].each_test_with_sources do |test, sources| + heading = @ceedling[:plugin_reportinator].generate_heading( test ) + @ceedling[:streaminator].stdout_puts(heading) + + sources.each do |source| + filename = File.basename(source) + name = filename.ext('') + command = @ceedling[:tool_executor].build_command_line( + TOOLS_GCOV_REPORT, + [], # No additional arguments + filename, # .c source file that should have been compiled with coverage + File.join(GCOV_BUILD_OUTPUT_PATH, test) # /gcov/out/ for coverage data files + ) + + # Run the gcov tool and collect raw coverage report + shell_results = @ceedling[:tool_executor].exec(command[:line], command[:options]) + results = shell_results[:output].strip + + # Skip to next loop iteration if no coverage results. + # A source component may have been compiled with coverage but none of its code actually called in a test. + # In this case, gcov does not produce an error, only blank results. + if results.empty? + @ceedling[:streaminator].stdout_puts("#{filename} : No functions called or code paths exercised by test\n") + next + end - if coverage_results.strip =~ /(File\s+'#{Regexp.escape(source)}'.+$)/m - report = Regexp.last_match(1).lines.to_a[1..-1].map { |line| basename + ' ' + line }.join('') - @ceedling[:streaminator].stdout_puts(report + "\n\n") + # If results include intended source, extract details from console + if results =~ /(File\s+'#{Regexp.escape(source)}'.+$)/m + # Reformat from first line as filename banner to each line labeled with the filename + # Only extract the first four lines of the console report (to avoid spidering coverage reports through libs, etc.) + report = Regexp.last_match(1).lines.to_a[1..4].map { |line| filename + ' | ' + line }.join('') + @ceedling[:streaminator].stdout_puts(report + "\n") + + # Otherwise, no coverage results were found + else + msg = "ERROR: Could not find coverage results for #{source} component of #{test}" + @ceedling[:streaminator].stderr_puts( msg, Verbosity::NORMAL ) + end end end + end - ignore_path_list = @ceedling[:file_system_utils].collect_paths(@ceedling[:configurator].project_config_hash[:gcov_uncovered_ignore_list] || []) - ignore_uncovered_list = @ceedling[:file_wrapper].instantiate_file_list - ignore_path_list.each do |path| - if File.exists?(path) and not File.directory?(path) - ignore_uncovered_list.include(path) - else - ignore_uncovered_list.include(File.join(path, "*#{EXTENSION_SOURCE}")) - end + def reports_enabled?(cfg_reports) + return false if cfg_reports.nil? or cfg_reports.empty? + return true + end + + def build_reportinators(cfg_utils, enabled) + reportinators = [] + + return [] if not enabled + + # Remove unsupported reporting utilities. + if (not cfg_utils.nil?) + cfg_utils.reject! { |item| !(UTILITY_NAMES.map(&:upcase).include? item.upcase) } end - found_uncovered = false - COLLECTION_ALL_SOURCE.each do |source| - unless coverage_sources.include?(source) - v = Verbosity::DEBUG - msg = "Could not find coverage results for " + source - if ignore_uncovered_list.include?(source) - msg += " [IGNORED]" - else - found_uncovered = true - v = Verbosity::NORMAL - end - msg += "\n" - @ceedling[:streaminator].stdout_puts(msg, v) - end + # Default to gcovr when no reporting utilities are specified. + if cfg_utils.nil? || cfg_utils.empty? + cfg_utils = [UTILITY_NAME_GCOVR] end - if found_uncovered - if @ceedling[:configurator].project_config_hash[:gcov_abort_on_uncovered] - @ceedling[:streaminator].stderr_puts("There were files with no coverage results: aborting.\n") - exit(-1) - end + + # Run reports using gcovr + if utility_enabled?( cfg_utils, UTILITY_NAME_GCOVR ) + reportinator = GcovrReportinator.new( @ceedling ) + reportinators << reportinator end + + # Run reports using ReportGenerator + if utility_enabled?( cfg_utils, UTILITY_NAME_REPORT_GENERATOR ) + reportinator = ReportGeneratorReportinator.new( @ceedling ) + reportinators << reportinator + end + + return reportinators end + + # Returns true if the given utility is enabled, otherwise returns false. + def utility_enabled?(opts, utility_name) + enabled = !(opts.nil?) && (opts.map(&:upcase).include? utility_name.upcase) + + # Simple check for utility installation + # system() result is nil if could not run command + if enabled and system(utility_name, '--version', [:out, :err] => File::NULL).nil? + @ceedling[:streaminator].stderr_puts("ERROR: gcov report generation tool '#{utility_name}'' not installed.", Verbosity::NORMAL) + raise + end + + return enabled + end + end # end blocks always executed following rake run diff --git a/tools/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb b/tools/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb index 74c9bbda..740a87c6 100644 --- a/tools/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb +++ b/tools/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb @@ -3,6 +3,9 @@ GCOV_TASK_ROOT = GCOV_ROOT_NAME + ':' GCOV_SYM = GCOV_ROOT_NAME.to_sym +GCOV_REPORT_NAMESPACE = 'report'.freeze +GCOV_REPORT_NAMESPACE_SYM = GCOV_REPORT_NAMESPACE.to_sym + GCOV_BUILD_PATH = File.join(PROJECT_BUILD_ROOT, GCOV_ROOT_NAME) GCOV_BUILD_OUTPUT_PATH = File.join(GCOV_BUILD_PATH, "out") GCOV_RESULTS_PATH = File.join(GCOV_BUILD_PATH, "results") @@ -20,6 +23,18 @@ # gcovr supports regular expressions. GCOV_FILTER_EXCLUDE = GCOV_FILTER_EXCLUDE_PATHS.map{|path| '^'.concat(*path).concat('.*')}.join('|') +TOOL_COLLECTION_GCOV_TASKS = { + :test_compiler => TOOLS_GCOV_COMPILER, + :test_assembler => TOOLS_TEST_ASSEMBLER, + :test_linker => TOOLS_GCOV_LINKER, + :test_fixture => TOOLS_GCOV_FIXTURE +} + +# Report Creation Utilities +UTILITY_NAME_GCOVR = "gcovr" +UTILITY_NAME_REPORT_GENERATOR = "ReportGenerator" +UTILITY_NAMES = [UTILITY_NAME_GCOVR, UTILITY_NAME_REPORT_GENERATOR] + # ReportGenerator supports text with wildcard characters. GCOV_REPORT_GENERATOR_FILE_FILTERS = GCOV_FILTER_EXCLUDE_PATHS.map{|path| File.join('-.', *path, '*')}.join(';') diff --git a/tools/vendor/ceedling/plugins/gcov/lib/gcovr_reportinator.rb b/tools/vendor/ceedling/plugins/gcov/lib/gcovr_reportinator.rb index 5317c5d2..6e51621e 100644 --- a/tools/vendor/ceedling/plugins/gcov/lib/gcovr_reportinator.rb +++ b/tools/vendor/ceedling/plugins/gcov/lib/gcovr_reportinator.rb @@ -1,13 +1,14 @@ require 'reportinator_helper' +require 'ceedling/constants' class GcovrReportinator def initialize(system_objects) @ceedling = system_objects - @reportinator_helper = ReportinatorHelper.new + @reportinator_helper = ReportinatorHelper.new(system_objects) + support_deprecated_options( @ceedling[:configurator].project_config_hash ) end - # Generate the gcovr report(s) specified in the options. def make_reports(opts) # Get the gcovr version number. @@ -17,19 +18,40 @@ def make_reports(opts) args_common = args_builder_common(opts) if ((gcovr_version_info[0] == 4) && (gcovr_version_info[1] >= 2)) || (gcovr_version_info[0] > 4) + reports = [] + # gcovr version 4.2 and later supports generating multiple reports with a single call. args = args_common - args += args_builder_cobertura(opts, false) - args += args_builder_sonarqube(opts, false) - args += args_builder_json(opts, true) - # As of gcovr version 4.2, the --html argument must appear last. - args += args_builder_html(opts, false) - print "Creating gcov results report(s) in '#{GCOV_ARTIFACTS_PATH}'... " - STDOUT.flush + args += (_args = args_builder_cobertura(opts, false)) + reports << "Cobertura XML" if not _args.empty? + + args += (_args = args_builder_sonarqube(opts, false)) + reports << "SonarQube" if not _args.empty? + + args += (_args = args_builder_json(opts, true)) + reports << "JSON" if not _args.empty? + + # As of gcovr version 4.2, the --html argument must appear last. + args += (_args = args_builder_html(opts, false)) + reports << "HTML" if not _args.empty? + + msg = @ceedling[:reportinator].generate_progress("Creating #{reports.join(', ')} coverage report(s) with gcovr in '#{GCOV_ARTIFACTS_PATH}'") + @ceedling[:streaminator].stdout_puts("\n" + msg, Verbosity::NORMAL) # Generate the report(s). - run(args) + # only if one of the previous done checks for: + # + # - args_builder_cobertura + # - args_builder_sonarqube + # - args_builder_json + # - args_builder_html + # + # updated the args variable. In other case, no need to run GCOVR + # for current setup. + if !(args == args_common) + run(args) + end else # gcovr version 4.1 and earlier supports HTML and Cobertura XML reports. # It does not support SonarQube and JSON reports. @@ -38,16 +60,16 @@ def make_reports(opts) args_html = args_builder_html(opts, true) if args_html.length > 0 - print "Creating a gcov HTML report in '#{GCOV_ARTIFACTS_PATH}'... " - STDOUT.flush + msg = @ceedling[:reportinator].generate_progress("Creating an HTML coverage report with gcovr in '#{GCOV_ARTIFACTS_PATH}'") + @ceedling[:streaminator].stdout_puts(msg, Verbosity::NORMAL) # Generate the HTML report. run(args_common + args_html) end if args_cobertura.length > 0 - print "Creating a gcov XML report in '#{GCOV_ARTIFACTS_PATH}'... " - STDOUT.flush + msg = @ceedling[:reportinator].generate_progress("Creating an Cobertura XML coverage report with gcovr in '#{GCOV_ARTIFACTS_PATH}'") + @ceedling[:streaminator].stdout_puts(msg, Verbosity::NORMAL) # Generate the Cobertura XML report. run(args_common + args_cobertura) @@ -81,19 +103,22 @@ def support_deprecated_options(opts) if opts[:gcov_reports].empty? && opts[:gcov_html_report_type].nil? && opts[:gcov_xml_report].nil? opts[:gcov_reports] = [ReportTypes::HTML_BASIC] - puts "In your project.yml, define one or more of the" - puts "following to specify which reports to generate." - puts "For now, creating only an #{ReportTypes::HTML_BASIC} report." - puts "" - puts ":gcov:" - puts " :reports:" - puts " - #{ReportTypes::HTML_BASIC}" - puts " - #{ReportTypes::HTML_DETAILED}" - puts " - #{ReportTypes::TEXT}" - puts " - #{ReportTypes::COBERTURA}" - puts " - #{ReportTypes::SONARQUBE}" - puts " - #{ReportTypes::JSON}" - puts "" + msg = <<~TEXT_BLOCK + NOTE: In your project.yml, define one or more of the following to specify which reports to generate. + For now, creating only an #{ReportTypes::HTML_BASIC} report... + + :gcov: + :reports: + - #{ReportTypes::HTML_BASIC}" + - #{ReportTypes::HTML_DETAILED}" + - #{ReportTypes::TEXT}" + - #{ReportTypes::COBERTURA}" + - #{ReportTypes::SONARQUBE}" + - #{ReportTypes::JSON}" + + TEXT_BLOCK + + @ceedling[:streaminator].stdout_puts(msg, Verbosity::NORMAL) end end @@ -125,7 +150,7 @@ def args_builder_common(opts) args += "--gcov-ignore-parse-errors " if gcovr_opts[:gcov_ignore_parse_errors] args += "--keep " if gcovr_opts[:keep] args += "--delete " if gcovr_opts[:delete] - args += "-j #{gcovr_opts[:num_parallel_threads]} " if !(gcovr_opts[:num_parallel_threads].nil?) && (gcovr_opts[:num_parallel_threads].is_a? Integer) + args += "-j #{gcovr_opts[:threads]} " if !(gcovr_opts[:threads].nil?) && (gcovr_opts[:threads].is_a? Integer) [:fail_under_line, :fail_under_branch, :source_encoding, :object_directory].each do |opt| unless gcovr_opts[opt].nil? @@ -133,10 +158,10 @@ def args_builder_common(opts) value = gcovr_opts[opt] if (opt == :fail_under_line) || (opt == :fail_under_branch) if not value.is_a? Integer - puts "Option value #{opt} has to be an integer" + @ceedling[:streaminator].stdout_puts("ERROR: Option value #{opt} has to be an integer", Verbosity::NORMAL) value = nil elsif (value < 0) || (value > 100) - puts "Option value #{opt} has to be a percentage from 0 to 100" + @ceedling[:streaminator].stdout_puts("ERROR: Option value #{opt} has to be a percentage from 0 to 100", Verbosity::NORMAL) value = nil end end @@ -254,20 +279,18 @@ def args_builder_html(opts, use_output_option=false) def make_text_report(opts, args_common) gcovr_opts = get_opts(opts) args_text = "" - message_text = "Creating a gcov text report" + message_text = "Creating a text coverage report" - if !(gcovr_opts[:text_artifact_filename].nil?) - artifacts_file_txt = File.join(GCOV_ARTIFACTS_PATH, gcovr_opts[:text_artifact_filename]) - args_text += "--output \"#{artifacts_file_txt}\" " - message_text += " in '#{GCOV_ARTIFACTS_PATH}'... " - else - message_text += "... " - end + filename = gcovr_opts[:text_artifact_filename] || 'coverage.txt' + + artifacts_file_txt = File.join(GCOV_ARTIFACTS_PATH, filename) + args_text += "--output \"#{artifacts_file_txt}\" " + message_text += " in '#{GCOV_ARTIFACTS_PATH}'" - print message_text - STDOUT.flush + msg = @ceedling[:reportinator].generate_progress(message_text) + @ceedling[:streaminator].stdout_puts(msg, Verbosity::NORMAL) - # Generate the text report. + # Generate the text report run(args_common + args_text) end @@ -280,16 +303,14 @@ def get_opts(opts) # Run gcovr with the given arguments. def run(args) - begin - command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_GCOVR_POST_REPORT, [], args) - shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options]) - @reportinator_helper.print_shell_result(shell_result) - rescue - # handle any unforeseen issues with called tool - exitcode = $?.exitstatus - show_gcovr_message(exitcode) - exit(exitcode) - end + command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_GCOVR_POST_REPORT, [], args) + @ceedling[:streaminator].stdout_puts("Command: #{command}", Verbosity::DEBUG) + + command[:options][:boom] = false # Don't raise an exception if non-zero exit + shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options]) + + @reportinator_helper.print_shell_result(shell_result) + show_gcovr_message(shell_result[:exit_code]) end @@ -300,6 +321,8 @@ def get_gcovr_version() version_number_minor = 0 command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_GCOVR_POST_REPORT, [], "--version") + @ceedling[:streaminator].stdout_puts("Command: #{command}", Verbosity::DEBUG) + shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options]) version_number_match_data = shell_result[:output].match(/gcovr ([0-9]+)\.([0-9]+)/) @@ -315,10 +338,12 @@ def get_gcovr_version() # Show a more human-friendly message on gcovr return code def show_gcovr_message(exitcode) if ((exitcode & 2) == 2) - puts "The line coverage is less than the minimum" + @ceedling[:streaminator].stdout_puts("ERROR: Line coverage is less than the minimum", Verbosity::NORMAL) + raise end if ((exitcode & 4) == 4) - puts "The branch coverage is less than the minimum" + @ceedling[:streaminator].stdout_puts("ERROR: Branch coverage is less than the minimum", Verbosity::NORMAL) + raise end end diff --git a/tools/vendor/ceedling/plugins/gcov/lib/reportgenerator_reportinator.rb b/tools/vendor/ceedling/plugins/gcov/lib/reportgenerator_reportinator.rb index d4a885c9..a94088ed 100644 --- a/tools/vendor/ceedling/plugins/gcov/lib/reportgenerator_reportinator.rb +++ b/tools/vendor/ceedling/plugins/gcov/lib/reportgenerator_reportinator.rb @@ -1,11 +1,12 @@ require 'benchmark' require 'reportinator_helper' +require 'ceedling/constants' class ReportGeneratorReportinator def initialize(system_objects) @ceedling = system_objects - @reportinator_helper = ReportinatorHelper.new + @reportinator_helper = ReportinatorHelper.new(system_objects) end @@ -15,8 +16,8 @@ def make_reports(opts) total_time = Benchmark.realtime do rg_opts = get_opts(opts) - print "Creating gcov results report(s) with ReportGenerator in '#{GCOV_REPORT_GENERATOR_PATH}'... " - STDOUT.flush + msg = @ceedling[:reportinator].generate_progress("Creating #{opts[:gcov_reports].join(', ')} coverage report(s) with ReportGenerator in '#{GCOV_REPORT_GENERATOR_PATH}'") + @ceedling[:streaminator].stdout_puts("\n" + msg, Verbosity::NORMAL) # Cleanup any existing .gcov files to avoid reporting old coverage results. for gcov_file in Dir.glob("*.gcov") @@ -26,10 +27,7 @@ def make_reports(opts) # Use a custom gcov executable, if specified. GCOV_TOOL_CONFIG[:executable] = rg_opts[:gcov_executable] unless rg_opts[:gcov_executable].nil? - # Avoid running gcov on the mock, test, unity, and cexception gcov notes files to save time. - gcno_exclude_str = "#{opts[:cmock_mock_prefix]}.*" - gcno_exclude_str += "|#{opts[:project_test_file_prefix]}.*" - gcno_exclude_str += "|#{VENDORS_FILES.join('|')}" + gcno_exclude_str = "" # Avoid running gcov on custom specified .gcno files. if !(rg_opts.nil?) && !(rg_opts[:gcov_exclude].nil?) && !(rg_opts[:gcov_exclude].empty?) @@ -52,8 +50,7 @@ def make_reports(opts) # Generate .gcov files by running gcov on gcov notes files (*.gcno). for gcno_filepath in Dir.glob(File.join(GCOV_BUILD_PATH, "**", "*.gcno")) - match_data = gcno_filepath.match(gcno_exclude_regex) - if match_data.nil? || (match_data[1].nil? && match_data[1].nil?) + if not (gcno_filepath =~ gcno_exclude_regex) # Skip path that matches exclude pattern # Ensure there is a matching gcov data file. if File.file?(gcno_filepath.gsub(".gcno", ".gcda")) run_gcov("\"#{gcno_filepath}\"") @@ -68,7 +65,7 @@ def make_reports(opts) # Generate the report(s). shell_result = run(args) else - puts "\nWarning: No matching .gcno coverage files found." + @ceedling[:streaminator].stdout_puts("\nWARNING: No matching .gcno coverage files found.", Verbosity::NORMAL) end # Cleanup .gcov files. @@ -138,7 +135,7 @@ def args_builder(opts) # Removing trailing ';' after the last report type. args = args.chomp(";") - # Append a space seperator after the report type. + # Append a space separator after the report type. args += "\" " end @@ -182,6 +179,8 @@ def get_opts(opts) # Run ReportGenerator with the given arguments. def run(args) command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_REPORTGENERATOR_POST_REPORT, [], args) + @ceedling[:streaminator].stdout_puts("Command: #{command}", Verbosity::DEBUG) + return @ceedling[:tool_executor].exec(command[:line], command[:options]) end @@ -189,6 +188,8 @@ def run(args) # Run gcov with the given arguments. def run_gcov(args) command = @ceedling[:tool_executor].build_command_line(GCOV_TOOL_CONFIG, [], args) + @ceedling[:streaminator].stdout_puts("Command: #{command}", Verbosity::DEBUG) + return @ceedling[:tool_executor].exec(command[:line], command[:options]) end diff --git a/tools/vendor/ceedling/plugins/gcov/lib/reportinator_helper.rb b/tools/vendor/ceedling/plugins/gcov/lib/reportinator_helper.rb index 92617fba..d4568ff8 100644 --- a/tools/vendor/ceedling/plugins/gcov/lib/reportinator_helper.rb +++ b/tools/vendor/ceedling/plugins/gcov/lib/reportinator_helper.rb @@ -1,15 +1,22 @@ +require 'ceedling/constants' + class ReportinatorHelper - # Output the shell result to the console. - def print_shell_result(shell_result) - if !(shell_result.nil?) - puts "Done in %.3f seconds." % shell_result[:time] - - if !(shell_result[:output].nil?) && (shell_result[:output].length > 0) - puts shell_result[:output] - end + def initialize(system_objects) + @ceedling = system_objects + end + + # Output the shell result to the console. + def print_shell_result(shell_result) + if !(shell_result.nil?) + msg = "Done in %.3f seconds." % shell_result[:time] + @ceedling[:streaminator].stdout_puts(msg, Verbosity::NORMAL) + + if !(shell_result[:output].nil?) && (shell_result[:output].length > 0) + @ceedling[:streaminator].stdout_puts(shell_result[:output], Verbosity::OBNOXIOUS) end end + end end diff --git a/tools/vendor/ceedling/plugins/html_tests_report/README.md b/tools/vendor/ceedling/plugins/html_tests_report/README.md new file mode 100644 index 00000000..939c066d --- /dev/null +++ b/tools/vendor/ceedling/plugins/html_tests_report/README.md @@ -0,0 +1,38 @@ +html_tests_report +================ + +## Overview + +The html_tests_report plugin creates an HTML file of test results, +which makes the results easier to read. The HTML file is output to the appropriate +`/artifacts/` directory (e.g. `artifacts/test/` for test tasks, +`artifacts/gcov/` for gcov, or `artifacts/bullseye/` for bullseye runs). + +## Setup + +Enable the plugin in your project.yml by adding `html_tests_report` to the list +of enabled plugins. + +``` YAML +:plugins: + :enabled: + - html_tests_report +``` + +## Configuration + +Optionally configure the output / artifact filename in your project.yml with +the `artifact_filename` configuration option. The default filename is +`report.html`. + +You can also configure the path that this artifact is stored. This can be done +by setting `path`. The default is that it will be placed in a subfolder under +the `build` directory. + +If you use some means for continuous integration, you may also want to add +.xsl file to CI's configuration for proper parsing of .xml report. + +``` YAML +:html_tests_report: + :artifact_filename: report_test.html +``` diff --git a/tools/vendor/ceedling/plugins/html_tests_report/lib/html_tests_report.rb b/tools/vendor/ceedling/plugins/html_tests_report/lib/html_tests_report.rb new file mode 100644 index 00000000..31b5440d --- /dev/null +++ b/tools/vendor/ceedling/plugins/html_tests_report/lib/html_tests_report.rb @@ -0,0 +1,198 @@ +require 'ceedling/plugin' +require 'ceedling/constants' + +class HtmlTestsReport < Plugin + def setup + @results_list = {} + @test_counter = 0 + end + + def post_test_fixture_execute(arg_hash) + context = arg_hash[:context] + + @results_list[context] = [] if @results_list[context].nil? + + @results_list[context] << arg_hash[:result_file] + end + + def post_build + @results_list.each_key do |context| + results = @ceedling[:plugin_reportinator].assemble_test_results(@results_list[context]) + + artifact_filename = @ceedling[:configurator].project_config_hash[:html_tests_report_artifact_filename] || 'report.html' + artifact_fullpath = @ceedling[:configurator].project_config_hash[:html_tests_report_path] || File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s) + file_path = File.join(artifact_fullpath, artifact_filename) + + @ceedling[:file_wrapper].open(file_path, 'w') do |f| + @test_counter = 1 + write_results(results, f) + end + end + end + + private + + def write_results(results, stream) + write_header(stream) + write_statistics(results[:counts], stream) + write_failures(results[:failures], stream) + write_tests(results[:ignores], stream, "Ignored Tests", "ignored") + write_tests(results[:successes], stream, "Success Tests", "success") + write_footer(stream) + end + + def write_header(stream) + stream.puts "" + stream.puts '' + stream.puts '' + stream.puts '' + stream.puts '' + stream.puts '' + stream.puts 'Test Overview' + stream.puts '' + stream.puts '' + stream.puts '' + end + + def write_statistics(counts, stream) + stream.puts '

Summary

' + stream.puts '' + stream.puts '' + stream.puts '' + stream.puts "" + stream.puts "" + stream.puts "" + stream.puts "" + stream.puts "" + stream.puts "" + stream.puts "" + stream.puts "
TotalPassedIgnoredFailed
#{counts[:total]}#{counts[:total] - counts[:ignored] - counts[:failed]}#{counts[:ignored]}#{counts[:failed]}
" + end + + def write_failures(results, stream) + if results.size.zero? + return + end + + stream.puts '

Failed Test

' + stream.puts '' + stream.puts '' + stream.puts '' + + results.each do |result| + filename = result[:source][:path] + result[:source][:file] + @first_row = true + + result[:collection].each do |item| + + stream.puts "" + + if @first_row + stream.puts "" + @first_row = false + end + + stream.puts "" + if item[:message].empty? + stream.puts "" + else + if item[:message].size > 150 + stream.puts "" + else + stream.puts "" + end + end + stream.puts "" + end + end + + stream.puts "" + stream.puts "
FileLocationMessage
#{filename}#{item[:test]}::#{item[:line]}—
Message hidden due to long length.#{item[:message]}
#{item[:message]}
" + end + + def write_tests(results, stream, title, style) + if results.size.zero? + return + end + + stream.puts "

#{title}

" + stream.puts "" + stream.puts '' + stream.puts '' + + results.each do |result| + filename = result[:source][:path] + result[:source][:file] + @first_row = true + + result[:collection].each do |item| + stream.puts "" + + if @first_row + stream.puts "" + @first_row = false + end + + stream.puts "" + if item[:message].empty? + stream.puts "" + else + if item[:message].size > 150 + stream.puts "" + else + stream.puts "" + end + end + stream.puts "" + end + end + + stream.puts "" + stream.puts "
FileNameMessage
#{filename}#{item[:test]}—
Message hidden due to long length.#{item[:message]}
#{item[:message]}
" + end + + def write_footer(stream) + stream.puts '' + stream.puts '' + end +end diff --git a/tools/vendor/ceedling/plugins/json_tests_report/lib/json_tests_report.rb b/tools/vendor/ceedling/plugins/json_tests_report/lib/json_tests_report.rb index e7023db7..8b02e580 100644 --- a/tools/vendor/ceedling/plugins/json_tests_report/lib/json_tests_report.rb +++ b/tools/vendor/ceedling/plugins/json_tests_report/lib/json_tests_report.rb @@ -47,7 +47,7 @@ def write_failures(results) result[:collection].each do |item| @test_counter += 1 retval << { - "file" => File.join(result[:source][:path], result[:source][:file]), + "file" => result[:source][:file], "test" => item[:test], "line" => item[:line], "message" => item[:message] @@ -63,7 +63,7 @@ def write_tests(results) result[:collection].each do |item| @test_counter += 1 retval << { - "file" => File.join(result[:source][:path], result[:source][:file]), + "file" => result[:source][:file], "test" => item[:test] } end diff --git a/tools/vendor/ceedling/plugins/module_generator/README.md b/tools/vendor/ceedling/plugins/module_generator/README.md index a3c2c7ad..71de14cd 100644 --- a/tools/vendor/ceedling/plugins/module_generator/README.md +++ b/tools/vendor/ceedling/plugins/module_generator/README.md @@ -109,7 +109,7 @@ Finally, you can force a particular naming convention. Even if someone calls the with something like `MyNewModule`, if they have the naming convention set to `:caps`, it will generate files like `MY_NEW_MODULE.c`. This keeps everyone on your team behaving the same way. -Your options are as follows: +Your options for `:naming:` are as follows: - `:bumpy` - BumpyFilesLooksLikeSo - `:camel` - camelFilesAreSimilarButStartLow diff --git a/tools/vendor/ceedling/plugins/module_generator/lib/module_generator.rb b/tools/vendor/ceedling/plugins/module_generator/lib/module_generator.rb index d14288c3..9b9bfb12 100644 --- a/tools/vendor/ceedling/plugins/module_generator/lib/module_generator.rb +++ b/tools/vendor/ceedling/plugins/module_generator/lib/module_generator.rb @@ -54,15 +54,15 @@ def divine_options(optz={}) bf = MODULE_GENERATOR_BOILERPLATE_FILES - if !bf[:src].nil? && File.exists?(bf[:src]) + if !bf[:src].nil? && File.exist?(bf[:src]) unity_generator_options[:boilerplates][:src] = File.read(bf[:src]) end - if !bf[:inc].nil? && File.exists?(bf[:inc]) + if !bf[:inc].nil? && File.exist?(bf[:inc]) unity_generator_options[:boilerplates][:inc] = File.read(bf[:inc]) end - if !bf[:tst].nil? && File.exists?(bf[:tst]) + if !bf[:tst].nil? && File.exist?(bf[:tst]) unity_generator_options[:boilerplates][:tst] = File.read(bf[:tst]) end end diff --git a/tools/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb b/tools/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb index 018388fc..bf1aa39b 100644 --- a/tools/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb +++ b/tools/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb @@ -11,7 +11,7 @@ def setup end def post_test_fixture_execute(arg_hash) - return if not (arg_hash[:context] == TEST_SYM) + #TODO CLEANUP return if not (arg_hash[:context] == TEST_SYM) @result_list << arg_hash[:result_file] end diff --git a/tools/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb b/tools/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb index 33d8548f..4b9616b3 100644 --- a/tools/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb +++ b/tools/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb @@ -36,7 +36,7 @@ def post_test_fixture_execute(arg_hash) results[:failures].each do |failure| failure[:collection].each do |test| teamcity_message "testStarted name='#{test[:test]}'" - teamcity_message "testFailed name='#{test[:test]}' message='#{escape(test[:message])}' details='File: #{failure[:source][:path]}/#{failure[:source][:file]} Line: #{test[:line]}'" + teamcity_message "testFailed name='#{test[:test]}' message='#{escape(test[:message])}' details='File: #{failure[:source][:file]} Line: #{test[:line]}'" teamcity_message "testFinished name='#{test[:test]}' duration='#{avg_duration}'" end end diff --git a/tools/vendor/ceedling/plugins/xml_tests_report/README.md b/tools/vendor/ceedling/plugins/xml_tests_report/README.md index 6200c7de..529e33b9 100644 --- a/tools/vendor/ceedling/plugins/xml_tests_report/README.md +++ b/tools/vendor/ceedling/plugins/xml_tests_report/README.md @@ -30,6 +30,9 @@ You can also configure the path that this artifact is stored. This can be done by setting `path`. The default is that it will be placed in a subfolder under the `build` directory. +If you use some means for continuous integration, you may also want to add +.xsl file to CI's configuration for proper parsing of .xml report. + ``` YAML :xml_tests_report: :artifact_filename: report_xunit.xml diff --git a/tools/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb b/tools/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb index ed4e9960..ea5eaf64 100644 --- a/tools/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb +++ b/tools/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb @@ -21,6 +21,7 @@ def post_build artifact_filename = @ceedling[:configurator].project_config_hash[:xml_tests_report_artifact_filename] || 'report.xml' artifact_fullpath = @ceedling[:configurator].project_config_hash[:xml_tests_report_path] || File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s) + file_path = File.join(artifact_fullpath, artifact_filename) @ceedling[:file_wrapper].open(file_path, 'w') do |f| @@ -56,7 +57,7 @@ def write_failures(results, stream) results.each do |result| result[:collection].each do |item| - filename = File.join(result[:source][:path], result[:source][:file]) + filename = result[:source][:file] stream.puts "\t\t" stream.puts "\t\t\t#{filename}::#{item[:test]}" @@ -84,8 +85,9 @@ def write_tests(results, stream, tag) results.each do |result| result[:collection].each do |item| + filename = result[:source][:file] stream.puts "\t\t" - stream.puts "\t\t\t#{File.join(result[:source][:path], result[:source][:file])}::#{item[:test]}" + stream.puts "\t\t\t#{filename}::#{item[:test]}" stream.puts "\t\t" @test_counter += 1 end diff --git a/tools/vendor/ceedling/vendor/cmock/lib/cmock_config.rb b/tools/vendor/ceedling/vendor/cmock/lib/cmock_config.rb index 716a0c55..c7db9451 100644 --- a/tools/vendor/ceedling/vendor/cmock/lib/cmock_config.rb +++ b/tools/vendor/ceedling/vendor/cmock/lib/cmock_config.rb @@ -15,7 +15,7 @@ class CMockConfig :weak => '', :subdir => nil, :plugins => [], - :strippables => ['(?:__attribute__\s*\(+.*?\)+)'], + :strippables => ['(?:__attribute__\s*\([ (]*.*?[ )]*\)+)'], :attributes => %w[__ramfunc __irq __fiq register extern], :c_calling_conventions => %w[__stdcall __cdecl __fastcall], :enforce_strict_ordering => false, @@ -50,7 +50,7 @@ class CMockConfig # - The keywords can appear before or after the return type (this is a compiler warning but people do weird stuff), # so we check for word boundaries when searching for them # - We first remove "static inline" combinations and boil down to single inline or static statements - :inline_function_patterns => ['(static\s+inline|inline\s+static)\s*', '(\bstatic\b|\binline\b)\s*'] # Last part (\s*) is just to remove whitespaces (only to prettify the output) + :inline_function_patterns => ['(static\s+inline|inline\s+static)\s*', '(\bstatic\b|\binline\b)\s*', '(?:static\s*)?(?:__inline__)?__attribute__\s*\([ (]*always_inline[ )]*\)', 'static __inline__'] # Last part (\s*) is just to remove whitespaces (only to prettify the output) }.freeze def initialize(options = nil) diff --git a/tools/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb b/tools/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb index 6ed51109..c3896dfb 100644 --- a/tools/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb +++ b/tools/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb @@ -22,7 +22,7 @@ def initialize(config, file_writer, utils, plugins) @exclude_setjmp_h = @config.exclude_setjmp_h @subdir = @config.subdir - @includes_h_pre_orig_header = (@config.includes || @config.includes_h_pre_orig_header || []).map { |h| h =~ / [] } - create_source_header_section(file, fullname, blank_project) if existing.empty? + if existing.empty? + create_source_header_section(file, fullname, blank_project) + else + file << existing << "\n" + end mock_project[:parsed_stuff][:functions].each do |function| create_function_skeleton(file, function, existing) end @@ -169,6 +173,10 @@ def create_mock_header_header(file, _filename, mock_project) file << "#pragma GCC diagnostic ignored \"-Wduplicate-decl-specifier\"\n" file << "#endif\n" file << "\n" + file << "#ifdef __cplusplus\n" + file << "extern \"C\" {\n" + file << "#endif\n" + file << "\n" end def create_typedefs(file, mock_project) @@ -184,6 +192,10 @@ def create_mock_header_service_call_declarations(file, mock_project) end def create_mock_header_footer(header) + header << "\n" + header << "#ifdef __cplusplus\n" + header << "}\n" + header << "#endif\n" header << "\n" header << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n" header << "#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n" diff --git a/tools/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb b/tools/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb index 9730bf40..491e4671 100644 --- a/tools/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb +++ b/tools/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb @@ -14,7 +14,7 @@ def initialize(cfg) @c_calling_conventions = cfg.c_calling_conventions.uniq @treat_as_array = cfg.treat_as_array @treat_as_void = (['void'] + cfg.treat_as_void).uniq - @function_declaration_parse_base_match = '([\w\s\*\(\),\[\]]+??)\(([\w\s\*\(\),\.\[\]+\-\/]*)\)' + @function_declaration_parse_base_match = '([\w\s\*\(\),\[\]]*?\w[\w\s\*\(\),\[\]]*?)\(([\w\s\*\(\),\.\[\]+\-\/]*)\)' @declaration_parse_matcher = /#{@function_declaration_parse_base_match}$/m @standards = (%w[int short char long unsigned signed] + cfg.treat_as.keys).uniq @array_size_name = cfg.array_size_name @@ -245,8 +245,8 @@ def import_source(source, parse_project, cpp = false) source.gsub!(/__attribute(?:__)?\s*\(\(+.*\)\)+/, '') # remove preprocessor statements and extern "C" - source.gsub!(/^\s*#.*/, '') source.gsub!(/extern\s+\"C\"\s*\{/, '') + source.gsub!(/^\s*#.*/, '') # enums, unions, structs, and typedefs can all contain things (e.g. function pointers) that parse like function prototypes, so yank them # forward declared structs are removed before struct definitions so they don't mess up real thing later. we leave structs keywords in function prototypes @@ -484,23 +484,27 @@ def clean_args(arg_list, parse_project) arg_list.gsub!(/\*(\w)/, '* \1') # scan argument list for function pointers and replace them with custom types - arg_list.gsub!(/([\w\s\*]+)\(+\s*\*[\*\s]*([\w\s]*)\s*\)+\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |_m| + arg_list.gsub!(/([\w\s\*]+)\(+([\w\s]*)\*[\*\s]*([\w\s]*)\s*\)+\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |_m| functype = "cmock_#{parse_project[:module_name]}_func_ptr#{parse_project[:typedefs].size + 1}" funcret = Regexp.last_match(1).strip - funcname = Regexp.last_match(2).strip - funcargs = Regexp.last_match(3).strip + funcdecl = Regexp.last_match(2).strip + funcname = Regexp.last_match(3).strip + funcargs = Regexp.last_match(4).strip funconst = '' if funcname.include? 'const' funcname.gsub!('const', '').strip! funconst = 'const ' end - parse_project[:typedefs] << "typedef #{funcret}(*#{functype})(#{funcargs});" + if funcdecl != '' + funcdecl += ' ' + end + parse_project[:typedefs] << "typedef #{funcret}(#{funcdecl}*#{functype})(#{funcargs});" funcname = "cmock_arg#{c += 1}" if funcname.empty? "#{functype} #{funconst}#{funcname}" end # scan argument list for function pointers with shorthand notation and replace them with custom types - arg_list.gsub!(/([\w\s\*]+)+\s+(\w+)\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |_m| + arg_list.gsub!(/([\w\s\*]+)\s+(\w+)\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |_m| functype = "cmock_#{parse_project[:module_name]}_func_ptr#{parse_project[:typedefs].size + 1}" funcret = Regexp.last_match(1).strip funcname = Regexp.last_match(2).strip diff --git a/tools/vendor/ceedling/vendor/cmock/src/cmock.c b/tools/vendor/ceedling/vendor/cmock/src/cmock.c index 88f2c2b2..e6a11971 100644 --- a/tools/vendor/ceedling/vendor/cmock/src/cmock.c +++ b/tools/vendor/ceedling/vendor/cmock/src/cmock.c @@ -25,8 +25,9 @@ static unsigned char* CMock_Guts_Buffer = NULL; static CMOCK_MEM_INDEX_TYPE CMock_Guts_BufferSize = CMOCK_MEM_ALIGN_SIZE; static CMOCK_MEM_INDEX_TYPE CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; #else -static unsigned char CMock_Guts_Buffer[CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE]; -static CMOCK_MEM_INDEX_TYPE CMock_Guts_BufferSize = CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE; +static long long CMock_Guts_Space[(CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE + sizeof(long long) - 1) / sizeof(long long)]; +static unsigned char* CMock_Guts_Buffer = (unsigned char *)CMock_Guts_Space; +static CMOCK_MEM_INDEX_TYPE CMock_Guts_BufferSize = CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE;//sizeof(CMock_Guts_Space); static CMOCK_MEM_INDEX_TYPE CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; #endif @@ -39,12 +40,16 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size) /* verify arguments valid (we must be allocating space for at least 1 byte, and the existing chain must be in memory somewhere) */ if (size < 1) + { return CMOCK_GUTS_NONE; + } /* verify we have enough room */ size = size + CMOCK_MEM_INDEX_SIZE; if (size & CMOCK_MEM_ALIGN_MASK) + { size = (size + CMOCK_MEM_ALIGN_MASK) & ~CMOCK_MEM_ALIGN_MASK; + } if ((CMock_Guts_BufferSize - CMock_Guts_FreePtr) < size) { #ifndef CMOCK_MEM_DYNAMIC @@ -103,9 +108,13 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_ do { index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE); if (index >= CMock_Guts_FreePtr) + { return CMOCK_GUTS_NONE; + } if (index > 0) + { next = (void*)(&CMock_Guts_Buffer[index]); + } } while (index > 0); *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE) = (CMOCK_MEM_INDEX_TYPE)((CMOCK_MEM_PTR_AS_INT)obj - (CMOCK_MEM_PTR_AS_INT)CMock_Guts_Buffer); return root_index; @@ -122,16 +131,22 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index /* There is nothing "next" if the pointer isn't from our buffer */ if ((previous_item_index < CMOCK_MEM_ALIGN_SIZE) || (previous_item_index >= CMock_Guts_FreePtr)) + { return CMOCK_GUTS_NONE; + } previous_item = (void*)(&CMock_Guts_Buffer[previous_item_index]); /* if the pointer is good, then use it to look up the next index * (we know the first element always goes in zero, so NEXT must always be > 1) */ index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)previous_item - CMOCK_MEM_INDEX_SIZE); if ((index > 1) && (index < CMock_Guts_FreePtr)) + { return index; + } else + { return CMOCK_GUTS_NONE; + } } /*------------------------------------------------------- diff --git a/tools/vendor/ceedling/vendor/unity/auto/__init__.py b/tools/vendor/ceedling/vendor/unity/auto/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tools/vendor/ceedling/vendor/unity/auto/extract_version.py b/tools/vendor/ceedling/vendor/unity/auto/extract_version.py new file mode 100644 index 00000000..1d137e5b --- /dev/null +++ b/tools/vendor/ceedling/vendor/unity/auto/extract_version.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +import re +import sys + +ver_re = re.compile(r"^#define\s+UNITY_VERSION_(?:MAJOR|MINOR|BUILD)\s+(\d+)$") +version = [] + +with open(sys.argv[1], "r") as f: + for line in f: + m = ver_re.match(line) + if m: + version.append(m.group(1)) + +print(".".join(version)) + diff --git a/tools/vendor/ceedling/vendor/unity/auto/generate_module.rb b/tools/vendor/ceedling/vendor/unity/auto/generate_module.rb index 0a88becc..7151586b 100644 --- a/tools/vendor/ceedling/vendor/unity/auto/generate_module.rb +++ b/tools/vendor/ceedling/vendor/unity/auto/generate_module.rb @@ -116,8 +116,8 @@ def self.default_options def self.grab_config(config_file) options = default_options unless config_file.nil? || config_file.empty? - require 'yaml' - yaml_guts = YAML.load_file(config_file) + require_relative 'yaml_helper' + yaml_guts = YamlHelper.load_file(config_file) options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) raise "No :unity or :cmock section found in #{config_file}" unless options end @@ -170,16 +170,16 @@ def files_to_operate_on(module_name, pattern = nil) ############################ def neutralize_filename(name, start_cap = true) return name if name.empty? - name = name.split(/(?:\s+|_|(?=[A-Z][a-z]))|(?<=[a-z])(?=[A-Z])/).map { |v| v.capitalize }.join('_') + name = name.split(/(?:\s+|_|(?=[A-Z][a-z]))|(?<=[a-z])(?=[A-Z])/).map(&:capitalize).join('_') name = name[0].downcase + name[1..-1] unless start_cap - return name + name end ############################ def create_filename(part1, part2 = '') name = part2.empty? ? part1 : part1 + '_' + part2 case (@options[:naming]) - when 'bumpy' then neutralize_filename(name,false).delete('_') + when 'bumpy' then neutralize_filename(name, false).delete('_') when 'camel' then neutralize_filename(name).delete('_') when 'snake' then neutralize_filename(name).downcase when 'caps' then neutralize_filename(name).upcase @@ -211,8 +211,8 @@ def generate(module_name, pattern = nil) f.write("#{file[:boilerplate]}\n" % [file[:name]]) unless file[:boilerplate].nil? f.write(file[:template] % [file[:name], file[:includes].map { |ff| "#include \"#{ff}\"\n" }.join, - file[:name].upcase.gsub(/-/, '_'), - file[:name].gsub(/-/, '_')]) + file[:name].upcase.tr('-', '_'), + file[:name].tr('-', '_')]) end if @options[:update_svn] `svn add \"#{file[:path]}\"` diff --git a/tools/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb b/tools/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb index d1d8f91a..69f3ff50 100644 --- a/tools/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb +++ b/tools/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb @@ -1,3 +1,5 @@ +#!/usr/bin/ruby + # ========================================== # Unity Project - A Test Framework for C # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams @@ -51,8 +53,8 @@ def self.default_options def self.grab_config(config_file) options = default_options unless config_file.nil? || config_file.empty? - require 'yaml' - yaml_guts = YAML.load_file(config_file) + require_relative 'yaml_helper' + yaml_guts = YamlHelper.load_file(config_file) options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) raise "No :unity or :cmock section found in #{config_file}" unless options end @@ -130,7 +132,8 @@ def find_tests(source) lines.each_with_index do |line, _index| # find tests - next unless line =~ /^((?:\s*(?:TEST_CASE|TEST_RANGE)\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m + next unless line =~ /^((?:\s*(?:TEST_(?:CASE|RANGE|MATRIX))\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m + next unless line =~ /^((?:\s*(?:TEST_(?:CASE|RANGE|MATRIX))\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]})\w*)\s*\(\s*(.*)\s*\)/m arguments = Regexp.last_match(1) name = Regexp.last_match(2) @@ -140,19 +143,38 @@ def find_tests(source) if @options[:use_param_tests] && !arguments.empty? args = [] - arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] } + type_and_args = arguments.split(/TEST_(CASE|RANGE|MATRIX)/) + for i in (1...type_and_args.length).step(2) + case type_and_args[i] + when "CASE" + args << type_and_args[i + 1].sub(/^\s*\(\s*(.*?)\s*\)\s*$/m, '\1') + + when "RANGE" + args += type_and_args[i + 1].scan(/(\[|<)\s*(-?\d+.?\d*)\s*,\s*(-?\d+.?\d*)\s*,\s*(-?\d+.?\d*)\s*(\]|>)/m).map do |arg_values_str| + exclude_end = arg_values_str[0] == '<' && arg_values_str[-1] == '>' + arg_values_str[1...-1].map do |arg_value_str| + arg_value_str.include?('.') ? arg_value_str.to_f : arg_value_str.to_i + end.push(exclude_end) + end.map do |arg_values| + Range.new(arg_values[0], arg_values[1], arg_values[3]).step(arg_values[2]).to_a + end.reduce(nil) do |result, arg_range_expanded| + result.nil? ? arg_range_expanded.map { |a| [a] } : result.product(arg_range_expanded) + end.map do |arg_combinations| + arg_combinations.flatten.join(', ') + end - arguments.scan(/\s*TEST_RANGE\s*\((.*)\)\s*$/).flatten.each do |range_str| - args += range_str.scan(/\[\s*(-?\d+.?\d*),\s*(-?\d+.?\d*),\s*(-?\d+.?\d*)\s*\]/).map do |arg_values_str| - arg_values_str.map do |arg_value_str| - arg_value_str.include?('.') ? arg_value_str.to_f : arg_value_str.to_i + when "MATRIX" + single_arg_regex_string = /(?:(?:"(?:\\"|[^\\])*?")+|(?:'\\?.')+|(?:[^\s\]\["'\,]|\[[\d\S_-]+\])+)/.source + args_regex = /\[((?:\s*#{single_arg_regex_string}\s*,?)*(?:\s*#{single_arg_regex_string})?\s*)\]/m + arg_elements_regex = /\s*(#{single_arg_regex_string})\s*,\s*/m + + args += type_and_args[i + 1].scan(args_regex).flatten.map do |arg_values_str| + (arg_values_str + ',').scan(arg_elements_regex) + end.reduce do |result, arg_range_expanded| + result.product(arg_range_expanded) + end.map do |arg_combinations| + arg_combinations.flatten.join(', ') end - end.map do |arg_values| - (arg_values[0]..arg_values[1]).step(arg_values[2]).to_a - end.reduce do |result, arg_range_expanded| - result.product(arg_range_expanded) - end.map do |arg_combinations| - arg_combinations.flatten.join(', ') end end end @@ -188,7 +210,7 @@ def find_includes(source) includes = { local: source.scan(/^\s*#include\s+\"\s*(.+\.#{@options[:include_extensions]})\s*\"/).flatten, system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" }, - linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+\.#{@options[:source_extensions]})\s*\"/).flatten + linkonly: source.scan(/^TEST_SOURCE_FILE\(\s*\"\s*(.+\.#{@options[:source_extensions]})\s*\"/).flatten } includes end @@ -212,8 +234,10 @@ def find_setup_and_teardown(source) def create_header(output, mocks, testfile_includes = []) output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') output.puts("\n/*=======Automagically Detected Files To Include=====*/") + output.puts('extern "C" {') if @options[:externcincludes] output.puts("#include \"#{@options[:framework]}.h\"") output.puts('#include "cmock.h"') unless mocks.empty? + output.puts('}') if @options[:externcincludes] if @options[:defines] && !@options[:defines].empty? @options[:defines].each { |d| output.puts("#ifndef #{d}\n#define #{d}\n#endif /* #{d} */") } end @@ -227,9 +251,11 @@ def create_header(output, mocks, testfile_includes = []) output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}") end end + output.puts('extern "C" {') if @options[:externcincludes] mocks.each do |mock| output.puts("#include \"#{mock}\"") end + output.puts('}') if @options[:externcincludes] output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception) return unless @options[:enforce_strict_ordering] @@ -341,7 +367,8 @@ def create_reset(output) def create_run_test(output) require 'erb' - template = ERB.new(File.read(File.join(__dir__, 'run_test.erb')), nil, '<>') + file = File.read(File.join(__dir__, 'run_test.erb')) + template = ERB.new(file, trim_mode: '<>') output.puts("\n" + template.result(binding)) end @@ -375,7 +402,7 @@ def create_main(output, filename, tests, used_mocks) output.puts(' {') output.puts(' if (parse_status < 0)') output.puts(' {') - output.puts(" UnityPrint(\"#{filename.gsub('.c', '')}.\");") + output.puts(" UnityPrint(\"#{filename.gsub('.c', '').gsub(/\\/, '\\\\\\')}.\");") output.puts(' UNITY_PRINT_EOL();') tests.each do |test| if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty? @@ -465,6 +492,9 @@ def create_h_file(output, filename, tests, testfile_includes, used_mocks) when '-cexception' options[:plugins] = [:cexception] true + when '-externcincludes' + options[:externcincludes] = true + true when /\.*\.ya?ml$/ options = UnityTestRunnerGenerator.grab_config(arg) true diff --git a/tools/vendor/ceedling/vendor/unity/auto/parse_output.rb b/tools/vendor/ceedling/vendor/unity/auto/parse_output.rb index d72c6e8b..864104be 100644 --- a/tools/vendor/ceedling/vendor/unity/auto/parse_output.rb +++ b/tools/vendor/ceedling/vendor/unity/auto/parse_output.rb @@ -14,10 +14,14 @@ # - normal output (raw unity) # - fixture output (unity_fixture.h/.c) # - fixture output with verbose flag set ("-v") +# - time output flag set (UNITY_INCLUDE_EXEC_TIME define enabled with milliseconds output) # # To use this parser use the following command # ruby parseOutput.rb [options] [file] # options: -xml : produce a JUnit compatible XML file +# -suiteRequiredSuiteName +# : replace default test suite name to +# "RequiredSuiteName" (can be any name) # file: file to scan for results #============================================================ @@ -26,6 +30,7 @@ class ParseOutput def initialize # internal data @class_name_idx = 0 + @result_usual_idx = 3 @path_delim = nil # xml output related @@ -33,6 +38,9 @@ def initialize @array_list = false # current suite name and statistics + ## testsuite name + @real_test_suite_name = 'Unity' + ## classname for testcase @test_suite = nil @total_tests = 0 @test_passed = 0 @@ -45,6 +53,16 @@ def set_xml_output @xml_out = true end + # Set the flag to indicate if there will be an XML output file or not + def test_suite_name=(cli_arg) + @real_test_suite_name = cli_arg + puts 'Real test suite name will be \'' + @real_test_suite_name + '\'' + end + + def xml_encode_s(str) + str.encode(:xml => :attr) + end + # If write our output to XML def write_xml_output output = File.open('report.xml', 'w') @@ -57,27 +75,27 @@ def write_xml_output # Pushes the suite info as xml to the array list, which will be written later def push_xml_output_suite_info # Insert opening tag at front - heading = '' + heading = '' @array_list.insert(0, heading) # Push back the closing tag @array_list.push '' end # Pushes xml output data to the array list, which will be written later - def push_xml_output_passed(test_name) - @array_list.push ' ' + def push_xml_output_passed(test_name, execution_time = 0) + @array_list.push ' ' end # Pushes xml output data to the array list, which will be written later - def push_xml_output_failed(test_name, reason) - @array_list.push ' ' + def push_xml_output_failed(test_name, reason, execution_time = 0) + @array_list.push ' ' @array_list.push ' ' + reason + '' @array_list.push ' ' end # Pushes xml output data to the array list, which will be written later - def push_xml_output_ignored(test_name, reason) - @array_list.push ' ' + def push_xml_output_ignored(test_name, reason, execution_time = 0) + @array_list.push ' ' @array_list.push ' ' + reason + '' @array_list.push ' ' end @@ -152,19 +170,29 @@ def test_ignored_unity_fixture(array) # Test was flagged as having passed so format the output def test_passed(array) + # ':' symbol will be valid in function args now + real_method_name = array[@result_usual_idx - 1..-2].join(':') + array = array[0..@result_usual_idx - 2] + [real_method_name] + [array[-1]] + last_item = array.length - 1 + test_time = get_test_time(array[last_item]) test_name = array[last_item - 1] test_suite_verify(array[@class_name_idx]) - printf "%-40s PASS\n", test_name + printf "%-40s PASS %10d ms\n", test_name, test_time return unless @xml_out - push_xml_output_passed(test_name) if @xml_out + push_xml_output_passed(test_name, test_time) if @xml_out end # Test was flagged as having failed so format the line def test_failed(array) + # ':' symbol will be valid in function args now + real_method_name = array[@result_usual_idx - 1..-3].join(':') + array = array[0..@result_usual_idx - 3] + [real_method_name] + array[-2..-1] + last_item = array.length - 1 + test_time = get_test_time(array[last_item]) test_name = array[last_item - 2] reason = array[last_item].chomp.lstrip + ' at line: ' + array[last_item - 3] class_name = array[@class_name_idx] @@ -180,14 +208,19 @@ def test_failed(array) end test_suite_verify(class_name) - printf "%-40s FAILED\n", test_name + printf "%-40s FAILED %10d ms\n", test_name, test_time - push_xml_output_failed(test_name, reason) if @xml_out + push_xml_output_failed(test_name, reason, test_time) if @xml_out end # Test was flagged as being ignored so format the output def test_ignored(array) + # ':' symbol will be valid in function args now + real_method_name = array[@result_usual_idx - 1..-3].join(':') + array = array[0..@result_usual_idx - 3] + [real_method_name] + array[-2..-1] + last_item = array.length - 1 + test_time = get_test_time(array[last_item]) test_name = array[last_item - 2] reason = array[last_item].chomp.lstrip class_name = array[@class_name_idx] @@ -203,9 +236,18 @@ def test_ignored(array) end test_suite_verify(class_name) - printf "%-40s IGNORED\n", test_name + printf "%-40s IGNORED %10d ms\n", test_name, test_time - push_xml_output_ignored(test_name, reason) if @xml_out + push_xml_output_ignored(test_name, reason, test_time) if @xml_out + end + + # Test time will be in ms + def get_test_time(value_with_time) + test_time_array = value_with_time.scan(/\((-?\d+.?\d*) ms\)\s*$/).flatten.map do |arg_value_str| + arg_value_str.include?('.') ? arg_value_str.to_f : arg_value_str.to_i + end + + test_time_array.any? ? test_time_array[0] : 0 end # Adjusts the os specific members according to the current path style @@ -234,7 +276,8 @@ def process(file_name) puts '' puts '=================== RESULTS =====================' puts '' - File.open(file_name).each do |line| + # Apply binary encoding. Bad symbols will be unchanged + File.open(file_name, 'rb').each do |line| # Typical test lines look like these: # ---------------------------------------------------- # 1. normal output: @@ -288,6 +331,22 @@ def process(file_name) line_array.push('No reason given') test_ignored(line_array) @test_ignored += 1 + elsif line_array.size >= 4 + # We will check output from color compilation + if line_array[@result_usual_idx..-1].any? { |l| l.include? 'PASS' } + test_passed(line_array) + @test_passed += 1 + elsif line_array[@result_usual_idx..-1].any? { |l| l.include? 'FAIL' } + test_failed(line_array) + @test_failed += 1 + elsif line_array[@result_usual_idx..-2].any? { |l| l.include? 'IGNORE' } + test_ignored(line_array) + @test_ignored += 1 + elsif line_array[@result_usual_idx..-1].any? { |l| l.include? 'IGNORE' } + line_array.push('No reason given (' + get_test_time(line_array[@result_usual_idx..-1]).to_s + ' ms)') + test_ignored(line_array) + @test_ignored += 1 + end end @total_tests = @test_passed + @test_failed + @test_ignored end @@ -314,6 +373,8 @@ def process(file_name) ARGV.each do |arg| if arg == '-xml' parse_my_file.set_xml_output + elsif arg.start_with?('-suite') + parse_my_file.test_suite_name = arg.delete_prefix('-suite') else parse_my_file.process(arg) break diff --git a/tools/vendor/ceedling/vendor/unity/auto/run_test.erb b/tools/vendor/ceedling/vendor/unity/auto/run_test.erb index f91b5669..68b33730 100644 --- a/tools/vendor/ceedling/vendor/unity/auto/run_test.erb +++ b/tools/vendor/ceedling/vendor/unity/auto/run_test.erb @@ -14,7 +14,7 @@ static void run_test(UnityTestFunction func, const char* name, UNITY_LINE_TYPE l if (TEST_PROTECT()) { <% if @options[:plugins].include?(:cexception) %> - CEXCEPTION_T e; + volatile CEXCEPTION_T e; Try { <%= @options[:setup_name] %>(); func(); diff --git a/tools/vendor/ceedling/vendor/unity/auto/unity_to_junit.py b/tools/vendor/ceedling/vendor/unity/auto/stylize_as_junit.py similarity index 60% rename from tools/vendor/ceedling/vendor/unity/auto/unity_to_junit.py rename to tools/vendor/ceedling/vendor/unity/auto/stylize_as_junit.py index 71dd5688..06c86596 100644 --- a/tools/vendor/ceedling/vendor/unity/auto/unity_to_junit.py +++ b/tools/vendor/ceedling/vendor/unity/auto/stylize_as_junit.py @@ -1,6 +1,15 @@ +#! python3 +# ========================================== +# Fork from Unity Project - A Test Framework for C +# Pull request on Gerrit in progress, the objective of this file is to be deleted when official Unity deliveries +# include that modification +# Copyright (c) 2015 Alexander Mueller / XelaRellum@web.de +# [Released under MIT License. Please refer to license.txt for details] +# ========================================== import sys import os from glob import glob +import argparse from pyparsing import * from junit_xml import TestSuite, TestCase @@ -14,6 +23,7 @@ def __init__(self): self.ignored = 0 self.targets = 0 self.root = None + self.output = None self.test_suites = dict() def run(self): @@ -37,15 +47,18 @@ def run(self): entry = entry_one | entry_two delimiter = Literal(':').suppress() - tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName( - 'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName( - 'tc_status') + Optional( - delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line") + # Format of a result line is `[file_name]:line:test_name:RESULT[:msg]` + tc_result_line = Group(ZeroOrMore(entry.setResultsName('tc_file_name')) + + delimiter + entry.setResultsName('tc_line_nr') + + delimiter + entry.setResultsName('tc_name') + + delimiter + entry.setResultsName('tc_status') + + Optional(delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line") eol = LineEnd().suppress() sol = LineStart().suppress() blank_line = sol + eol + # Format of the summary line is `# Tests # Failures # Ignored` tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName( "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName( "tc_summary") @@ -67,7 +80,10 @@ def run(self): tmp_tc_line = r['tc_line'] # get only the file name which will be used as the classname - file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0] + if 'tc_file_name' in tmp_tc_line: + file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0] + else: + file_name = result_file.strip("./") tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name) if 'tc_status' in tmp_tc_line: if str(tmp_tc_line['tc_status']) == 'IGNORE': @@ -96,7 +112,7 @@ def run(self): for suite_name in self.test_suites: ts.append(TestSuite(suite_name, self.test_suites[suite_name])) - with open('result.xml', 'w') as f: + with open(self.output, 'w') as f: TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8') return self.report @@ -107,40 +123,39 @@ def set_targets(self, target_array): def set_root_path(self, path): self.root = path - @staticmethod - def usage(err_msg=None): - print("\nERROR: ") - if err_msg: - print(err_msg) - print("\nUsage: unity_test_summary.py result_file_directory/ root_path/") - print(" result_file_directory - The location of your results files.") - print(" Defaults to current directory if not specified.") - print(" Should end in / if specified.") - print(" root_path - Helpful for producing more verbose output if using relative paths.") - sys.exit(1) + def set_output(self, output): + self.output = output if __name__ == '__main__': uts = UnityTestSummary() - try: - # look in the specified or current directory for result files - if len(sys.argv) > 1: - targets_dir = sys.argv[1] - else: - targets_dir = './' - targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*'))) - if len(targets) == 0: - raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir) - uts.set_targets(targets) - - # set the root path - if len(sys.argv) > 2: - root_path = sys.argv[2] - else: - root_path = os.path.split(__file__)[0] - uts.set_root_path(root_path) - - # run the summarizer - print(uts.run()) - except Exception as e: - UnityTestSummary.usage(e) + parser = argparse.ArgumentParser(description= + """Takes as input the collection of *.testpass and *.testfail result + files, and converts them to a JUnit formatted XML.""") + parser.add_argument('targets_dir', metavar='result_file_directory', + type=str, nargs='?', default='./', + help="""The location of your results files. + Defaults to current directory if not specified.""") + parser.add_argument('root_path', nargs='?', + default='os.path.split(__file__)[0]', + help="""Helpful for producing more verbose output if + using relative paths.""") + parser.add_argument('--output', '-o', type=str, default="result.xml", + help="""The name of the JUnit-formatted file (XML).""") + args = parser.parse_args() + + if args.targets_dir[-1] != '/': + args.targets_dir+='/' + targets = list(map(lambda x: x.replace('\\', '/'), glob(args.targets_dir + '*.test*'))) + if len(targets) == 0: + raise Exception("No *.testpass or *.testfail files found in '%s'" % args.targets_dir) + uts.set_targets(targets) + + # set the root path + uts.set_root_path(args.root_path) + + # set output + uts.set_output(args.output) + + # run the summarizer + print(uts.run()) diff --git a/tools/vendor/ceedling/vendor/unity/auto/test_file_filter.rb b/tools/vendor/ceedling/vendor/unity/auto/test_file_filter.rb index 5c3a79fc..3cc32de8 100644 --- a/tools/vendor/ceedling/vendor/unity/auto/test_file_filter.rb +++ b/tools/vendor/ceedling/vendor/unity/auto/test_file_filter.rb @@ -4,7 +4,7 @@ # [Released under MIT License. Please refer to license.txt for details] # ========================================== -require'yaml' +require_relative 'yaml_helper' module RakefileHelpers class TestFileFilter @@ -12,9 +12,10 @@ def initialize(all_files = false) @all_files = all_files return unless @all_files - return unless File.exist?('test_file_filter.yml') - filters = YAML.load_file('test_file_filter.yml') + file = 'test_file_filter.yml' + return unless File.exist?(file) + filters = YamlHelper.load_file(file) @all_files = filters[:all_files] @only_files = filters[:only_files] @exclude_files = filters[:exclude_files] diff --git a/tools/vendor/ceedling/vendor/unity/auto/yaml_helper.rb b/tools/vendor/ceedling/vendor/unity/auto/yaml_helper.rb new file mode 100644 index 00000000..e5a08657 --- /dev/null +++ b/tools/vendor/ceedling/vendor/unity/auto/yaml_helper.rb @@ -0,0 +1,19 @@ +# ========================================== +# Unity Project - A Test Framework for C +# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +# [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +require 'yaml' + +module YamlHelper + def self.load(body) + YAML.respond_to?(:unsafe_load) ? + YAML.unsafe_load(body) : YAML.load(body) + end + + def self.load_file(file) + body = File.read(file) + self.load(body) + end +end diff --git a/tools/vendor/ceedling/vendor/unity/src/meson.build b/tools/vendor/ceedling/vendor/unity/src/meson.build index 1c7b426f..5365227f 100644 --- a/tools/vendor/ceedling/vendor/unity/src/meson.build +++ b/tools/vendor/ceedling/vendor/unity/src/meson.build @@ -1,11 +1,17 @@ # -# build script written by : Michael Brockus. +# build script written by : Michael Gene Brockus. # github repo author: Mike Karlesky, Mark VanderVoord, Greg Williams. # # license: MIT # -unity_dir = include_directories('.') -unity_lib = static_library(meson.project_name(), - files('unity.c'), - include_directories: unity_dir) +unity_inc += include_directories('.') +unity_src += files('unity.c') + +if not meson.is_subproject() + install_headers( + 'unity.h', + 'unity_internals.h', + subdir: meson.project_name() + ) +endif diff --git a/tools/vendor/ceedling/vendor/unity/src/unity.c b/tools/vendor/ceedling/vendor/unity/src/unity.c index 764a42b1..8c946ebe 100644 --- a/tools/vendor/ceedling/vendor/unity/src/unity.c +++ b/tools/vendor/ceedling/vendor/unity/src/unity.c @@ -5,12 +5,9 @@ ============================================================================ */ #include "unity.h" -#include -#ifdef AVR -#include -#else -#define PROGMEM +#ifndef UNITY_PROGMEM +#define UNITY_PROGMEM #endif /* If omitted from header, declare overrideable prototypes here so they're ready for use */ @@ -19,57 +16,57 @@ void UNITY_OUTPUT_CHAR(int); #endif /* Helpful macros for us to use here in Assert functions */ -#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } -#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } -#define RETURN_IF_FAIL_OR_IGNORE if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) TEST_ABORT() +#define UNITY_FAIL_AND_BAIL do { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define UNITY_IGNORE_AND_BAIL do { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define RETURN_IF_FAIL_OR_IGNORE do { if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) { TEST_ABORT(); } } while (0) struct UNITY_STORAGE_T Unity; #ifdef UNITY_OUTPUT_COLOR -const char PROGMEM UnityStrOk[] = "\033[42mOK\033[00m"; -const char PROGMEM UnityStrPass[] = "\033[42mPASS\033[00m"; -const char PROGMEM UnityStrFail[] = "\033[41mFAIL\033[00m"; -const char PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[00m"; +const char UNITY_PROGMEM UnityStrOk[] = "\033[42mOK\033[0m"; +const char UNITY_PROGMEM UnityStrPass[] = "\033[42mPASS\033[0m"; +const char UNITY_PROGMEM UnityStrFail[] = "\033[41mFAIL\033[0m"; +const char UNITY_PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[0m"; #else -const char PROGMEM UnityStrOk[] = "OK"; -const char PROGMEM UnityStrPass[] = "PASS"; -const char PROGMEM UnityStrFail[] = "FAIL"; -const char PROGMEM UnityStrIgnore[] = "IGNORE"; +const char UNITY_PROGMEM UnityStrOk[] = "OK"; +const char UNITY_PROGMEM UnityStrPass[] = "PASS"; +const char UNITY_PROGMEM UnityStrFail[] = "FAIL"; +const char UNITY_PROGMEM UnityStrIgnore[] = "IGNORE"; #endif -static const char PROGMEM UnityStrNull[] = "NULL"; -static const char PROGMEM UnityStrSpacer[] = ". "; -static const char PROGMEM UnityStrExpected[] = " Expected "; -static const char PROGMEM UnityStrWas[] = " Was "; -static const char PROGMEM UnityStrGt[] = " to be greater than "; -static const char PROGMEM UnityStrLt[] = " to be less than "; -static const char PROGMEM UnityStrOrEqual[] = "or equal to "; -static const char PROGMEM UnityStrNotEqual[] = " to be not equal to "; -static const char PROGMEM UnityStrElement[] = " Element "; -static const char PROGMEM UnityStrByte[] = " Byte "; -static const char PROGMEM UnityStrMemory[] = " Memory Mismatch."; -static const char PROGMEM UnityStrDelta[] = " Values Not Within Delta "; -static const char PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; -static const char PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; -static const char PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +static const char UNITY_PROGMEM UnityStrNull[] = "NULL"; +static const char UNITY_PROGMEM UnityStrSpacer[] = ". "; +static const char UNITY_PROGMEM UnityStrExpected[] = " Expected "; +static const char UNITY_PROGMEM UnityStrWas[] = " Was "; +static const char UNITY_PROGMEM UnityStrGt[] = " to be greater than "; +static const char UNITY_PROGMEM UnityStrLt[] = " to be less than "; +static const char UNITY_PROGMEM UnityStrOrEqual[] = "or equal to "; +static const char UNITY_PROGMEM UnityStrNotEqual[] = " to be not equal to "; +static const char UNITY_PROGMEM UnityStrElement[] = " Element "; +static const char UNITY_PROGMEM UnityStrByte[] = " Byte "; +static const char UNITY_PROGMEM UnityStrMemory[] = " Memory Mismatch."; +static const char UNITY_PROGMEM UnityStrDelta[] = " Values Not Within Delta "; +static const char UNITY_PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UNITY_PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UNITY_PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; #ifndef UNITY_EXCLUDE_FLOAT -static const char PROGMEM UnityStrNot[] = "Not "; -static const char PROGMEM UnityStrInf[] = "Infinity"; -static const char PROGMEM UnityStrNegInf[] = "Negative Infinity"; -static const char PROGMEM UnityStrNaN[] = "NaN"; -static const char PROGMEM UnityStrDet[] = "Determinate"; -static const char PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +static const char UNITY_PROGMEM UnityStrNot[] = "Not "; +static const char UNITY_PROGMEM UnityStrInf[] = "Infinity"; +static const char UNITY_PROGMEM UnityStrNegInf[] = "Negative Infinity"; +static const char UNITY_PROGMEM UnityStrNaN[] = "NaN"; +static const char UNITY_PROGMEM UnityStrDet[] = "Determinate"; +static const char UNITY_PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; #endif -const char PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; -const char PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; -const char PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; -const char PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; -static const char PROGMEM UnityStrBreaker[] = "-----------------------"; -static const char PROGMEM UnityStrResultsTests[] = " Tests "; -static const char PROGMEM UnityStrResultsFailures[] = " Failures "; -static const char PROGMEM UnityStrResultsIgnored[] = " Ignored "; +const char UNITY_PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; +const char UNITY_PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UNITY_PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UNITY_PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char UNITY_PROGMEM UnityStrBreaker[] = "-----------------------"; +static const char UNITY_PROGMEM UnityStrResultsTests[] = " Tests "; +static const char UNITY_PROGMEM UnityStrResultsFailures[] = " Failures "; +static const char UNITY_PROGMEM UnityStrResultsIgnored[] = " Ignored "; #ifndef UNITY_EXCLUDE_DETAILS -static const char PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; -static const char PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; +static const char UNITY_PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; #endif /*----------------------------------------------- * Pretty Printers & Test Result Output Handlers @@ -369,10 +366,12 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) } else { - UNITY_INT32 n_int = 0, n; - int exponent = 0; - int decimals, digits; - char buf[16] = {0}; + UNITY_INT32 n_int = 0; + UNITY_INT32 n; + int exponent = 0; + int decimals; + int digits; + char buf[16] = {0}; /* * Scale up or down by powers of 10. To minimize rounding error, @@ -450,9 +449,14 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) buf[digits++] = (char)('0' + n % 10); n /= 10; } + + /* print out buffer (backwards) */ while (digits > 0) { - if (digits == decimals) { UNITY_OUTPUT_CHAR('.'); } + if (digits == decimals) + { + UNITY_OUTPUT_CHAR('.'); + } UNITY_OUTPUT_CHAR(buf[--digits]); } @@ -564,26 +568,26 @@ void UnityConcludeTest(void) /*-----------------------------------------------*/ static void UnityAddMsgIfSpecified(const char* msg) { - if (msg) - { - UnityPrint(UnityStrSpacer); - #ifdef UNITY_PRINT_TEST_CONTEXT - UNITY_PRINT_TEST_CONTEXT(); + UnityPrint(UnityStrSpacer); + UNITY_PRINT_TEST_CONTEXT(); #endif #ifndef UNITY_EXCLUDE_DETAILS - if (Unity.CurrentDetail1) + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrSpacer); + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) { - UnityPrint(UnityStrDetail1Name); - UnityPrint(Unity.CurrentDetail1); - if (Unity.CurrentDetail2) - { - UnityPrint(UnityStrDetail2Name); - UnityPrint(Unity.CurrentDetail2); - } - UnityPrint(UnityStrSpacer); + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); } + } #endif + if (msg) + { + UnityPrint(UnityStrSpacer); UnityPrint(msg); } } @@ -765,11 +769,12 @@ void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, } #define UnityPrintPointlessAndBail() \ -{ \ +do { \ UnityTestResultsFailBegin(lineNumber); \ UnityPrint(UnityStrPointless); \ UnityAddMsgIfSpecified(msg); \ - UNITY_FAIL_AND_BAIL; } + UNITY_FAIL_AND_BAIL; \ +} while (0) /*-----------------------------------------------*/ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, @@ -788,7 +793,11 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, if (num_elements == 0) { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else UnityPrintPointlessAndBail(); +#endif } if (expected == actual) @@ -811,12 +820,22 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, case 1: expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x000000FF; + actual_val &= 0x000000FF; + } increment = sizeof(UNITY_INT8); break; case 2: expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x0000FFFF; + actual_val &= 0x0000FFFF; + } increment = sizeof(UNITY_INT16); break; @@ -832,6 +851,13 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, case 4: expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; +#ifdef UNITY_SUPPORT_64 + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x00000000FFFFFFFF; + actual_val &= 0x00000000FFFFFFFF; + } +#endif increment = sizeof(UNITY_INT32); length = 4; break; @@ -884,11 +910,12 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, #ifndef UNITY_EXCLUDE_FLOAT_PRINT #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ - { \ + do { \ UnityPrint(UnityStrExpected); \ UnityPrintFloat(expected); \ UnityPrint(UnityStrWas); \ - UnityPrintFloat(actual); } + UnityPrintFloat(actual); \ + } while (0) #else #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ UnityPrint(UnityStrDelta) @@ -902,21 +929,39 @@ static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOA } /*-----------------------------------------------*/ -void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, - UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags) +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) { UNITY_UINT32 elements = num_elements; UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; + UNITY_FLOAT in_delta = delta; + UNITY_FLOAT current_element_delta = delta; RETURN_IF_FAIL_OR_IGNORE; if (elements == 0) { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (isinf(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (isnan(in_delta)) + { + /* Delta must be correct number */ UnityPrintPointlessAndBail(); } @@ -930,9 +975,23 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, UNITY_FAIL_AND_BAIL; } + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + while (elements--) { - if (!UnityFloatsWithin(*ptr_expected * UNITY_FLOAT_PRECISION, *ptr_expected, *ptr_actual)) + current_element_delta = *ptr_expected * UNITY_FLOAT_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityFloatsWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) { UnityTestResultsFailBegin(lineNumber); UnityPrint(UnityStrElement); @@ -968,6 +1027,60 @@ void UnityAssertFloatsWithin(const UNITY_FLOAT delta, } } +/*-----------------------------------------------*/ +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityFloatsWithin(threshold * UNITY_FLOAT_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + /*-----------------------------------------------*/ void UnityAssertFloatSpecial(const UNITY_FLOAT actual, const char* msg, @@ -1002,6 +1115,7 @@ void UnityAssertFloatSpecial(const UNITY_FLOAT actual, is_trait = !isinf(actual) && !isnan(actual); break; + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ default: /* including UNITY_FLOAT_INVALID_TRAIT */ trait_index = 0; trait_names[0] = UnityStrInvalidFloatTrait; @@ -1043,21 +1157,39 @@ static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_D } /*-----------------------------------------------*/ -void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, - UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags) +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) { UNITY_UINT32 elements = num_elements; UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; + UNITY_DOUBLE in_delta = delta; + UNITY_DOUBLE current_element_delta = delta; RETURN_IF_FAIL_OR_IGNORE; if (elements == 0) { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (isinf(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (isnan(in_delta)) + { + /* Delta must be correct number */ UnityPrintPointlessAndBail(); } @@ -1071,9 +1203,23 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expecte UNITY_FAIL_AND_BAIL; } + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + while (elements--) { - if (!UnityDoublesWithin(*ptr_expected * UNITY_DOUBLE_PRECISION, *ptr_expected, *ptr_actual)) + current_element_delta = *ptr_expected * UNITY_DOUBLE_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityDoublesWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) { UnityTestResultsFailBegin(lineNumber); UnityPrint(UnityStrElement); @@ -1108,6 +1254,60 @@ void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, } } +/*-----------------------------------------------*/ +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityDoublesWithin(threshold * UNITY_DOUBLE_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + /*-----------------------------------------------*/ void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, const char* msg, @@ -1142,6 +1342,7 @@ void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, is_trait = !isinf(actual) && !isnan(actual); break; + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ default: /* including UNITY_FLOAT_INVALID_TRAIT */ trait_index = 0; trait_names[0] = UnityStrInvalidFloatTrait; @@ -1239,7 +1440,11 @@ void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, if (num_elements == 0) { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else UnityPrintPointlessAndBail(); +#endif } if (expected == actual) @@ -1260,30 +1465,70 @@ void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, switch (length) { case 1: - expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; - actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; - increment = sizeof(UNITY_INT8); + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + increment = sizeof(UNITY_INT8); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)actual; + increment = sizeof(UNITY_UINT8); + } break; case 2: - expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; - actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; - increment = sizeof(UNITY_INT16); + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + increment = sizeof(UNITY_INT16); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)actual; + increment = sizeof(UNITY_UINT16); + } break; #ifdef UNITY_SUPPORT_64 case 8: - expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; - actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; - increment = sizeof(UNITY_INT64); + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)actual; + increment = sizeof(UNITY_UINT64); + } break; #endif default: /* default is length 4 bytes */ case 4: - expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; - actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; - increment = sizeof(UNITY_INT32); + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + increment = sizeof(UNITY_INT32); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)actual; + increment = sizeof(UNITY_UINT32); + } length = 4; break; } @@ -1438,7 +1683,11 @@ void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, /* if no elements, it's an error */ if (num_elements == 0) { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else UnityPrintPointlessAndBail(); +#endif } if ((const void*)expected == (const void*)actual) @@ -1515,7 +1764,15 @@ void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, RETURN_IF_FAIL_OR_IGNORE; - if ((elements == 0) || (length == 0)) + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + if (length == 0) { UnityPrintPointlessAndBail(); } @@ -1623,10 +1880,96 @@ UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) } #endif +#ifdef UNITY_INCLUDE_PRINT_FORMATTED + +/*----------------------------------------------- + * printf length modifier helpers + *-----------------------------------------------*/ + +enum UnityLengthModifier { + UNITY_LENGTH_MODIFIER_NONE, + UNITY_LENGTH_MODIFIER_LONG_LONG, + UNITY_LENGTH_MODIFIER_LONG, +}; + +#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \ +do { \ + switch (LENGTH_MOD) \ + { \ + case UNITY_LENGTH_MODIFIER_LONG_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_NONE: \ + default: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \ + break; \ + } \ + } \ +} while (0) + +static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length) +{ + enum UnityLengthModifier length_mod; + switch (pch[0]) + { + case 'l': + { + if (pch[1] == 'l') + { + *length = 2; + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + } + else + { + *length = 1; + length_mod = UNITY_LENGTH_MODIFIER_LONG; + } + break; + } + case 'h': + { + // short and char are converted to int + length_mod = UNITY_LENGTH_MODIFIER_NONE; + if (pch[1] == 'h') + { + *length = 2; + } + else + { + *length = 1; + } + break; + } + case 'j': + case 'z': + case 't': + case 'L': + { + // Not supported, but should gobble up the length specifier anyway + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 1; + break; + } + default: + { + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 0; + } + } + return length_mod; +} + /*----------------------------------------------- * printf helper function *-----------------------------------------------*/ -#ifdef UNITY_INCLUDE_PRINT_FORMATTED static void UnityPrintFVA(const char* format, va_list va) { const char* pch = format; @@ -1641,12 +1984,17 @@ static void UnityPrintFVA(const char* format, va_list va) if (pch != NULL) { + int length_mod_size; + enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size); + pch += length_mod_size; + switch (*pch) { case 'd': case 'i': { - const int number = va_arg(va, int); + UNITY_INT number; + UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int); UnityPrintNumber((UNITY_INT)number); break; } @@ -1661,21 +2009,31 @@ static void UnityPrintFVA(const char* format, va_list va) #endif case 'u': { - const unsigned int number = va_arg(va, unsigned int); - UnityPrintNumberUnsigned((UNITY_UINT)number); + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UnityPrintNumberUnsigned(number); break; } case 'b': { - const unsigned int number = va_arg(va, unsigned int); + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; UNITY_OUTPUT_CHAR('0'); UNITY_OUTPUT_CHAR('b'); - UnityPrintMask(mask, (UNITY_UINT)number); + UnityPrintMask(mask, number); break; } case 'x': case 'X': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex(number, 8); + break; + } case 'p': { const unsigned int number = va_arg(va, unsigned int); @@ -1848,7 +2206,7 @@ void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int /*-----------------------------------------------*/ void UnitySetTestFile(const char* filename) { - Unity.TestFile = filename; + Unity.TestFile = filename; } /*-----------------------------------------------*/ diff --git a/tools/vendor/ceedling/vendor/unity/src/unity.h b/tools/vendor/ceedling/vendor/unity/src/unity.h index 338df0b5..2785c728 100644 --- a/tools/vendor/ceedling/vendor/unity/src/unity.h +++ b/tools/vendor/ceedling/vendor/unity/src/unity.h @@ -89,7 +89,7 @@ void verifyTest(void); * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script * Parameterized Tests - * - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing + * - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing * Tests with Arguments * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity @@ -105,17 +105,27 @@ void verifyTest(void); #define TEST_MESSAGE(message) UnityMessage((message), __LINE__) #define TEST_ONLY() #ifdef UNITY_INCLUDE_PRINT_FORMATTED -#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), __VA_ARGS__) +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__) #endif /* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ #define TEST_PASS() TEST_ABORT() -#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while(0) +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) -/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out - * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */ -#define TEST_FILE(a) +/*------------------------------------------------------- + * Build Directives + *------------------------------------------------------- + + * These macros do nothing, but they are useful for additional build context. + * Tools (like Ceedling) can scan for these directives and make use of them for + * per-test-executable #include search paths and linking. */ + +/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */ +#define TEST_SOURCE_FILE(a) + +/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */ +#define TEST_INCLUDE_PATH(a) /*------------------------------------------------------- * Test Asserts (simple) @@ -337,9 +347,16 @@ void verifyTest(void); /* Floating Point (If Enabled) */ #define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) #define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) #define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) #define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) #define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) #define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) #define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) @@ -351,9 +368,16 @@ void verifyTest(void); /* Double (If Enabled) */ #define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) #define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) #define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) #define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) #define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) #define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) #define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) @@ -607,8 +631,14 @@ void verifyTest(void); /* Floating Point (If Enabled) */ #define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) #define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) #define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) #define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) #define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) #define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) #define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) @@ -621,8 +651,14 @@ void verifyTest(void); /* Double (If Enabled) */ #define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) #define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) #define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) #define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) #define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) #define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) #define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) diff --git a/tools/vendor/ceedling/vendor/unity/src/unity_internals.h b/tools/vendor/ceedling/vendor/unity/src/unity_internals.h index 2c91b6db..9f89eda9 100644 --- a/tools/vendor/ceedling/vendor/unity/src/unity_internals.h +++ b/tools/vendor/ceedling/vendor/unity/src/unity_internals.h @@ -52,12 +52,32 @@ #define UNITY_NORETURN [[ noreturn ]] #endif #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #include - #define UNITY_NORETURN noreturn + #if defined(_WIN32) && defined(_MSC_VER) + /* We are using MSVC compiler on Windows platform. */ + /* Not all Windows SDKs supports , but compiler can support C11: */ + /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ + /* Not sure, that Mingw compilers has Windows SDK headers at all. */ + #include + #endif + + /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ + /* Mingw GCC should work without that fixes. */ + /* Based on: */ + /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ + /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ + #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) + /* Based on tests and: */ + /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ + /* https://en.cppreference.com/w/c/language/_Noreturn */ + #define UNITY_NORETURN _Noreturn + #else /* Using newer Windows SDK or not MSVC compiler */ + #include + #define UNITY_NORETURN noreturn + #endif #endif #endif #ifndef UNITY_NORETURN - #define UNITY_NORETURN UNITY_FUNCTION_ATTR(noreturn) + #define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__) #endif /*------------------------------------------------------- @@ -194,6 +214,8 @@ #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* #endif +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + /*------------------------------------------------------- * Float Support *-------------------------------------------------------*/ @@ -287,10 +309,10 @@ typedef UNITY_FLOAT_TYPE UNITY_FLOAT; #ifdef UNITY_USE_FLUSH_STDOUT /* We want to use the stdout flush utility */ #include - #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) #else /* We've specified nothing, therefore flush should just be ignored */ - #define UNITY_OUTPUT_FLUSH() + #define UNITY_OUTPUT_FLUSH() (void)0 #endif #else /* If defined as something else, make sure we declare it here so it's ready for use */ @@ -302,11 +324,11 @@ typedef UNITY_FLOAT_TYPE UNITY_FLOAT; #ifndef UNITY_OUTPUT_FLUSH #define UNITY_FLUSH_CALL() #else -#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() #endif #ifndef UNITY_PRINT_EOL -#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') #endif #ifndef UNITY_OUTPUT_START @@ -365,19 +387,19 @@ typedef UNITY_FLOAT_TYPE UNITY_FLOAT; #endif #ifndef UNITY_EXEC_TIME_START -#define UNITY_EXEC_TIME_START() do{}while(0) +#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0) #endif #ifndef UNITY_EXEC_TIME_STOP -#define UNITY_EXEC_TIME_STOP() do{}while(0) +#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0) #endif #ifndef UNITY_TIME_TYPE -#define UNITY_TIME_TYPE UNITY_UINT +#define UNITY_TIME_TYPE UNITY_UINT #endif #ifndef UNITY_PRINT_EXEC_TIME -#define UNITY_PRINT_EXEC_TIME() do{}while(0) +#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0) #endif /*------------------------------------------------------- @@ -516,9 +538,9 @@ void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int #define UNITY_SET_DETAIL(d1) #define UNITY_SET_DETAILS(d1,d2) #else -#define UNITY_CLR_DETAILS() { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } -#define UNITY_SET_DETAIL(d1) { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } -#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } +#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0) #ifndef UNITY_DETAIL1_NAME #define UNITY_DETAIL1_NAME "Function" @@ -648,12 +670,25 @@ void UnityAssertFloatsWithin(const UNITY_FLOAT delta, const char* msg, const UNITY_LINE_TYPE lineNumber); -void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, - UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, - const UNITY_UINT32 num_elements, +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags); + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); void UnityAssertFloatSpecial(const UNITY_FLOAT actual, const char* msg, @@ -668,12 +703,25 @@ void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, const char* msg, const UNITY_LINE_TYPE lineNumber); -void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, - UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, - const UNITY_UINT32 num_elements, +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags); + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, const char* msg, @@ -719,19 +767,38 @@ extern const char UnityStrErrShorthand[]; #define TEST_ABORT() return #endif +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS + #ifdef __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #define UNITY_SUPPORT_VARIADIC_MACROS + #endif + #endif +#endif + /* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ #ifndef RUN_TEST -#ifdef __STDC_VERSION__ -#if __STDC_VERSION__ >= 199901L -#define UNITY_SUPPORT_VARIADIC_MACROS -#endif -#endif #ifdef UNITY_SUPPORT_VARIADIC_MACROS #define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) #define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) #endif #endif +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES + #ifdef UNITY_SUPPORT_VARIADIC_MACROS + #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) + #define TEST_CASE(...) + #endif + #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) + #define TEST_RANGE(...) + #endif + #if !defined(TEST_MATRIX) && !defined(UNITY_EXCLUDE_TEST_MATRIX) + #define TEST_MATRIX(...) + #endif + #endif +#endif + /* If we can't do the tricky version, we'll just have to require them to always include the line number */ #ifndef RUN_TEST #ifdef CMOCK @@ -786,7 +853,7 @@ int UnityTestMatches(void); * Test Asserts *-------------------------------------------------------*/ -#define UNITY_TEST_ASSERT(condition, line, message) do {if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));}} while(0) +#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message)); } } while (0) #define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message)) #define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message)) #define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (UNITY_LINE_TYPE)(line), (message)) @@ -889,7 +956,7 @@ int UnityTestMatches(void); #define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) #define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) #define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) #define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) #define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) #define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) @@ -995,9 +1062,16 @@ int UnityTestMatches(void); #ifdef UNITY_EXCLUDE_FLOAT #define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) @@ -1008,9 +1082,16 @@ int UnityTestMatches(void); #define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #else #define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) #define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) -#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray(UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) #define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) #define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) #define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) @@ -1023,9 +1104,16 @@ int UnityTestMatches(void); #ifdef UNITY_EXCLUDE_DOUBLE #define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) @@ -1036,9 +1124,16 @@ int UnityTestMatches(void); #define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #else #define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) #define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) -#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) #define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) #define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) #define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) diff --git a/tools/waf-tools/doxygen.py b/tools/waf-tools/doxygen.py index b0ebcd7b..ea6d4929 100644 --- a/tools/waf-tools/doxygen.py +++ b/tools/waf-tools/doxygen.py @@ -57,7 +57,7 @@ def runnable_status(self): key, val = i_txt.split("=") self.doxygen_config[key] = val.split(" ") except ValueError: - # not simple parseable, ignore, as we are only interested + # not simple parsable, ignore, as we are only interested # in a few simple values pass self.doxygen_input = [] # pylint: disable=attribute-defined-outside-init diff --git a/tools/waf-tools/f_guidelines.py b/tools/waf-tools/f_guidelines.py index 208d8ee2..68ba7c8c 100644 --- a/tools/waf-tools/f_guidelines.py +++ b/tools/waf-tools/f_guidelines.py @@ -54,6 +54,7 @@ # pylint: disable-msg=invalid-name # pylint: disable=no-member +# pylint: disable=too-many-lines TOOLDIR = os.path.dirname(os.path.realpath(__file__)) @@ -102,6 +103,7 @@ class GuidelineViolations(AutoNumberGuidelineErrors): RST_MISSING_INCLUDE = () RST_ORPHAN = () RST_HEADING = () + C_UNIT_TEST_DIRECTIVES = () def options(opt): @@ -278,7 +280,7 @@ def keyword(self): class encoding(Task.Task): """Class to implement the utf-8 coding check - A task is only executed if a file is changed. + . """ @@ -449,7 +451,7 @@ def keyword(self): class trailing_whitespace(Task.Task): """Class to implement the trailing whitespace check - A task is only executed if a file is changed. + . """ @@ -515,7 +517,7 @@ def keyword(self): class tabs(Task.Task): """Class to implement running the trailing whitespace check - A task is only executed if a file is changed. + . """ @@ -548,7 +550,7 @@ def run(self): for err in errors: Logs.error( f"{self.rule_name}: File {self.inputs[0].abspath()}:{err[1]} " - f"forbidden tabs found" + "forbidden tabs found" ) return GuidelineViolations.GENERAL_TABS.value return GuidelineViolations.NO_VIOLATION.value @@ -1039,7 +1041,7 @@ def keyword(self): class c_check_comment_style(Task.Task): """Class to implement c comment style check - A task is only executed if a file is changed. + . """ @@ -1273,7 +1275,7 @@ def keyword(self): class rst_check_heading(Task.Task): """Class to implement the rst heading check - A task is only executed if a file is changed. + . """ @@ -1460,11 +1462,7 @@ def keyword(self): class rst_check_orphan(Task.Task): - """Class to implement declaration of rst file orphans - - A task is only executed if a file is changed - - """ + """Class to implement declaration of rst file orphans""" # color (string): color in which the command line is displayed in the terminal color = "BLUE" @@ -1494,7 +1492,7 @@ def run(self): if error != GuidelineViolations.NO_VIOLATION: Logs.error( f"{self.rule_name}: File: {self.inputs[0].abspath()}:" - f" The first line has to be ':orphan:'" + " The first line has to be ':orphan:'" ) return GuidelineViolations.RST_ORPHAN.value return GuidelineViolations.NO_VIOLATION.value @@ -1522,6 +1520,100 @@ def keyword(self): return f"Checking rst orphan ({self.rule_name})" +class sort_unit_testing_directives(Task.Task): + """Class to implement declaration of rst file orphans""" + + # color (string): color in which the command line is displayed in the terminal + color = "BLUE" + + before = ["clang_format"] + + def run(self): + """calls test function and prints the error message + + A list (in self.input) containing the path of the to be + checked file is passed as first argument in the task generation. The + second argument self.rule_name contains the name of the style guide rule. + run calls the test function and passes the first line of the to be checked + file. Depending on the return value of the test function an error + message with the filename is printed. + + Returns: + int: + If no violation is found the value of + GuidelineViolations.NO_VIOLATION is returned. If the file does not + have orphan in the first line the value of + GuidelineViolations.RST_ORPHAN is returned + """ + error = self.test(self.inputs[0].read()) + if error: + print(error) + Logs.error( + f"File: {self.inputs[0].abspath()}: unit testing directives are not sorted" + ) + return GuidelineViolations.C_UNIT_TEST_DIRECTIVES.value + return GuidelineViolations.NO_VIOLATION.value + + @staticmethod + def test(txt: str): + """Implements check that the unit testing framework directives in a + file are correctly sorted. + + Args: + txt (string): first line of the to be checked file + + Returns: + fixed list of directives + """ + re_test_files = re.compile(r"TEST_SOURCE_FILE\(\"(.*)\"\)") + re_include_paths = re.compile(r"TEST_INCLUDE_PATH\(\"(.*)\"\)") + test_files = [] + include_paths = [] + txt_input = txt.splitlines() + for i, line in enumerate(txt_input): + m = re_test_files.match(line) + if m: + test_files.append((m.group(0), i)) + m = re_include_paths.match(line) + if m: + include_paths.append((m.group(0), i)) + # if there are no directives, just return early + if not test_files and not include_paths: + return 0 + + error = 0 + # check that the order is ok: sources, then includes, and that there is an + # empty line between these + test_files_line_nr = [i[1] for i in test_files] + include_paths_line_nr = [i[1] for i in include_paths] + if not test_files_line_nr == sorted(test_files_line_nr): + error = 1 + + if not include_paths_line_nr == sorted(include_paths_line_nr): + error = 2 + + if ( + test_files_line_nr + and include_paths_line_nr + and not (max(test_files_line_nr) - min(include_paths_line_nr)) == -2 + ): + error = 3 + + # check that each list is sorted alphabetically + if not test_files == sorted(test_files): + print(f"Test files should be sorted like this:\n{sorted(test_files)}") + error += 4 + if not include_paths == sorted(include_paths): + print(f"Includes should be sorted like this:\n{sorted(include_paths)}") + error += 5 + + return error + + def keyword(self): + """Displayed keyword for check""" + return "Checking sorting of unit testing directives" + + @TaskGen.feature("guidelines") def process_guidelines(self): # pylint: disable=too-many-statements,too-many-branches,too-many-locals @@ -1924,10 +2016,20 @@ def process_guidelines(self): for rst_file in rst_to_check_orphan: self.create_task("rst_check_orphan", src=rst_file, rule_name=rn) + # the unit testing framework directives shall be sorted + unit_test_files = self.bld.path.ant_glob("tests/unit/**/*.c", quiet=True) + for unit_test_file in unit_test_files: + self.create_task( + "sort_unit_testing_directives", src=unit_test_file, rule_name=rn + ) + def check_guidelines(ctx): """Calls the guidelines check""" rules_node = ctx.path.find_node("conf/guidelines/rules.json") + if validate_rules_file(rules_node.read_json()): + ctx.fatal("Rules file is not sorted.") + if not rules_node: ctx.fatal("Could not find guidelines file") rules = json.loads(rules_node.read()) @@ -1944,3 +2046,26 @@ class guidelines_context(BuildContext): # inject command into top-level wscript. This requires that g_module is available if Context.g_module: Context.g_module.__dict__["check_guidelines"] = check_guidelines + + +def validate_rules_file(rules: dict, err: int = 0) -> int: + """validate that the rules file has a consistent ordering""" + prev_err = err + for k, v in rules.items(): + if isinstance(v, dict): + new_err = validate_rules_file(v, err) + if new_err != prev_err: + err = new_err + elif isinstance(v, list): + if k in ("text", "sections", "regex"): + continue + try: # only sort lists of simple types + if not v == sorted(v): + err += 1 + Logs.error( + f"List '{json.dumps(v)}' not sorted.\n" + f"Use\n {json.dumps(sorted(v))}\n" + ) + except TypeError: + pass + return err diff --git a/tools/waf-tools/f_hcg.py b/tools/waf-tools/f_hcg.py index c8edb6ed..4a44fa5f 100644 --- a/tools/waf-tools/f_hcg.py +++ b/tools/waf-tools/f_hcg.py @@ -86,12 +86,12 @@ def parse_xml(self): self.removes.append(value_os.text) continue for hcg_setting in self.root.iter(element.tag): - for hw_type in list(hcg_setting[0]): - if "_GCC" in hw_type.tag: + for hardware_type in list(hcg_setting[0]): + if "_GCC" in hardware_type.tag: # we are not interested in GCC specific files as we are # using TI ARM CGT continue - for value_hal in list(hw_type): + for value_hal in list(hardware_type): if value_hal.tag == "PATH": if value_hal.text is not None: if value_hal.text.endswith("HL_sys_main.c"): diff --git a/tools/waf-tools/f_helpers.py b/tools/waf-tools/f_helpers.py index a2118c1e..0b9c75db 100644 --- a/tools/waf-tools/f_helpers.py +++ b/tools/waf-tools/f_helpers.py @@ -57,8 +57,8 @@ def f_validator( ): """Returns a validator with resolved relative references""" schema_path = pathlib.Path(schema_path).resolve().as_posix() - with open(schema_path, mode="r", encoding="utf-8") as filepointer: - schema = json.load(filepointer) + with open(schema_path, mode="r", encoding="utf-8") as f: + schema = json.load(f) if Utils.is_win32: uri_template = "file:///{0}" else: diff --git a/tools/waf-tools/f_lauterbach.py b/tools/waf-tools/f_lauterbach.py index c187af47..aa1735f9 100644 --- a/tools/waf-tools/f_lauterbach.py +++ b/tools/waf-tools/f_lauterbach.py @@ -65,7 +65,7 @@ def options(opt): """Lauterbach waf tool configuration options""" - homedrive = os.getenv("HOMEDRIVE", os.path.join("C", os.sep)) + homedrive = os.getenv("HOMEDRIVE", "C:") lauterbach_installation_directory = [ os.path.join(homedrive, os.sep, "T32-tms"), os.path.join(homedrive, os.sep, "T32"), @@ -95,13 +95,13 @@ def configure(conf): ) conf.find_program("t32marm", var="T32MARM", mandatory=False) if not conf.env.T32MARM: - lauterbach_bin_diretories = [ + lauterbach_bin_directories = [ os.path.join(i, "bin", "windows64") for i in conf.options.LAUTERBACH_BASE ] conf.find_program( "t32marm", var="T32MARM", - path_list=lauterbach_bin_diretories, + path_list=lauterbach_bin_directories, mandatory=False, ) conf.end_msg(conf.env.get_flat("T32MARM")) @@ -121,6 +121,11 @@ def configure(conf): t32_cmm = conf.path.find_node( os.path.join(os.path.join("tools", "debugger", "lauterbach", "t32.cmm.in")) ) + load_macro_values = conf.path.find_node( + os.path.join( + os.path.join("tools", "debugger", "lauterbach", "load_macro_values.cmm.in") + ) + ) t32_root = conf.root.find_node(conf.env.FILECVT[0]).parent.abspath() if t32_root.endswith(os.sep): @@ -147,6 +152,12 @@ def configure(conf): t32_cmm_node = conf.path.get_bld().make_node("t32.cmm") t32_cmm_node.write(t32_cmm) + load_macro_values = load_macro_values.read() + replacements = "" + load_macro_values = load_macro_values.replace("@MACROS_AND_VALUES@", replacements) + load_macro_values_node = conf.path.get_bld().make_node("load_macro_values.cmm") + load_macro_values_node.write(load_macro_values) + path = os.path.join(conf.path.get_bld().abspath(), "run_t32marm.lnk") shell = win32com.client.Dispatch("WScript.Shell") diff --git a/tools/waf-tools/f_miniconda_env.py b/tools/waf-tools/f_miniconda_env.py index 89d4c9a6..7503a224 100644 --- a/tools/waf-tools/f_miniconda_env.py +++ b/tools/waf-tools/f_miniconda_env.py @@ -66,6 +66,7 @@ def configure(conf): CONDA_BASE = [ os.path.join(os.environ["USERPROFILE"], "miniconda3"), os.path.join(os.environ["LOCALAPPDATA"], "Continuum", "miniconda3"), + os.path.join(os.environ["LOCALAPPDATA"], "miniconda3"), os.path.join(os.environ["ProgramData"], "Miniconda3"), os.path.join(os.environ["SystemDrive"], os.sep, "miniconda3"), ] diff --git a/tools/waf-tools/f_sphinx_build.py b/tools/waf-tools/f_sphinx_build.py index da1f4875..a4cab968 100644 --- a/tools/waf-tools/f_sphinx_build.py +++ b/tools/waf-tools/f_sphinx_build.py @@ -54,27 +54,27 @@ class sphinx_task(Task.Task): # pylint: disable=invalid-name .. graphviz:: :caption: Input-output relation for conf.py - :name: confpy-to-docs + :name: conf_py-to-docs digraph ASM_TO_OBJECT { compound=true; rankdir=LR; nd_sphinx [label="sphinx_build", style=filled, fillcolor=green]; - nd_confpy [label="conf.py", style=filled]; - nd_outdir [label="OUTDIR/index.html", style=filled]; + nd_conf_py [label="conf.py", style=filled]; + nd_out_dir [label="OUTDIR/index.html", style=filled]; subgraph cluster_cmd { label = "Command Line"; rank=same; - nd_buildername [label="BUILDERNAME"]; + nd_builder_name [label="BUILDERNAME"]; nd_version [label="VERSION"]; nd_release [label="RELEASE"]; nd_dot [label="DOT"]; nd_doctreedir [label="DOCTREEDIR"]; nd_srcdir [label="SRCDIR"]; } - nd_sphinx -> nd_buildername [lhead=cluster_cmd]; - nd_confpy -> nd_buildername [lhead=cluster_cmd]; - nd_buildername -> nd_outdir [ltail=cluster_cmd]; + nd_sphinx -> nd_builder_name [lhead=cluster_cmd]; + nd_conf_py -> nd_builder_name [lhead=cluster_cmd]; + nd_builder_name -> nd_out_dir [ltail=cluster_cmd]; } """ @@ -86,7 +86,7 @@ class sphinx_task(Task.Task): # pylint: disable=invalid-name def run(self): """Creates a command line processed by ``Utils.subprocess.Popen`` in - order to build the sphinx documentation. See :numref:`confpy-to-docs` + order to build the sphinx documentation. See :numref:`conf_py-to-docs` for a simplified representation""" verbosity = "" if Logs.verbose: @@ -138,7 +138,7 @@ def check_output_spelling(self, std_out, std_err): # if the output line contains ".rst:" it indicates that an error # has been found. The path is relative to the source directory # therefore we need to construct the path to the source file with - # the error to generate a meaningfull errormessage + # the error to generate a meaningful error message match = re_err.search(line) if match: err_bit += 1 @@ -249,14 +249,14 @@ def apply_sphinx(self): inputs.append(node) # get sphinx config (conf.py) and derive the srcdir from it. - if not getattr(self, "confpy", None): + if not getattr(self, "conf_py", None): raise ValueError("Path to the sphinx config must be specified ('conf.py').") - src_dir = self.confpy.parent.abspath() + src_dir = self.conf_py.parent.abspath() # set the output directory - if not getattr(self, "outdir", None): - raise ValueError("outdir must be specified.") - self.outdir_node = self.path.find_or_declare(getattr(self, "outdir")).get_bld() + if not getattr(self, "out_dir", None): + raise ValueError("out_dir must be specified.") + self.out_dir_node = self.path.find_or_declare(getattr(self, "out_dir")).get_bld() # add builders, build at least html documentation builders = [] @@ -269,7 +269,7 @@ def apply_sphinx(self): outfile = self.path.get_bld().make_node(builder) outfile.write(builder) builder_task = self.create_task("sphinx_task", inputs + [outfile]) - builder_task.inputs.append(self.confpy) + builder_task.inputs.append(self.conf_py) builder_task.env["BUILDERNAME"] = builder builder_task.env["SRCDIR"] = src_dir builder_task.env["CONFDIR"] = src_dir @@ -280,17 +280,17 @@ def apply_sphinx(self): builder_task.env["DOCTREEDIR"] = getattr( self, "doctreedir", - os.path.join(self.outdir_node.abspath(), ".doctrees"), + os.path.join(self.out_dir_node.abspath(), ".doctrees"), ) else: builder_task.env["DOCTREEDIR"] = os.path.join( - self.outdir_node.abspath(), f".doctrees-{builder}" + self.out_dir_node.abspath(), f".doctrees-{builder}" ) builder_task.no_errcheck_out = True - builder_task.env["OUTDIR"] = self.outdir_node.abspath() + builder_task.env["OUTDIR"] = self.out_dir_node.abspath() builder_task.env["VERSION"] = f"version={self.env.VERSION}" builder_task.env["RELEASE"] = f"release={self.env.VERSION}" - builder_task.outputs.append(self.outdir_node) + builder_task.outputs.append(self.out_dir_node) def configure(conf): diff --git a/tools/waf-tools/f_ti_arm_cgt.py b/tools/waf-tools/f_ti_arm_cgt.py index a5fee404..a48fc07a 100644 --- a/tools/waf-tools/f_ti_arm_cgt.py +++ b/tools/waf-tools/f_ti_arm_cgt.py @@ -1392,7 +1392,7 @@ class print_swi(Task.Task): # pylint: disable=invalid-name def run(self): """combines all swi information in one file""" - # get jumptable information from asm file + # get jump-table information from asm file txt = self.inputs[0].read().splitlines() found = False table_entry = 0 @@ -1439,6 +1439,64 @@ def print_swi_aliases(self): ) +class get_stack(Task.Task): # pylint: disable=invalid-name + """gathers all swi information in one file""" + + after = ["link_task"] + + def run(self): + """Gathers the stack usage information""" + + def parse(txt, line_number): + stack_usage_re = re.compile(r"Stack usage:\s+(\d+)\s+bytes") + out = {"Stack usage": -1, "Called functions": [], "Indirect calls": False} + found_stack = False + found_functions = False + called_functions = [] + for line in txt[line_number:]: + if not found_stack: + m = stack_usage_re.match(line) + if m and m.group(1): + out["Stack usage"] = int(m.group(1)) + found_stack = True + elif line == "Function contains indirect calls.": + out["Indirect calls"] = True + elif line == "Called functions:": + found_functions = True + elif found_functions: + if not line: + break + called_functions.append(line.strip()) + out["Called functions"] = called_functions + return out + + out = {} + func_re = re.compile(r"\|\s+FUNCTION:\s+(\w+)\s+|") + srcs = self.generator.bld.bldnode.ant_glob("**/*.aux", quiet=True) + for src in srcs: + txt_lines = src.read().splitlines() + for i, line in enumerate(txt_lines): + m = func_re.match(line) + if m and m.group(1): + out[m.group(1)] = parse(txt_lines, i) + + self.outputs[0].write_json(out) + + +@TaskGen.feature("cprogram") +@TaskGen.after_method("process_source") +def test_exec_fun(self): + """get stack usage""" + tgt = os.path.join( + self.bld.bldnode.abspath(), f"{self.env.APPNAME.lower()}.stacks.json" + ) + self.create_task( + "get_stack", + src=self.link_task.inputs, + tgt=self.path.find_or_declare(tgt), + ) + + @conf def find_armcl(conf): # pylint: disable-msg=redefined-outer-name """configures the compiler, determines the compiler version, and sets the diff --git a/tools/waf-tools/f_unit_test.py b/tools/waf-tools/f_unit_test.py index aa76c847..b8585654 100644 --- a/tools/waf-tools/f_unit_test.py +++ b/tools/waf-tools/f_unit_test.py @@ -46,7 +46,7 @@ import os -from waflib import Task, TaskGen +from waflib import Task, TaskGen, Utils class ceedling(Task.Task): # pylint: disable=invalid-name,too-few-public-methods @@ -115,12 +115,17 @@ def configure(conf): # get build directory conf.env.append_unique("CEEDLING_OPTIONS", ["verbosity[3]"]) conf.env.append_unique("CEEDLING_TEST_OPTIONS", ["test:all"]) - conf.env.append_unique("CEEDLING_COVERAGE_OPTIONS", ["gcov:all", "utils:gcov"]) - ceedling_project_file = conf.path.find_node( - os.path.join("conf", "unit", "project.yml") - ) + conf.env.append_unique("CEEDLING_COVERAGE_OPTIONS", ["gcov:all"]) + + ceedling_project_file_dir = conf.path.find_dir(os.path.join("conf", "unit")) + if Utils.is_win32: + ext = "cmd" + ceedling_project_file = ceedling_project_file_dir.find_node("project_win32.yml") + else: + ext = "sh" + ceedling_project_file = ceedling_project_file_dir.find_node("project_posix.yml") ceedling_cmd_file = conf.path.find_node( - os.path.join("conf", "unit", "ceedling.cmd") + os.path.join("conf", "unit", f"ceedling.{ext}") ) conf.env.CEEDLING_MAIN_PROJECT_FILE = ceedling_project_file.relpath() conf.env.CEEDLING_CMD_FILE = ceedling_cmd_file.relpath() diff --git a/tools/waf-tools/f_vscode.py b/tools/waf-tools/f_vscode.py index f7c4bfa9..15e8b991 100644 --- a/tools/waf-tools/f_vscode.py +++ b/tools/waf-tools/f_vscode.py @@ -72,6 +72,7 @@ def configure(conf): # pylint: disable=too-many-statements,too-many-branches - configure a project if code was found""" # create a VS Code workspace if code is installed on this platform is_remote_session = False + conf.start_msg("Checking for program 'code'") if Utils.is_win32: conf.find_program("code", mandatory=False) if not conf.env.CODE: @@ -92,9 +93,10 @@ def configure(conf): # pylint: disable=too-many-statements,too-many-branches code_server_dir = os.path.join(os.path.expanduser("~"), ".vscode-server") is_remote_session = os.path.isdir(code_server_dir) conf.msg("Found 'vscode-server' (remote session)", code_server_dir) - if not (conf.env.CODE or is_remote_session): + conf.end_msg(False) return + conf.end_msg(conf.env.get_flat("CODE") or "remote") conf.start_msg("Creating workspace") vscode_dir = conf.path.make_node(".vscode") vscode_dir.mkdir() @@ -236,13 +238,16 @@ def configure(conf): # pylint: disable=too-many-statements,too-many-branches Path(str(conf.root.find_node(i).path_from(conf.path))).as_posix() for i in conf.env.INCLUDES_RTOS ] + afe_includes = [ + Path(str(conf.root.find_node(i).path_from(conf.path))).as_posix() + for i in conf.env.INCLUDES_AFE + ] c_cpp_properties = template.render( ARMCL=Path(conf.env.CC[0]).as_posix(), RTOS=conf.env.RTOS_NAME[0], RTOS_INCLUDES=rtos_includes, BALANCING_STRATEGY=conf.env.balancing_strategy, - AFE_MANUFACTURER=conf.env.afe_manufacturer, - AFE_IC=conf.env.afe_ic, + AFE_INCLUDES=afe_includes, TEMPERATURE_SENSOR_MANUFACTURER=conf.env.temperature_sensor_manuf, TEMPERATURE_SENSOR_MODEL=conf.env.temperature_sensor_model, TEMPERATURE_SENSOR_METHOD=conf.env.temperature_sensor_meth, diff --git a/wscript b/wscript index aeb74415..a14884cc 100644 --- a/wscript +++ b/wscript @@ -53,8 +53,10 @@ import shlex import sys import tarfile import linecache +import stat from binascii import hexlify import dataclasses +from typing import Union import jsonschema from waflib import Build, Configure, Context, Errors, Logs, Options, Scripting, Utils @@ -72,13 +74,13 @@ Configure.autoconfig = 1 out = "build" # pylint:disable=invalid-name """output directory""" top = "." # pylint:disable=invalid-name -"""waf top directory""" +"""Waf top directory""" APPNAME = "foxBMS" -"""name of the application. This is used in various waf functions""" +"""name of the application. This is used in various Waf functions""" -VERSION = "1.5.1" -"""version of the application. This is used in various waf functions. This +VERSION = "1.6.0" +"""version of the application. This is used in various Waf functions. This version must match the version number defined in ``macros.txt``. Otherwise a configuration error is thrown.""" @@ -101,12 +103,13 @@ class FoxBMSDefine: """container for defines""" name: str - value: int = 0 + value: Union[int, str, None] = 0 AFE_SETUP = { "fsm": FoxBMSDefine("FOXBMS_AFE_DRIVER_TYPE_FSM", 0), "no-fsm": FoxBMSDefine("FOXBMS_AFE_DRIVER_TYPE_NO_FSM", 0), + "afe-ic": FoxBMSDefine("", None), } for target_type, target_val in ALL_VARIANTS.items(): @@ -143,13 +146,13 @@ for target_type, target_val in ALL_VARIANTS.items(): contexts = old_contexts -BLD_VARIANTS = [] -CLN_VARIANTS = [] +BUILD_VARIANTS = [] +CLEAN_VARIANTS = [] # build and clean variants exist for all commands for target_type, target_val in ALL_VARIANTS.items(): for var in target_val: - BLD_VARIANTS.append(f"build_{var}") - CLN_VARIANTS.append(f"clean_{var}") + BUILD_VARIANTS.append(f"build_{var}") + CLEAN_VARIANTS.append(f"clean_{var}") DIST_EXCLUDE = ( f"{out}/** **/.git **/.gitignore .gitlab/** **/.gitattributes " @@ -185,7 +188,8 @@ def version_consistency_checker(ctx): ) repo_url = "https://github.com/foxBMS/foxbms-2" must_include_version = [ - f"curl -Ss -L -o foxbms-2-v{VERSION}.zip {repo_url}/archive/v{VERSION}.zip", + f"curl --silent --show-error -L -o foxbms-2-v{VERSION}.zip " + f"{repo_url}/archive/v{VERSION}.zip", f"tar -x -f foxbms-2-v{VERSION}.zip", f"ren foxbms-2-{VERSION} foxbms-2", ] @@ -336,6 +340,7 @@ def configure(conf): # pylint: disable=too-many-statements,too-many-branches ) def full_build(bld): + bld.env.APPNAME = "TEST_BUILD" c_fragment = "#include \n\nint main() {\n return 0;\n}\n" h_fragment = ( "#ifndef GENERAL_H_\n#define GENERAL_H_\n#include \n" @@ -449,15 +454,44 @@ def configure(conf): # pylint: disable=too-many-statements,too-many-branches # vendor/ic includes and foxBMS specific driver adaptions afe_ic_inc = slave_afe["ic"] afe_driver_type = "fsm" + afe_ic_d = None if slave_afe["manufacturer"] == "ltc": if slave_afe["ic"] in ("6804-1", "6811-1", "6812-1"): afe_ic_inc = "6813-1" + if slave_afe["ic"] == "6804-1": + afe_ic_d = "LTC_LTC6804_1" + elif slave_afe["ic"] == "6806": + afe_ic_d = "LTC_LTC6806" + elif slave_afe["ic"] == "6811-1": + afe_ic_d = "LTC_LTC6811_1" + elif slave_afe["ic"] == "6812-1": + afe_ic_d = "LTC_LTC6812_1" + elif slave_afe["ic"] == "6813-1": + afe_ic_d = "LTC_LTC6813_1" elif slave_afe["manufacturer"] == "nxp": + afe_driver_type = "no-fsm" if slave_afe["ic"] == "mc33775a": - afe_driver_type = "no-fsm" - + afe_ic_d = "NXP_MC33775A" + elif slave_afe["manufacturer"] == "adi": + afe_driver_type = "no-fsm" + if slave_afe["ic"] == "ades1830": + afe_ic_d = "ADI_ADES1830" + elif slave_afe["manufacturer"] == "debug": + if slave_afe["ic"] == "default": + afe_ic_d = "DEBUG_DEFAULT" + elif slave_afe["manufacturer"] == "maxim": + if slave_afe["ic"] == "max17852": + afe_ic_d = "MAX_MAX17852" + elif slave_afe["manufacturer"] == "ti": + if slave_afe["ic"] == "dummy": + afe_ic_d = "TI_DUMMY" + + if not afe_ic_d: + conf.fatal("AFE IC specific define not set.") # set the driver type implementation accordingly AFE_SETUP[afe_driver_type].value = 1 + AFE_SETUP["afe-ic"].name = "FOXBMS_AFE_DRIVER_" + afe_ic_d + AFE_SETUP["afe-ic"].value = 1 for _, i in AFE_SETUP.items(): conf.define(i.name, i.value) @@ -550,7 +584,7 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements if not bld.variant: bld.fatal( f"A {bld.cmd} variant must be specified. The build variants are: " - f"{', '.join(BLD_VARIANTS)}.\nFor more details run 'python " + f"{', '.join(BUILD_VARIANTS)}.\nFor more details run 'python " f"tools{os.sep}waf --help'" ) # we need to patch the build instructions for the Axivion build, and by @@ -625,7 +659,7 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements bld( features="subst", source=source, - target=source.name, + target="project.yml", is_copy=True, ) source = bld.path.find_node(bld.env.CEEDLING_CMD_FILE) @@ -634,21 +668,25 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements source=source, target=source.name, is_copy=True, + chmod=os.stat(source.abspath()).st_mode | stat.S_IEXEC, ) - bld( - source=os.path.join("conf", "hcg", "hcg.hcg"), - unit_test=True, - startup_hash=bld.path.find_node(os.path.join("src", "hal", "startup.hash")), - ) + if Utils.is_win32: + bld( + source=os.path.join("conf", "hcg", "hcg.hcg"), + unit_test=True, + startup_hash=bld.path.find_node( + os.path.join("src", "hal", "startup.hash") + ), + ) + else: + Logs.warn( + "HALCoGen not available. Assuming generated sources are available otherwise." + ) bld.add_group() bld(features="ceedling") if bld.variant == "docs": - # General documentation build - # There are two contexts defined. The first one copies the ``wscript`` files - # to the build directory with a ``.py`` extension to make the build scripts - # autodoc-able. - # At next the jinja2 templates generate the specific template files for documentation. + # The jinja2 templates generate the specific template files for documentation. # At next doxygen is run, to ensure that doxygen's xml output is build. # After that the regular documentation can be build using sphinx-build, which # now includes the build documentation as well as the API documentation from @@ -687,6 +725,7 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements bld.path.find_node(os.path.join("src", "app", "driver", "afe", "ltc", "common", "ltc_pec.c")), bld.path.find_node(os.path.join("src", "app", "driver", "afe", "ltc", "common", "ltc_pec.h")), bld.path.find_node(os.path.join("src", "app", "driver", "afe", "nxp", "mc33775a","vendor")), + bld.path.find_node(os.path.join("tests", "unit", "build")), ] _html_footer = bld.path.find_node(os.path.join("docs", "doxygen_footer.html")) _layout_file = bld.path.find_node(os.path.join("docs", "doxygen_layout.xml")) @@ -763,17 +802,42 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "developer-manual", "preface.rst"), os.path.join(doc_dir, "developer-manual", "public-release-process.rst"), os.path.join(doc_dir, "developer-manual", "software", "software-development-process.rst"), + os.path.join(doc_dir, "developer-manual", "software", "software-modifications.rst"), os.path.join(doc_dir, "developer-manual", "software", "software-programming-language.rst"), os.path.join(doc_dir, "developer-manual", "software", "software-testing.rst"), os.path.join(doc_dir, "developer-manual", "software", "software-tools.rst"), os.path.join(doc_dir, "developer-manual", "software", "software-verification.rst"), os.path.join(doc_dir, "developer-manual", "software-developer-manual.rst"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_batch_shell.rst"), os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_c.rst"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_general.rst"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_overview.rst"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_overview_c.csv"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_overview_general.csv"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_overview_python.csv"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_overview_rst.csv"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_overview_sh.csv"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_overview_yaml.csv"), os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_python.rst"), os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_rst.rst"), + os.path.join(doc_dir, "developer-manual", "style-guide", "guidelines_yaml.rst"), os.path.join(doc_dir, "developer-manual", "style-guide", "state-machines_how-to.rst"), os.path.join(doc_dir, "developer-manual", "style-guide", "style-guide.rst"), os.path.join(doc_dir, "general", "changelog.rst"), + os.path.join(doc_dir, "general", "commit-msgs", "next-release.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.0.0.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.0.1.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.0.2.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.1.0.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.1.1.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.1.2.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.2.0.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.2.1.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.3.0.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.4.0.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.4.1.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.5.0.txt"), + os.path.join(doc_dir, "general", "commit-msgs", "release-v1.5.1.txt"), os.path.join(doc_dir, "general", "license.rst"), os.path.join(doc_dir, "general", "license-tables", "license-info_ceedling.csv"), os.path.join(doc_dir, "general", "license-tables", "license-info_freertos.csv"), @@ -789,8 +853,8 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "general", "license-tables", "license-info_vs-code_extensions.csv"), os.path.join(doc_dir, "general", "license-tables", "license-info_waf-binary.csv"), os.path.join(doc_dir, "general", "license-tables", "license-info_waf-unit-tests.csv"), - os.path.join(doc_dir, "general", "license-tables", "license-packages-conda-env-spelling-build-strings.txt"), os.path.join(doc_dir, "general", "license-tables", "license-packages-conda-env-spelling.txt"), + os.path.join(doc_dir, "general", "license-tables", "license-packages-conda-env-spelling-build-strings.txt"), os.path.join(doc_dir, "general", "motivation.rst"), os.path.join(doc_dir, "general", "releases.csv"), os.path.join(doc_dir, "general", "releases.rst"), @@ -801,30 +865,148 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "general", "team-former.rst"), os.path.join(doc_dir, "getting-started", "first-steps-on-hardware.rst"), os.path.join(doc_dir, "getting-started", "getting-started.rst"), + os.path.join(doc_dir, "getting-started", "llvm-installation", "llvm-installation.rst"), + os.path.join(doc_dir, "getting-started", "mingw64-installation", "mingw64-installation.rst"), + os.path.join(doc_dir, "getting-started", "miniconda-installation", "conda-configuration.rst"), + os.path.join(doc_dir, "getting-started", "miniconda-installation", "miniconda-installation.rst"), os.path.join(doc_dir, "getting-started", "repository-structure.rst"), + os.path.join(doc_dir, "getting-started", "ruby-installation", "ruby-installation.rst"), os.path.join(doc_dir, "getting-started", "software-installation.rst"), os.path.join(doc_dir, "getting-started", "workspace.rst"), os.path.join(doc_dir, "hardware", "connectors.rst"), os.path.join(doc_dir, "hardware", "design-resources.rst"), os.path.join(doc_dir, "hardware", "hardware.rst"), - os.path.join(doc_dir, "hardware", "interfaces","maxim-max17841b-vx.x.x", "maxim-max17841b-v1.0.0.rst"), + os.path.join(doc_dir, "hardware", "interfaces", "ltc-ltc6820-vx.x.x", "ltc-ltc6820-changelog.rst"), + os.path.join(doc_dir, "hardware", "interfaces", "ltc-ltc6820-vx.x.x", "ltc-ltc6820-v1.0.3", "ltc-ltc6820-v1.0.3_isospi_connectors.csv"), + os.path.join(doc_dir, "hardware", "interfaces", "ltc-ltc6820-vx.x.x", "ltc-ltc6820-v1.0.3", "ltc-ltc6820-v1.0.3_master_connector.csv"), + os.path.join(doc_dir, "hardware", "interfaces", "ltc-ltc6820-vx.x.x", "ltc-ltc6820-v1.0.3.rst"), + os.path.join(doc_dir, "hardware", "interfaces", "maxim-max17841b-vx.x.x", "maxim-max17841b-changelog.rst"), + os.path.join(doc_dir, "hardware", "interfaces", "maxim-max17841b-vx.x.x", "maxim-max17841b-v1.0.0", "maxim-max17841b-v1.0.0_debug_connector.csv"), + os.path.join(doc_dir, "hardware", "interfaces", "maxim-max17841b-vx.x.x", "maxim-max17841b-v1.0.0", "maxim-max17841b-v1.0.0_master_connector.csv"), + os.path.join(doc_dir, "hardware", "interfaces", "maxim-max17841b-vx.x.x", "maxim-max17841b-v1.0.0", "maxim-max17841b-v1.0.0_uartrx_connectors.csv"), + os.path.join(doc_dir, "hardware", "interfaces", "maxim-max17841b-vx.x.x", "maxim-max17841b-v1.0.0", "maxim-max17841b-v1.0.0_uarttx_connectors.csv"), + os.path.join(doc_dir, "hardware", "interfaces", "maxim-max17841b-vx.x.x", "maxim-max17841b-v1.0.0.rst"), + os.path.join(doc_dir, "hardware", "interfaces", "nxp-mc33664-vx.x.x", "nxp-mc33664-changelog.rst"), + os.path.join(doc_dir, "hardware", "interfaces", "nxp-mc33664-vx.x.x", "nxp-mc33664-v1.0.2.rst"), + os.path.join(doc_dir, "hardware", "interfaces.rst"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-changelog.rst"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_can1.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_can2.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_debug.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_ethernet.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_extension.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_interface.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_interlock.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_isomon.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_rs485.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_sps.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "pinout", "ti-tms570lc4357-v1.1.1_supply_ext.csv"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "ti-tms570lc4357-v1.1.1_block_diagram.rst"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "ti-tms570lc4357-v1.1.1_functional_description.rst"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1", "ti-tms570lc4357-v1.1.1_pinout.rst"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.1.rst"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.3.rst"), + os.path.join(doc_dir, "hardware", "master", "ti-tms570lc4357-vx.x.x", "ti-tms570lc4357-v1.1.5.rst"), + os.path.join(doc_dir, "hardware", "master.rst"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6804-1-vx.x.x", "12-ltc-ltc6804-1-v1.x.x", "12-ltc-ltc6804-1-v1.x.x_cell_temperature_connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6804-1-vx.x.x", "12-ltc-ltc6804-1-v1.x.x", "12-ltc-ltc6804-1-v1.x.x_cell_voltage_connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6804-1-vx.x.x", "12-ltc-ltc6804-1-v1.x.x", "12-ltc-ltc6804-1-v1.x.x_master_daisy_connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6804-1-vx.x.x", "12-ltc-ltc6804-1-v1.x.x", "12-ltc-ltc6804-1-v1.x.x_primary_daisy_connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6804-1-vx.x.x", "12-ltc-ltc6804-1-v1.x.x.rst"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-changelog.rst"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_analog-inputs-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_cell-voltage-sense-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_daisy-input-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_daisy-output-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_digital-io-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_electrical-ratings.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_extension-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_external-dc-supply-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_gpio-extension-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_mechanical-dimensions.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3", "12-ltc-ltc6811-1-v2.0.3_temperature-sensor-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.0.3.rst"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_analog-inputs-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_cell-voltage-sense-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_daisy-input-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_daisy-output-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_digital-io-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_electrical-ratings.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_extension-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_external-dc-supply-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_gpio-extension-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_mechanical-dimensions.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2", "12-ltc-ltc6811-1-v2.1.2_temperature-sensor-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.2.rst"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_analog-inputs-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_cell-voltage-sense-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_daisy-input-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_daisy-output-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_digital-io-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_electrical-ratings.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_extension-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_external-dc-supply-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_gpio-extension-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_mechanical-dimensions.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6", "12-ltc-ltc6811-1-v2.1.6_temperature-sensor-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "12-ltc-ltc6811-1-vx.x.x", "12-ltc-ltc6811-1-v2.1.6.rst"), + os.path.join(doc_dir, "hardware", "slaves", "14-nxp-mc33775a-vx.x.x", "14-nxp-mc33775a-changelog.rst"), + os.path.join(doc_dir, "hardware", "slaves", "14-nxp-mc33775a-vx.x.x", "14-nxp-mc33775a-v1.0.0", "14-nxp-mc33775a-v1.0.0_mechanical-dimensions.csv"), + os.path.join(doc_dir, "hardware", "slaves", "14-nxp-mc33775a-vx.x.x", "14-nxp-mc33775a-v1.0.0.rst"), + os.path.join(doc_dir, "hardware", "slaves", "16-adi-ades1830-vx.x.x", "16-adi-ades1830-changelog.rst"), + os.path.join(doc_dir, "hardware", "slaves", "16-adi-ades1830-vx.x.x", "16-adi-ades1830-v0.9.0", "16-adi-ades1830-v0.9.0_cell_voltage-sense-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "16-adi-ades1830-vx.x.x", "16-adi-ades1830-v0.9.0", "16-adi-ades1830-v0.9.0_daisy-input-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "16-adi-ades1830-vx.x.x", "16-adi-ades1830-v0.9.0", "16-adi-ades1830-v0.9.0_daisy-output-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "16-adi-ades1830-vx.x.x", "16-adi-ades1830-v0.9.0", "16-adi-ades1830-v0.9.0_electrical-ratings.csv"), + os.path.join(doc_dir, "hardware", "slaves", "16-adi-ades1830-vx.x.x", "16-adi-ades1830-v0.9.0", "16-adi-ades1830-v0.9.0_mechanical-dimensions.csv"), + os.path.join(doc_dir, "hardware", "slaves", "16-adi-ades1830-vx.x.x", "16-adi-ades1830-v0.9.0", "16-adi-ades1830-v0.9.0_temperature-sensor-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "16-adi-ades1830-vx.x.x", "16-adi-ades1830-v0.9.0.rst"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-changelog.rst"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_analog-inputs-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_cell_voltage-sense-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_daisy-input-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_daisy-output-connectors.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_digital-io-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_electrical-ratings.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_extension-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_extension-connector_2.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_external-dc-supply-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_gpio-extension-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_mechanical-dimensions.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3", "18-ltc-ltc6813-1-v1.1.3_temperature-sensor-connector.csv"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.3.rst"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.4.rst"), + os.path.join(doc_dir, "hardware", "slaves", "18-ltc-ltc6813-1-vx.x.x", "18-ltc-ltc6813-1-v1.1.5.rst"), + os.path.join(doc_dir, "hardware", "slaves.rst"), os.path.join(doc_dir, "index.rst"), os.path.join(doc_dir, "introduction", "abbreviations-definitions.rst"), os.path.join(doc_dir, "introduction", "bms-overview.rst"), + os.path.join(doc_dir, "introduction", "naming-conventions.rst"), + os.path.join(doc_dir, "introduction", "use-case.rst"), os.path.join(doc_dir, "macros.txt"), + os.path.join(doc_dir, "misc", "acknowledgements.rst"), os.path.join(doc_dir, "misc", "bibliography.rst"), os.path.join(doc_dir, "misc", "definitions.csv"), os.path.join(doc_dir, "misc", "developer-manual-nomenclature.csv"), os.path.join(doc_dir, "misc", "indices-and-tables.rst"), os.path.join(doc_dir, "software", "api", "overview.rst"), + os.path.join(doc_dir, "software", "architecture", "architecture.rst"), os.path.join(doc_dir, "software", "build", "build.rst"), + os.path.join(doc_dir, "software", "build", "waf-available-commands.csv"), os.path.join(doc_dir, "software", "build-environment", "build-environment.rst"), os.path.join(doc_dir, "software", "build-environment", "build-environment_how-to.rst"), os.path.join(doc_dir, "software", "build-process", "build-process.rst"), os.path.join(doc_dir, "software", "build-process", "library-project_how-to.rst"), + os.path.join(doc_dir, "software", "configuration", "battery-cell-configuration.csv"), + os.path.join(doc_dir, "software", "configuration", "battery-system-configuration.csv"), + os.path.join(doc_dir, "software", "configuration", "compiler", "compiler-configuration.rst"), + os.path.join(doc_dir, "software", "configuration", "compiler", "linker_pulls", "example_linker_output.txt"), os.path.join(doc_dir, "software", "configuration", "configuration.rst"), + os.path.join(doc_dir, "software", "configuration", "fstartup.c-check.txt"), os.path.join(doc_dir, "software", "configuration", "without-halcogen_how-to.rst"), os.path.join(doc_dir, "software", "how-to", "how-to.rst"), + os.path.join(doc_dir, "software", "linker-script", "linker-script.rst"), + os.path.join(doc_dir, "software", "linker-script", "linker-script-definitions.csv"), os.path.join(doc_dir, "software", "modules", "application", "algorithm", "algorithm.rst"), os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "soc", "soc_counting.rst"), os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "soc", "soc_debug.rst"), @@ -832,15 +1014,21 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "soe", "soe_counting.rst"), os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "soe", "soe_debug.rst"), os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "soe", "soe_none.rst"), - os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "sof", "trapezoid.rst"), + os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "sof", "sof_trapezoid.rst"), os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "soh", "soh_debug.rst"), os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "soh", "soh_none.rst"), os.path.join(doc_dir, "software", "modules", "application", "algorithm", "state-estimation", "state-estimation.rst"), os.path.join(doc_dir, "software", "modules", "application", "bal", "bal.rst"), os.path.join(doc_dir, "software", "modules", "application", "bms", "bms.rst"), + os.path.join(doc_dir, "software", "modules", "application", "bms", "bms_how-to.rst"), os.path.join(doc_dir, "software", "modules", "application", "plausibility", "plausibility.rst"), os.path.join(doc_dir, "software", "modules", "application", "redundancy", "redundancy.rst"), + os.path.join(doc_dir, "software", "modules", "application", "soa", "soa.rst"), os.path.join(doc_dir, "software", "modules", "driver", "adc", "adc.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "afe", "adding-a-new-ic_how-to.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "afe", "adi", "adi_ades1830.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "afe", "afe.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "afe", "debug", "default.rst"), os.path.join(doc_dir, "software", "modules", "driver", "afe", "ltc", "6804-1.rst"), os.path.join(doc_dir, "software", "modules", "driver", "afe", "ltc", "6806.rst"), os.path.join(doc_dir, "software", "modules", "driver", "afe", "ltc", "6811-1.rst"), @@ -850,11 +1038,15 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "software", "modules", "driver", "afe", "nxp", "mc33775a.rst"), os.path.join(doc_dir, "software", "modules", "driver", "afe", "supported-afes.rst"), os.path.join(doc_dir, "software", "modules", "driver", "can", "can.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "can", "can_how-to.rst"), os.path.join(doc_dir, "software", "modules", "driver", "contactor", "contactor.rst"), os.path.join(doc_dir, "software", "modules", "driver", "crc", "crc.rst"), os.path.join(doc_dir, "software", "modules", "driver", "dma", "dma.rst"), os.path.join(doc_dir, "software", "modules", "driver", "foxmath", "foxmath.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "foxmath", "utils.rst"), os.path.join(doc_dir, "software", "modules", "driver", "fram", "fram.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "htsen", "htsen.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "i2c", "i2c.rst"), os.path.join(doc_dir, "software", "modules", "driver", "imd", "bender", "bender_ir155.rst"), os.path.join(doc_dir, "software", "modules", "driver", "imd", "bender", "bender_iso165c.rst"), os.path.join(doc_dir, "software", "modules", "driver", "imd", "imd.rst"), @@ -863,6 +1055,8 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "software", "modules", "driver", "io", "io.rst"), os.path.join(doc_dir, "software", "modules", "driver", "mcu", "mcu.rst"), os.path.join(doc_dir, "software", "modules", "driver", "meas", "meas.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "pex", "pex.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "pwm", "pwm.rst"), os.path.join(doc_dir, "software", "modules", "driver", "rtc", "rtc.rst"), os.path.join(doc_dir, "software", "modules", "driver", "sbc", "sbc.rst"), os.path.join(doc_dir, "software", "modules", "driver", "spi", "spi.rst"), @@ -871,6 +1065,7 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "software", "modules", "driver", "ts", "epcos", "b57251v5103j060.rst"), os.path.join(doc_dir, "software", "modules", "driver", "ts", "epcos", "b57861s0103f045.rst"), os.path.join(doc_dir, "software", "modules", "driver", "ts", "fake", "none.rst"), + os.path.join(doc_dir, "software", "modules", "driver", "ts", "murata", "ncxxxxh103.rst"), os.path.join(doc_dir, "software", "modules", "driver", "ts", "ts.rst"), os.path.join(doc_dir, "software", "modules", "driver", "ts", "ts-sensors.rst"), os.path.join(doc_dir, "software", "modules", "driver", "ts", "ts-short-names.csv"), @@ -880,6 +1075,7 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "software", "modules", "engine", "database", "database_how-to.rst"), os.path.join(doc_dir, "software", "modules", "engine", "diag", "diag.rst"), os.path.join(doc_dir, "software", "modules", "engine", "diag", "diag_how-to.rst"), + os.path.join(doc_dir, "software", "modules", "engine", "hw_info", "hw_info.rst"), os.path.join(doc_dir, "software", "modules", "engine", "sys", "sys.rst"), os.path.join(doc_dir, "software", "modules", "engine", "sys_mon", "sys_mon.rst"), os.path.join(doc_dir, "software", "modules", "main", "fassert.rst"), @@ -889,22 +1085,35 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "software", "modules", "modules.rst"), os.path.join(doc_dir, "software", "modules", "task", "ftask", "ftask.rst"), os.path.join(doc_dir, "software", "modules", "task", "ftask", "ftask_how-to.rst"), + os.path.join(doc_dir, "software", "modules", "task", "ftask", "ftask-function-overview.csv"), + os.path.join(doc_dir, "software", "modules", "task", "ftask", "ftask-user-code-functions.csv"), os.path.join(doc_dir, "software", "modules", "task", "os", "os.rst"), + os.path.join(doc_dir, "software", "overview", "sw-overview.rst"), os.path.join(doc_dir, "software", "unit-tests", "unit-tests.rst"), os.path.join(doc_dir, "software", "unit-tests", "unit-tests_how-to.rst"), + os.path.join(doc_dir, "spelling_wordlist.txt"), + os.path.join(doc_dir, "system", "bjb-measurements.csv"), + os.path.join(doc_dir, "system", "colors-in-system-block-diagram.csv"), + os.path.join(doc_dir, "system", "precharging.rst"), + os.path.join(doc_dir, "system", "symbols-in-system-block-diagram.csv"), + os.path.join(doc_dir, "system", "system-introduction.rst"), + os.path.join(doc_dir, "system", "system-voltage-and-current-monitoring.rst"), + os.path.join(doc_dir, "tools", "dbc.rst"), os.path.join(doc_dir, "tools", "debugger", "debug-application.rst"), os.path.join(doc_dir, "tools", "debugger", "debugger-lauterbach.rst"), os.path.join(doc_dir, "tools", "debugger", "debugger-ozone.rst"), + os.path.join(doc_dir, "tools", "gui", "gui.rst"), + os.path.join(doc_dir, "tools", "gui", "gui-implementation.rst"), os.path.join(doc_dir, "tools", "gui", "impl", "entry", "entry.rst"), + os.path.join(doc_dir, "tools", "gui", "impl", "fgui.rst"), os.path.join(doc_dir, "tools", "gui", "impl", "log_parser", "log_parser.rst"), os.path.join(doc_dir, "tools", "gui", "impl", "lvac", "lvac.rst"), os.path.join(doc_dir, "tools", "gui", "impl", "misc", "misc.rst"), os.path.join(doc_dir, "tools", "gui", "impl", "workers", "workers.rst"), - os.path.join(doc_dir, "tools", "gui", "gui.rst"), - os.path.join(doc_dir, "tools", "gui", "gui-implementation.rst"), os.path.join(doc_dir, "tools", "halcogen", "halcogen.rst"), os.path.join(doc_dir, "tools", "static-analysis", "axivion.rst"), os.path.join(doc_dir, "tools", "waf-tools", "compiler-tool", "f_ti_arm_cgt.rst"), + os.path.join(doc_dir, "tools", "waf-tools", "compiler-tool", "f_ti_arm_cgt_cc_options.rst"), os.path.join(doc_dir, "tools", "waf-tools", "compiler-tool", "f_ti_arm_helper.rst"), os.path.join(doc_dir, "tools", "waf-tools", "compiler-tool", "f_ti_arm_tools.rst"), os.path.join(doc_dir, "tools", "waf-tools", "compiler-tool", "f_ti_color_arm_cgt.rst"), @@ -916,7 +1125,10 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "tools", "waf-tools", "f_git_hooks.rst"), os.path.join(doc_dir, "tools", "waf-tools", "f_guidelines.rst"), os.path.join(doc_dir, "tools", "waf-tools", "f_hcg.rst"), + os.path.join(doc_dir, "tools", "waf-tools", "f_j_flash.rst"), + os.path.join(doc_dir, "tools", "waf-tools", "f_lauterbach.rst"), os.path.join(doc_dir, "tools", "waf-tools", "f_miniconda_env.rst"), + os.path.join(doc_dir, "tools", "waf-tools", "f_node_helper.rst"), os.path.join(doc_dir, "tools", "waf-tools", "f_ozone.rst"), os.path.join(doc_dir, "tools", "waf-tools", "f_pylint.rst"), os.path.join(doc_dir, "tools", "waf-tools", "f_sphinx_build.rst"), @@ -926,7 +1138,6 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements os.path.join(doc_dir, "tools", "waf-tools", "ti-arm-compiler-tools.rst"), os.path.join(doc_dir, "tools", "waf-tools", "waf-tools.rst"), os.path.join(doc_dir, "units.txt"), - ] # pylint: enable=line-too-long # fmt: on @@ -940,9 +1151,9 @@ def build(bld): # pylint: disable=too-many-branches,too-many-statements bld( features="sphinx", builders="html spelling", - outdir=".", + out_dir=".", source=source, - confpy=config, + conf_py=config, VERSION=bld.env.version, RELEASE=bld.env.version, ) @@ -952,7 +1163,7 @@ def build_all(ctx): # pylint: disable=unused-argument """shortcut to build all variants""" # axivion, if existing, needs to be inserted at the end of build commands has_ax = "" - for bld_var in BLD_VARIANTS: + for bld_var in BUILD_VARIANTS: if "axivion" in bld_var: has_ax = "axivion" continue @@ -965,11 +1176,11 @@ def clean_all(ctx): # pylint: disable=unused-argument """shortcut to clean all variants""" # axivion, if existing, needs to be inserted at the end of clean commands has_ax = "" - for cln_var in CLN_VARIANTS: - if "axivion" in cln_var: + for i in CLEAN_VARIANTS: + if "axivion" in i: has_ax = "axivion" continue - Options.commands.append(cln_var) + Options.commands.append(i) if has_ax: Options.commands.append("clean_axivion") @@ -1085,6 +1296,18 @@ def check_test_files(ctx): if diff: ctx.fatal(f"{err_msg}\nTest files are missing.") + err_msg = "" + for test in ctx.path.ant_glob("tests/unit/**/test_*.c"): + for i, line in enumerate(test.read(encoding="utf-8").splitlines()): + if line.startswith("void test"): + if not line.endswith("(void) {"): + err_msg += ( + f"{test.abspath()}:{i+1}: Test files need to have " + f"the form 'test (void) {{' ({line}\n" + ) + if err_msg: + ctx.fatal(f"{err_msg}\nTests are implement invalid.") + def get_axivion_files(ctx): """get all relevant test files. The output is meant to be used in