From 4045bab1b785eb8f1dac3627f525e6baaa97499b Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Mon, 12 Jun 2023 18:15:31 +0200 Subject: [PATCH 01/12] twister: pytest: Parse report file to get testcases Extended parsing of report.xml file - produced by pytest-twister-harness plugin. Now testcases are properly extracted and added to twister report. Added unit tests. Signed-off-by: Grzegorz Chwierut --- scripts/pylib/twister/twisterlib/handlers.py | 1 + scripts/pylib/twister/twisterlib/harness.py | 125 +++++++-------- .../pylib/twister/twisterlib/testinstance.py | 22 ++- scripts/tests/twister/conftest.py | 2 + .../pytest_integration/test_harness_pytest.py | 142 ++++++++++++++++++ 5 files changed, 226 insertions(+), 66 deletions(-) create mode 100644 scripts/tests/twister/pytest_integration/test_harness_pytest.py diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 7442eaa780bd60d..5af283cbfc4f3e3 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -40,6 +40,7 @@ logger.setLevel(logging.DEBUG) SUPPORTED_SIMS = ["mdb-nsim", "nsim", "renode", "qemu", "tsim", "armfvp", "xt-sim", "native"] +SUPPORTED_SIMS_IN_PYTEST = ['native', 'qemu'] def terminate_process(proc): diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index f475170d857d2f7..3df794b264af329 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -1,4 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations from asyncio.log import logger import platform import re @@ -13,7 +14,8 @@ import time from twisterlib.environment import ZEPHYR_BASE, PYTEST_PLUGIN_INSTALLED -from twisterlib.handlers import terminate_process +from twisterlib.handlers import Handler, terminate_process, SUPPORTED_SIMS_IN_PYTEST +from twisterlib.testinstance import TestInstance logger = logging.getLogger('twister') @@ -21,8 +23,6 @@ _WINDOWS = platform.system() == 'Windows' -SUPPORTED_SIMS_IN_PYTEST = ['native', 'qemu'] - # pylint: disable=anomalous-backslash-in-string result_re = re.compile(".*(PASS|FAIL|SKIP) - (test_)?(.*) in (\\d*[.,]?\\d*) seconds") @@ -49,7 +49,6 @@ def __init__(self): self.matches = OrderedDict() self.ordered = True self.repeat = 1 - self.testcases = [] self.id = None self.fail_on_fault = True self.fault = False @@ -63,7 +62,7 @@ def __init__(self): self.run_id = None self.matched_run_id = False self.run_id_exists = False - self.instance = None + self.instance: TestInstance | None = None self.testcase_output = "" self._match = False @@ -224,7 +223,7 @@ class PytestHarnessException(Exception): class Pytest(Harness): - def configure(self, instance): + def configure(self, instance: TestInstance): super(Pytest, self).configure(instance) self.running_dir = instance.build_dir self.source_dir = instance.testsuite.source_dir @@ -234,16 +233,15 @@ def configure(self, instance): def pytest_run(self, timeout): try: cmd = self.generate_command() - if not cmd: - logger.error('Pytest command not generated, check logs') - return self.run_command(cmd, timeout) except PytestHarnessException as pytest_exception: logger.error(str(pytest_exception)) + self.state = 'failed' + self.instance.reason = str(pytest_exception) finally: if self.reserved_serial: self.instance.handler.make_device_available(self.reserved_serial) - self._apply_instance_status() + self._update_test_status() def generate_command(self): config = self.instance.testsuite.harness_config @@ -260,7 +258,7 @@ def generate_command(self): ] command.extend(pytest_args) - handler = self.instance.handler + handler: Handler = self.instance.handler if handler.options.verbose > 1: command.append('--log-level=DEBUG') @@ -277,7 +275,7 @@ def generate_command(self): raise PytestHarnessException(f'Handling of handler {handler.type_str} not implemented yet') return command - def _generate_parameters_for_hardware(self, handler): + def _generate_parameters_for_hardware(self, handler: Handler): command = ['--device-type=hardware'] hardware = handler.get_hardware() if not hardware: @@ -318,53 +316,26 @@ def _generate_parameters_for_hardware(self, handler): def run_command(self, cmd, timeout): cmd, env = self._update_command_with_env_dependencies(cmd) - with subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - env=env) as proc: + with subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=env + ) as proc: try: reader_t = threading.Thread(target=self._output_reader, args=(proc,), daemon=True) reader_t.start() reader_t.join(timeout) if reader_t.is_alive(): terminate_process(proc) - logger.warning('Timeout has occurred.') + logger.warning('Timeout has occurred. Can be extended in testspec file. ' + f'Currently set to {timeout} seconds.') + self.instance.reason = 'Pytest timeout' self.state = 'failed' proc.wait(timeout) - - if self.state != 'failed': - tree = ET.parse(self.report_file) - root = tree.getroot() - for child in root: - if child.tag == 'testsuite': - if child.attrib['failures'] != '0': - self.state = "failed" - elif child.attrib['skipped'] != '0': - self.state = "skipped" - elif child.attrib['errors'] != '0': - self.state = "error" - else: - self.state = "passed" - self.instance.execution_time = float(child.attrib['time']) except subprocess.TimeoutExpired: + self.state = 'failed' proc.kill() - self.state = "failed" - except ET.ParseError: - self.state = "failed" - except IOError: - logger.warning("Can't access report.xml") - self.state = "failed" - - tc = self.instance.get_case_or_create(self.id) - if self.state == "passed": - tc.status = "passed" - logger.debug("Pytest cases passed") - elif self.state == "skipped": - tc.status = "skipped" - logger.debug("Pytest cases skipped.") - else: - tc.status = "failed" - logger.info("Pytest cases failed.") @staticmethod def _update_command_with_env_dependencies(cmd): @@ -397,16 +368,52 @@ def _output_reader(proc): logger.debug('PYTEST: %s', line) proc.communicate() - def _apply_instance_status(self): - if self.state: - self.instance.status = self.state - if self.state in ["error", "failed"]: - self.instance.reason = "Pytest failed" - else: - self.instance.status = "failed" - self.instance.reason = "Pytest timeout" - if self.instance.status in ["error", "failed"]: - self.instance.add_missing_case_status("blocked", self.instance.reason) + def _update_test_status(self): + if not self.state: + self.instance.testcases = [] + try: + self._parse_report_file(self.report_file) + except Exception as e: + logger.error(f'Error when parsing file {self.report_file}: {e}') + self.state = 'failed' + finally: + if not self.instance.testcases: + self.instance.init_cases() + + self.instance.status = self.state or 'failed' + if self.instance.status in ['error', 'failed']: + self.instance.reason = self.instance.reason or 'Pytest failed' + self.instance.add_missing_case_status('blocked', self.instance.reason) + + def _parse_report_file(self, report): + tree = ET.parse(report) + root = tree.getroot() + if elem_ts := root.find('testsuite'): + if elem_ts.get('failures') != '0': + self.state = 'failed' + elif elem_ts.get('errors') != '0': + self.state = 'error' + elif elem_ts.get('skipped') == elem_ts.get('tests'): + self.state = 'skipped' + else: + self.state = 'passed' + self.instance.execution_time = float(elem_ts.get('time')) + + for elem_tc in elem_ts.findall('testcase'): + tc = self.instance.get_case_or_create(f"{self.id}.{elem_tc.get('name')}") + tc.duration = float(elem_tc.get('time')) + elem = elem_tc.find('*') + if elem is None: + tc.status = 'passed' + else: + if elem.tag == 'skipped': + tc.status = 'skipped' + elif elem.tag == 'failure': + tc.status = 'failed' + else: + tc.status = 'error' + tc.reason = elem.get('message') + tc.output = elem.text class Gtest(Harness): diff --git a/scripts/pylib/twister/twisterlib/testinstance.py b/scripts/pylib/twister/twisterlib/testinstance.py index bc8bc43b1a495d5..62b0dd8cd335cd5 100644 --- a/scripts/pylib/twister/twisterlib/testinstance.py +++ b/scripts/pylib/twister/twisterlib/testinstance.py @@ -3,7 +3,7 @@ # Copyright (c) 2018-2022 Intel Corporation # Copyright 2022 NXP # SPDX-License-Identifier: Apache-2.0 - +from __future__ import annotations import os import hashlib import random @@ -11,11 +11,19 @@ import shutil import glob -from twisterlib.testsuite import TestCase +from twisterlib.testsuite import TestCase, TestSuite +from twisterlib.platform import Platform from twisterlib.error import BuildError from twisterlib.size_calc import SizeCalculator -from twisterlib.handlers import Handler, SimulationHandler, BinaryHandler, QEMUHandler, DeviceHandler, SUPPORTED_SIMS -from twisterlib.harness import SUPPORTED_SIMS_IN_PYTEST +from twisterlib.handlers import ( + Handler, + SimulationHandler, + BinaryHandler, + QEMUHandler, + DeviceHandler, + SUPPORTED_SIMS, + SUPPORTED_SIMS_IN_PYTEST, +) logger = logging.getLogger('twister') logger.setLevel(logging.DEBUG) @@ -33,8 +41,8 @@ class TestInstance: def __init__(self, testsuite, platform, outdir): - self.testsuite = testsuite - self.platform = platform + self.testsuite: TestSuite = testsuite + self.platform: Platform = platform self.status = None self.reason = "Unknown" @@ -51,7 +59,7 @@ def __init__(self, testsuite, platform, outdir): self.domains = None self.run = False - self.testcases = [] + self.testcases: list[TestCase] = [] self.init_cases() self.filters = [] self.filter_type = None diff --git a/scripts/tests/twister/conftest.py b/scripts/tests/twister/conftest.py index 86f40c12bf38964..232c9c374584a94 100644 --- a/scripts/tests/twister/conftest.py +++ b/scripts/tests/twister/conftest.py @@ -9,6 +9,8 @@ import sys import pytest +pytest_plugins = ["pytester"] + ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister")) sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts")) diff --git a/scripts/tests/twister/pytest_integration/test_harness_pytest.py b/scripts/tests/twister/pytest_integration/test_harness_pytest.py new file mode 100644 index 000000000000000..db7bf389fbdc5a6 --- /dev/null +++ b/scripts/tests/twister/pytest_integration/test_harness_pytest.py @@ -0,0 +1,142 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import pytest +import textwrap + +from unittest import mock +from pathlib import Path + +from twisterlib.harness import Pytest +from twisterlib.testsuite import TestSuite +from twisterlib.testinstance import TestInstance +from twisterlib.platform import Platform + + +@pytest.fixture +def testinstance() -> TestInstance: + testsuite = TestSuite('.', 'samples/hello', 'unit.test') + testsuite.harness_config = {} + testsuite.ignore_faults = False + platform = Platform() + + testinstance = TestInstance(testsuite, platform, 'outdir') + testinstance.handler = mock.Mock() + testinstance.handler.options = mock.Mock() + testinstance.handler.options.verbose = 1 + testinstance.handler.type_str = 'native' + return testinstance + + +@pytest.mark.parametrize('device_type', ['native', 'qemu']) +def test_pytest_command(testinstance: TestInstance, device_type): + pytest_harness = Pytest() + pytest_harness.configure(testinstance) + + testinstance.handler.type_str = device_type + ref_command = [ + 'pytest', + 'samples/hello/pytest', + f'--build-dir={testinstance.build_dir}', + f'--junit-xml={testinstance.build_dir}/report.xml', + f'--device-type={device_type}' + ] + + command = pytest_harness.generate_command() + for c in ref_command: + assert c in command + + +def test_if_report_is_parsed(pytester, testinstance: TestInstance): + test_file_content = textwrap.dedent(""" + def test_1(): + pass + def test_2(): + pass + """) + test_file = pytester.path / 'test_valid.py' + test_file.write_text(test_file_content) + report_file = Path('report.xml') + result = pytester.runpytest( + str(test_file), + f'--junit-xml={str(report_file)}' + ) + result.assert_outcomes(passed=2) + assert report_file.is_file() + + pytest_harness = Pytest() + pytest_harness.configure(testinstance) + pytest_harness.report_file = report_file + + pytest_harness._update_test_status() + + assert pytest_harness.state == "passed" + assert testinstance.status == "passed" + assert len(testinstance.testcases) == 2 + for tc in testinstance.testcases: + assert tc.status == "passed" + + +def test_if_report_with_error(pytester, testinstance: TestInstance): + test_file_content = textwrap.dedent(""" + def test_exp(): + raise Exception('Test error') + def test_err(): + assert False + """) + test_file = pytester.path / 'test_error.py' + test_file.write_text(test_file_content) + report_file = pytester.path / 'report.xml' + result = pytester.runpytest( + str(test_file), + f'--junit-xml={str(report_file)}' + ) + result.assert_outcomes(failed=2) + assert report_file.is_file() + + pytest_harness = Pytest() + pytest_harness.configure(testinstance) + pytest_harness.report_file = report_file + + pytest_harness._update_test_status() + + assert pytest_harness.state == "failed" + assert testinstance.status == "failed" + assert len(testinstance.testcases) == 2 + for tc in testinstance.testcases: + assert tc.status == "failed" + assert tc.output + assert tc.reason + + +def test_if_report_with_skip(pytester, testinstance: TestInstance): + test_file_content = textwrap.dedent(""" + import pytest + @pytest.mark.skip('Test skipped') + def test_skip_1(): + pass + def test_skip_2(): + pytest.skip('Skipped on runtime') + """) + test_file = pytester.path / 'test_skip.py' + test_file.write_text(test_file_content) + report_file = pytester.path / 'report.xml' + result = pytester.runpytest( + str(test_file), + f'--junit-xml={str(report_file)}' + ) + result.assert_outcomes(skipped=2) + assert report_file.is_file() + + pytest_harness = Pytest() + pytest_harness.configure(testinstance) + pytest_harness.report_file = report_file + + pytest_harness._update_test_status() + + assert pytest_harness.state == "skipped" + assert testinstance.status == "skipped" + assert len(testinstance.testcases) == 2 + for tc in testinstance.testcases: + assert tc.status == "skipped" From daa505780064437745d27a8b5862d54e3269a18e Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Tue, 20 Jun 2023 06:50:28 +0100 Subject: [PATCH 02/12] ARC: MWDT: update docs to reflect recent changes Update docs to reflect recent changes: * ARCMWDT_TOOLCHAIN_PATH auto detecting * Usage GNU helper tools from Zephyr SDK Signed-off-by: Eugeniy Paltsev Signed-off-by: Evgeniy Paltsev --- .../toolchains/designware_arc_mwdt.rst | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/doc/develop/toolchains/designware_arc_mwdt.rst b/doc/develop/toolchains/designware_arc_mwdt.rst index cac9671da8faeb1..24d5d53dc1b226b 100644 --- a/doc/develop/toolchains/designware_arc_mwdt.rst +++ b/doc/develop/toolchains/designware_arc_mwdt.rst @@ -3,28 +3,27 @@ DesignWare ARC MetaWare Development Toolkit (MWDT) ################################################## -#. You need to have `ARC MWDT - `_ installed on your - host. +#. You need to have `ARC MWDT `_ installed on + your host. -#. :ref:`Set these environment variables `: - - - Set :envvar:`ZEPHYR_TOOLCHAIN_VARIANT` to ``arcmwdt``. - - Set :envvar:`ARCMWDT_TOOLCHAIN_PATH` to the toolchain installation - directory. MWDT installation provides :envvar:`METAWARE_ROOT` so simply set - :envvar:`ARCMWDT_TOOLCHAIN_PATH` to ``$METAWARE_ROOT/../`` (Linux) - or ``%METAWARE_ROOT%\..\`` (Windows) +#. You need to have :ref:`Zephyr SDK ` installed on your host. .. note:: - Even though ARC MWDT compiler is used for Zephyr RTOS sources compilation, still the GNU - preprocessor & GNU objcopy might be used for some steps like DTS preprocessing and ``.bin`` - file generation. Hence we need to have either ARC or host GNU tools in :envvar:`PATH`. - Currently Zephyr looks for: + A Zephyr SDK is used as a source of tools like device tree compiler (DTC), QEMU, etc... + Even though ARC MWDT toolchain is used for Zephyr RTOS build, still the GNU preprocessor & GNU + objcopy might be used for some steps like device tree preprocessing and ``.bin`` file + generation. We used Zephyr SDK as a source of these ARC GNU tools as well. - * objcopy binaries: ``arc-elf32-objcopy`` or ``arc-linux-objcopy`` or ``objcopy`` - * gcc binaries: ``arc-elf32-gcc`` or ``arc-linux-gcc`` or ``gcc`` +#. :ref:`Set these environment variables `: + + - Set :envvar:`ZEPHYR_TOOLCHAIN_VARIANT` to ``arcmwdt``. + - Set :envvar:`ARCMWDT_TOOLCHAIN_PATH` to the toolchain installation directory. MWDT installation + provides :envvar:`METAWARE_ROOT` so simply set :envvar:`ARCMWDT_TOOLCHAIN_PATH` to + ``$METAWARE_ROOT/../`` (Linux) or ``%METAWARE_ROOT%\..\`` (Windows). - This list can be extended or modified in future. + .. tip:: + If you have only one ARC MWDT toolchain version installed on your machine you may skip setting + :envvar:`ARCMWDT_TOOLCHAIN_PATH` - it would be detected automatically. #. To check that you have set these variables correctly in your current environment, follow these example shell sessions (the @@ -36,10 +35,10 @@ DesignWare ARC MetaWare Development Toolkit (MWDT) $ echo $ZEPHYR_TOOLCHAIN_VARIANT arcmwdt $ echo $ARCMWDT_TOOLCHAIN_PATH - /home/you/ARC/MWDT_2019.12/ + /home/you/ARC/MWDT_2023.03/ # Windows: > echo %ZEPHYR_TOOLCHAIN_VARIANT% arcmwdt > echo %ARCMWDT_TOOLCHAIN_PATH% - C:\ARC\MWDT_2019.12\ + C:\ARC\MWDT_2023.03\ From a64499dae130415181a89a12f11973ac35071e91 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 19 Jun 2023 12:23:06 +0200 Subject: [PATCH 03/12] doc licensing: Remove get_maintainers.pl There is no get_maintainers.pl in the tree, and hasn't been for as long as the git history lasts. Remove its mentiona as a GPL component. get_maintainers.py is Apache 2. Signed-off-by: Alberto Escolar Piedras --- doc/LICENSING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/LICENSING.rst b/doc/LICENSING.rst index 42a997004ede2ee..a69811df85471bd 100644 --- a/doc/LICENSING.rst +++ b/doc/LICENSING.rst @@ -16,7 +16,7 @@ licensing in this document. .. _GPLv2 License: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/COPYING -*scripts/{checkpatch.pl,checkstack.pl,get_maintainers.pl,spelling.txt}* +*scripts/{checkpatch.pl,checkstack.pl,spelling.txt}* *Origin:* Linux Kernel *Licensing:* `GPLv2 License`_ From eccefc4dcc3b6ef401f7574b910198faa1bb43e2 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 19 Jun 2023 12:28:16 +0200 Subject: [PATCH 04/12] doc: contribute external: Fix link and add if not Apache2 The link to the zephyr_licensing page was broken => fix it. Also add a relatively evident if to the list: There is no need to add an entry to the licensing list if the integrated code is Apache 2. Signed-off-by: Alberto Escolar Piedras --- doc/contribute/external.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/contribute/external.rst b/doc/contribute/external.rst index 8d0bf379a2cc074..2ce1b392edd931f 100644 --- a/doc/contribute/external.rst +++ b/doc/contribute/external.rst @@ -87,7 +87,8 @@ automatically implies that the imported source code becomes part of the - The code is subject to the same checks and verification requirements as the rest of the code in the main tree, including static analysis - All files contain an SPDX tag if not already present -- An entry is added to the `licensing page ` +- If the source is not Apache 2.0 licensed, + an entry is added to the :ref:`licensing page `. This mode of integration can be applicable to both small and large external codebases, but it is typically used more commonly with the former. From 88dd32c38c7f8ed363c2b59104404dc201abccb4 Mon Sep 17 00:00:00 2001 From: Christopher Friedt Date: Sat, 24 Jun 2023 10:10:53 -0400 Subject: [PATCH 05/12] doc: services: posix: fix setvbuf typo Fix a typo in the spelling of `setvbuf()`. Signed-off-by: Christopher Friedt --- doc/services/portability/posix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/services/portability/posix.rst b/doc/services/portability/posix.rst index 45d3496dc4d5900..84e0ea2b05d5ce4 100644 --- a/doc/services/portability/posix.rst +++ b/doc/services/portability/posix.rst @@ -430,7 +430,7 @@ POSIX_DEVICE_IO read(),yes scanf(), setbuf(), - etvbuf(), + setvbuf(), stderr,yes stdin,yes stdout,yes From 675a66072791e0e6a18cb02ce157a0fb27a522bb Mon Sep 17 00:00:00 2001 From: Christopher Friedt Date: Sat, 24 Jun 2023 10:13:41 -0400 Subject: [PATCH 06/12] doc: services: posix: _POSIX_THREAD_PRIO_INHERIT unsupported _POSIX_THREAD_PRIO_INHERIT was mistakenly marked supported in commit a07774eada presumably because we have prototypes for the functions below. pthread_mutexattr_getprotocol() pthread_mutexattr_setprotocol() However, the functions are not actually implemented in Zephyr. Signed-off-by: Christopher Friedt --- doc/services/portability/posix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/services/portability/posix.rst b/doc/services/portability/posix.rst index 84e0ea2b05d5ce4..edc384f6e908551 100644 --- a/doc/services/portability/posix.rst +++ b/doc/services/portability/posix.rst @@ -97,7 +97,7 @@ Zephyr. _POSIX_THREAD_ATTR_STACKADDR,yes _POSIX_THREAD_ATTR_STACKSIZE,yes _POSIX_THREAD_CPUTIME, - _POSIX_THREAD_PRIO_INHERIT,yes + _POSIX_THREAD_PRIO_INHERIT, _POSIX_THREAD_PRIO_PROTECT, _POSIX_THREAD_PRIORITY_SCHEDULING,yes _POSIX_THREAD_SPORADIC_SERVER, From 64a477342d81dd6e0eeed55912e9d701a00515a5 Mon Sep 17 00:00:00 2001 From: Christopher Friedt Date: Sat, 24 Jun 2023 10:45:32 -0400 Subject: [PATCH 07/12] doc: services: posix: pthread_condattr_destroy and init supported The functions pthread_condattr_destroy() and pthread_condattr_init() are implemented (they just do nothing). Signed-off-by: Christopher Friedt --- doc/services/portability/posix.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/services/portability/posix.rst b/doc/services/portability/posix.rst index edc384f6e908551..79b23e5fbc36571 100644 --- a/doc/services/portability/posix.rst +++ b/doc/services/portability/posix.rst @@ -151,8 +151,8 @@ multiple processes. pthread_cond_signal(),yes pthread_cond_timedwait(),yes pthread_cond_wait(),yes - pthread_condattr_destroy(), - pthread_condattr_init(), + pthread_condattr_destroy(),yes + pthread_condattr_init(),yes pthread_create(),yes pthread_detach(),yes pthread_equal(), From b416a90672625881f229a480b0fb578468f33c57 Mon Sep 17 00:00:00 2001 From: Christopher Friedt Date: Sat, 24 Jun 2023 10:49:53 -0400 Subject: [PATCH 08/12] doc: services: posix: pthread_mutexattr_destroy init supported The functions pthread_mutexattr_destroy() and pthread_mutexattr_init() are implemented (they just do nothing). Signed-off-by: Christopher Friedt --- doc/services/portability/posix.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/services/portability/posix.rst b/doc/services/portability/posix.rst index 79b23e5fbc36571..b2a807d4f0594fa 100644 --- a/doc/services/portability/posix.rst +++ b/doc/services/portability/posix.rst @@ -167,8 +167,8 @@ multiple processes. pthread_mutex_lock(),yes pthread_mutex_trylock(),yes pthread_mutex_unlock(),yes - pthread_mutexattr_destroy(), - pthread_mutexattr_init(), + pthread_mutexattr_destroy(),yes + pthread_mutexattr_init(),yes pthread_once(),yes pthread_self(),yes pthread_setcancelstate(),yes From b158c52e244a97423804d2eb6f4e2dd45fac4630 Mon Sep 17 00:00:00 2001 From: Alexander Razinkov Date: Mon, 22 May 2023 18:52:52 +0300 Subject: [PATCH 09/12] devicetree: support of 64-bit addresses from devicetree Usage of 64-bit address constants from devicetree without a UINT64_C wrapping macro results in the following warning and the cut-off of the address value: "warning: integer constant is so large that it is unsigned" This change extends devicetree API adding few wrappers over the address constant getters which add ULL size suffix to an address integer literal when the appearance of 64-bit address values is possible Signed-off-by: Alexander Razinkov --- dts/bindings/test/vnd,reg-holder-64.yaml | 15 ++++++ include/zephyr/devicetree.h | 69 ++++++++++++++++++++++++ tests/lib/devicetree/api/app.overlay | 12 +++++ tests/lib/devicetree/api/src/main.c | 32 +++++++++++ 4 files changed, 128 insertions(+) create mode 100644 dts/bindings/test/vnd,reg-holder-64.yaml diff --git a/dts/bindings/test/vnd,reg-holder-64.yaml b/dts/bindings/test/vnd,reg-holder-64.yaml new file mode 100644 index 000000000000000..0e0800e784b2816 --- /dev/null +++ b/dts/bindings/test/vnd,reg-holder-64.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Syntacore +# SPDX-License-Identifier: Apache-2.0 + +description: Test 64-bit register property container + +compatible: "vnd,reg-holder-64" + +include: [base.yaml] + +properties: + reg: + required: true + + reg-names: + required: true diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index ed8db9edfc7095c..c9aab6653431b74 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -18,6 +18,10 @@ #include +#if !defined(_LINKER) && !defined(_ASMLANGUAGE) +#include +#endif + #include /** @@ -2219,6 +2223,18 @@ */ #define DT_REG_ADDR(node_id) DT_REG_ADDR_BY_IDX(node_id, 0) +/** + * @brief 64-bit version of DT_REG_ADDR() + * + * This macro version adds the appropriate suffix for 64-bit unsigned + * integer literals. + * Note that this macro is equivalent to DT_REG_ADDR() in linker/ASM context. + * + * @param node_id node identifier + * @return node's register block address + */ +#define DT_REG_ADDR_U64(node_id) DT_U64_C(DT_REG_ADDR(node_id)) + /** * @brief Get a node's (only) register block size * @@ -2237,6 +2253,21 @@ #define DT_REG_ADDR_BY_NAME(node_id, name) \ DT_CAT4(node_id, _REG_NAME_, name, _VAL_ADDRESS) +/** + * @brief 64-bit version of DT_REG_ADDR_BY_NAME() + * + * This macro version adds the appropriate suffix for 64-bit unsigned + * integer literals. + * Note that this macro is equivalent to DT_REG_ADDR_BY_NAME() in + * linker/ASM context. + * + * @param node_id node identifier + * @param name lowercase-and-underscores register specifier name + * @return address of the register block specified by name + */ +#define DT_REG_ADDR_BY_NAME_U64(node_id, name) \ + DT_U64_C(DT_REG_ADDR_BY_NAME(node_id, name)) + /** * @brief Get a register block's size by name * @param node_id node identifier @@ -3681,6 +3712,21 @@ #define DT_INST_REG_ADDR_BY_NAME(inst, name) \ DT_REG_ADDR_BY_NAME(DT_DRV_INST(inst), name) +/** + * @brief 64-bit version of DT_INST_REG_ADDR_BY_NAME() + * + * This macro version adds the appropriate suffix for 64-bit unsigned + * integer literals. + * Note that this macro is equivalent to DT_INST_REG_ADDR_BY_NAME() in + * linker/ASM context. + * + * @param inst instance number + * @param name lowercase-and-underscores register specifier name + * @return address of the register block with the given @p name + */ +#define DT_INST_REG_ADDR_BY_NAME_U64(inst, name) \ + DT_U64_C(DT_INST_REG_ADDR_BY_NAME(inst, name)) + /** * @brief Get a `DT_DRV_COMPAT`'s register block size by name * @param inst instance number @@ -3697,6 +3743,19 @@ */ #define DT_INST_REG_ADDR(inst) DT_INST_REG_ADDR_BY_IDX(inst, 0) +/** + * @brief 64-bit version of DT_INST_REG_ADDR() + * + * This macro version adds the appropriate suffix for 64-bit unsigned + * integer literals. + * Note that this macro is equivalent to DT_INST_REG_ADDR() in + * linker/ASM context. + * + * @param inst instance number + * @return instance's register block address + */ +#define DT_INST_REG_ADDR_U64(inst) DT_U64_C(DT_INST_REG_ADDR(inst)) + /** * @brief Get a `DT_DRV_COMPAT`'s (only) register block size * @param inst instance number @@ -4172,6 +4231,16 @@ #define DT_INST_NODE_HAS_PROP_AND_OR(inst, prop) \ DT_INST_NODE_HAS_PROP(inst, prop) || +/** + * @def DT_U64_C + * @brief Macro to add ULL postfix to the devicetree address constants + */ +#if defined(_LINKER) || defined(_ASMLANGUAGE) +#define DT_U64_C(_v) (_v) +#else +#define DT_U64_C(_v) UINT64_C(_v) +#endif + /** @endcond */ /* have these last so they have access to all previously defined macros */ diff --git a/tests/lib/devicetree/api/app.overlay b/tests/lib/devicetree/api/app.overlay index 0a915b1f31ff9ab..49c71263740ace6 100644 --- a/tests/lib/devicetree/api/app.overlay +++ b/tests/lib/devicetree/api/app.overlay @@ -621,4 +621,16 @@ val = "XA XPLUS XB", "XC XPLUS XD", "XA XMINUS XB", "XC XMINUS XD"; }; }; + + test_64 { + #address-cells = < 2 >; + #size-cells = < 0 >; + + test_reg_64: reg-holder-64@ffffffff11223344 { + compatible = "vnd,reg-holder-64"; + reg = < 0xffffffff 0x11223344>; + status = "okay"; + reg-names = "test_name"; + }; + }; }; diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c index 55c92fdc9de5086..d173e3357f255e7 100644 --- a/tests/lib/devicetree/api/src/main.c +++ b/tests/lib/devicetree/api/src/main.c @@ -39,6 +39,7 @@ #define TEST_VENDOR DT_NODELABEL(test_vendor) #define TEST_MODEL DT_NODELABEL(test_vendor) #define TEST_ENUM_0 DT_NODELABEL(test_enum_0) +#define TEST_64BIT DT_NODELABEL(test_reg_64) #define TEST_I2C DT_NODELABEL(test_i2c) #define TEST_I2C_DEV DT_PATH(test, i2c_11112222, test_i2c_dev_10) @@ -546,6 +547,9 @@ ZTEST(devicetree_api, test_reg) /* DT_REG_ADDR */ zassert_equal(DT_REG_ADDR(TEST_ABCD1234), 0xabcd1234, ""); + /* DT_REG_ADDR_U64 */ + zassert_equal(DT_REG_ADDR_U64(TEST_ABCD1234), 0xabcd1234, ""); + /* DT_REG_SIZE */ zassert_equal(DT_REG_SIZE(TEST_ABCD1234), 0x500, ""); @@ -553,6 +557,10 @@ ZTEST(devicetree_api, test_reg) zassert_equal(DT_REG_ADDR_BY_NAME(TEST_ABCD1234, one), 0xabcd1234, ""); zassert_equal(DT_REG_ADDR_BY_NAME(TEST_ABCD1234, two), 0x98765432, ""); + /* DT_REG_ADDR_BY_NAME_U64 */ + zassert_equal(DT_REG_ADDR_BY_NAME_U64(TEST_ABCD1234, one), 0xabcd1234, ""); + zassert_equal(DT_REG_ADDR_BY_NAME_U64(TEST_ABCD1234, two), 0x98765432, ""); + /* DT_REG_SIZE_BY_NAME */ zassert_equal(DT_REG_SIZE_BY_NAME(TEST_ABCD1234, one), 0x500, ""); zassert_equal(DT_REG_SIZE_BY_NAME(TEST_ABCD1234, two), 0xff, ""); @@ -576,6 +584,9 @@ ZTEST(devicetree_api, test_reg) /* DT_INST_REG_ADDR */ zassert_equal(DT_INST_REG_ADDR(0), 0x9999aaaa, ""); + /* DT_INST_REG_ADDR_U64 */ + zassert_equal(DT_INST_REG_ADDR_U64(0), 0x9999aaaa, ""); + /* DT_INST_REG_SIZE */ zassert_equal(DT_INST_REG_SIZE(0), 0x1000, ""); @@ -583,11 +594,32 @@ ZTEST(devicetree_api, test_reg) zassert_equal(DT_INST_REG_ADDR_BY_NAME(0, first), 0x9999aaaa, ""); zassert_equal(DT_INST_REG_ADDR_BY_NAME(0, second), 0xbbbbcccc, ""); + /* DT_INST_REG_ADDR_BY_NAME_U64 */ + zassert_equal(DT_INST_REG_ADDR_BY_NAME_U64(0, first), 0x9999aaaa, ""); + zassert_equal(DT_INST_REG_ADDR_BY_NAME_U64(0, second), 0xbbbbcccc, ""); + /* DT_INST_REG_SIZE_BY_NAME */ zassert_equal(DT_INST_REG_SIZE_BY_NAME(0, first), 0x1000, ""); zassert_equal(DT_INST_REG_SIZE_BY_NAME(0, second), 0x3f, ""); } +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT vnd_reg_holder_64 +ZTEST(devicetree_api, test_reg_64) +{ + /* DT_REG_ADDR_U64 */ + zassert_equal(DT_REG_ADDR_U64(TEST_64BIT), 0xffffffff11223344, ""); + + /* DT_REG_ADDR_BY_NAME_U64 */ + zassert_equal(DT_REG_ADDR_BY_NAME_U64(TEST_64BIT, test_name), 0xffffffff11223344, ""); + + /* DT_INST_REG_ADDR_U64 */ + zassert_equal(DT_INST_REG_ADDR_U64(0), 0xffffffff11223344, ""); + + /* DT_INST_REG_ADDR_BY_NAME_U64 */ + zassert_equal(DT_INST_REG_ADDR_BY_NAME_U64(0, test_name), 0xffffffff11223344, ""); +} + #undef DT_DRV_COMPAT #define DT_DRV_COMPAT vnd_interrupt_holder ZTEST(devicetree_api, test_irq) From cb491cacad74bd81a771564add67f722f6c10796 Mon Sep 17 00:00:00 2001 From: Alexander Razinkov Date: Wed, 24 May 2023 09:50:43 +0300 Subject: [PATCH 10/12] drivers: support 64-bit addresses from devicetree for PLIC, MTIMER, UART Usage of 64-bit address constants from devicetree without an UINT64_C wrapping macro results in the following warning and the cut-off of the address value: "warning: integer constant is so large that it is unsigned" This change fixes such issue for PLIC, MTIMER and UART in case they are used with some 64-bit RISC-V platforms Signed-off-by: Alexander Razinkov --- drivers/interrupt_controller/intc_plic.c | 6 +++--- drivers/timer/riscv_machine_timer.c | 6 +++--- include/zephyr/sys/device_mmio.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/interrupt_controller/intc_plic.c b/drivers/interrupt_controller/intc_plic.c index d7958ad9b4a15bb..11d41e2f191a1a7 100644 --- a/drivers/interrupt_controller/intc_plic.c +++ b/drivers/interrupt_controller/intc_plic.c @@ -22,9 +22,9 @@ #include #define PLIC_MAX_PRIO DT_INST_PROP(0, riscv_max_priority) -#define PLIC_PRIO DT_INST_REG_ADDR_BY_NAME(0, prio) -#define PLIC_IRQ_EN DT_INST_REG_ADDR_BY_NAME(0, irq_en) -#define PLIC_REG DT_INST_REG_ADDR_BY_NAME(0, reg) +#define PLIC_PRIO DT_INST_REG_ADDR_BY_NAME_U64(0, prio) +#define PLIC_IRQ_EN DT_INST_REG_ADDR_BY_NAME_U64(0, irq_en) +#define PLIC_REG DT_INST_REG_ADDR_BY_NAME_U64(0, reg) #define PLIC_IRQS (CONFIG_NUM_IRQS - CONFIG_2ND_LVL_ISR_TBL_OFFSET) #define PLIC_EN_SIZE ((PLIC_IRQS >> 5) + 1) diff --git a/drivers/timer/riscv_machine_timer.c b/drivers/timer/riscv_machine_timer.c index f4ac7afe4d43ff3..7ddbc359dfa7dd1 100644 --- a/drivers/timer/riscv_machine_timer.c +++ b/drivers/timer/riscv_machine_timer.c @@ -67,9 +67,9 @@ #define DT_DRV_COMPAT scr_machine_timer #define MTIMER_HAS_DIVIDER -#define MTIMEDIV_REG (DT_INST_REG_ADDR(0) + 4) -#define MTIME_REG (DT_INST_REG_ADDR(0) + 8) -#define MTIMECMP_REG (DT_INST_REG_ADDR(0) + 16) +#define MTIMEDIV_REG (DT_INST_REG_ADDR_U64(0) + 4) +#define MTIME_REG (DT_INST_REG_ADDR_U64(0) + 8) +#define MTIMECMP_REG (DT_INST_REG_ADDR_U64(0) + 16) #define TIMER_IRQN DT_INST_IRQN(0) #endif diff --git a/include/zephyr/sys/device_mmio.h b/include/zephyr/sys/device_mmio.h index 887ea7ee18e7060..bc28c3e91e448b8 100644 --- a/include/zephyr/sys/device_mmio.h +++ b/include/zephyr/sys/device_mmio.h @@ -116,12 +116,12 @@ struct z_device_mmio_rom { #define Z_DEVICE_MMIO_ROM_INITIALIZER(node_id) \ { \ - .addr = DT_REG_ADDR(node_id) \ + .addr = (mm_reg_t)DT_REG_ADDR_U64(node_id) \ } #define Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id) \ { \ - .addr = DT_REG_ADDR_BY_NAME(node_id, name) \ + .addr = (mm_reg_t)DT_REG_ADDR_BY_NAME_U64(node_id, name) \ } #endif /* DEVICE_MMIO_IS_IN_RAM */ From 89f15cb2f30c324bfb47d5b07edec9a7411f8ead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Fri, 23 Jun 2023 11:54:50 +0200 Subject: [PATCH 11/12] doc: release: update dates to ISO 8601 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Write dates as ISO 8601 as previous notation could be confusing. Signed-off-by: Benjamin Cabé --- doc/releases/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/releases/index.rst b/doc/releases/index.rst index bb6c0b1f73b1165..31c327081e81f47 100644 --- a/doc/releases/index.rst +++ b/doc/releases/index.rst @@ -50,15 +50,15 @@ Supported Releases +-----------------+----------------+---------------+ | Release | Release date | EOL | +=================+================+===============+ -| `Zephyr 2.7.5`_ | 01/06/2023 | 31/08/2024 | +| `Zephyr 2.7.5`_ | 2023-06-01 | 2024-08-31 | +-----------------+----------------+---------------+ -| `Zephyr 3.3.0`_ | 19/02/2023 | 31/10/2023 | +| `Zephyr 3.3.0`_ | 2023-02-19 | 2023-10-31 | +-----------------+----------------+---------------+ -| `Zephyr 3.2.0`_ | 30/09/2022 | 31/06/2023 | +| `Zephyr 3.2.0`_ | 2022-09-30 | 2023-06-30 | +-----------------+----------------+---------------+ -As of 01/01/2022, LTS1 (1.14.x) is not supported and has reached end of life (EOL). +As of 2022-01-01, LTS1 (1.14.x) is not supported and has reached end of life (EOL). Release Notes ************* From e7414495fa4fd188ca3aec07a33d02d873d8d7d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Fri, 23 Jun 2023 11:56:35 +0200 Subject: [PATCH 12/12] doc: release: add Zephyr 3.4 as supported release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Zephyr 3.4 as a supported release until end of Feb 2024. Signed-off-by: Benjamin Cabé --- doc/releases/index.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/releases/index.rst b/doc/releases/index.rst index 31c327081e81f47..27571f65b31549c 100644 --- a/doc/releases/index.rst +++ b/doc/releases/index.rst @@ -52,6 +52,8 @@ Supported Releases +=================+================+===============+ | `Zephyr 2.7.5`_ | 2023-06-01 | 2024-08-31 | +-----------------+----------------+---------------+ +| `Zephyr 3.4.0`_ | 2023-06-16 | 2024-02-29 | ++-----------------+----------------+---------------+ | `Zephyr 3.3.0`_ | 2023-02-19 | 2023-10-31 | +-----------------+----------------+---------------+ | `Zephyr 3.2.0`_ | 2022-09-30 | 2023-06-30 | @@ -95,3 +97,4 @@ specific release and can be found at https://docs.zephyrproject.org/. .. _`Zephyr 2.7.5`: https://docs.zephyrproject.org/2.7.5/ .. _`Zephyr 3.2.0`: https://docs.zephyrproject.org/3.2.0/ .. _`Zephyr 3.3.0`: https://docs.zephyrproject.org/3.3.0/ +.. _`Zephyr 3.4.0`: https://docs.zephyrproject.org/3.4.0/