From bbf274aecc127cdf8bd7f094203f71f4dac4bf56 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Fri, 7 Feb 2020 10:23:21 +0100 Subject: [PATCH 1/3] cpu/kinetis: immediately convert shell expansion of RAM_BASE_ADDR --- cpu/kinetis/Makefile.include | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpu/kinetis/Makefile.include b/cpu/kinetis/Makefile.include index 17af151c72..a7778b2ec9 100644 --- a/cpu/kinetis/Makefile.include +++ b/cpu/kinetis/Makefile.include @@ -27,7 +27,8 @@ LINKER_SCRIPT = kinetis.ld ROM_START_ADDR = 0x00000000 RAM_BASE_ADDR = 0x20000000 -RAM_START_ADDR = $$(($(RAM_BASE_ADDR)-($(KINETIS_SRAM_L_SIZE) * 1024))) +RAM_START_ADDR := $(shell printf "0x%08x" $$(($(RAM_BASE_ADDR)-($(KINETIS_SRAM_L_SIZE) * 1024)))) + # Define ROM_LEN with a non arithmetic value as it must be # evaluated in `cortexm_common` without a shell context # The `K` is correctly handled by both the linker and `cortexm_common`. From 5dc32b14cc9a2c324aa1d8babe5932e433c97364 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Mon, 18 Jul 2016 16:03:55 +0200 Subject: [PATCH 2/3] sys: zptr: initial commit Provides functionality to compress pointers from 32bit to 16bit if possible. --- makefiles/pseudomodules.inc.mk | 1 + sys/Makefile.include | 4 + sys/include/zptr.h | 139 +++++++++++++++++++++++++++++++++ sys/zptr/Makefile.include | 14 ++++ 4 files changed, 158 insertions(+) create mode 100644 sys/include/zptr.h create mode 100644 sys/zptr/Makefile.include diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 620365e0be..521d5e6e14 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -93,6 +93,7 @@ PSEUDOMODULES += stdio_cdc_acm PSEUDOMODULES += stdio_uart_rx PSEUDOMODULES += suit_% PSEUDOMODULES += wakaama_objects_% +PSEUDOMODULES += zptr # handle suit_v4 being a distinct module NO_PSEUDOMODULES += suit_v4 diff --git a/sys/Makefile.include b/sys/Makefile.include index b4b3a2dd2a..b81b2fbc43 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -111,3 +111,7 @@ endif ifneq (,$(filter clif, $(USEMODULE))) INCLUDES += -I$(RIOTBASE)/sys/clif/include endif + +ifneq (,$(filter zptr,$(USEMODULE))) + include $(RIOTBASE)/sys/zptr/Makefile.include +endif diff --git a/sys/include/zptr.h b/sys/include/zptr.h new file mode 100644 index 0000000000..4d63e2ae0f --- /dev/null +++ b/sys/include/zptr.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2017 Kaspar Schleiser + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup sys_util_zptr Pointer Compression + * @ingroup sys + * @brief Provides 32bit -> 16bit pointer compression + * + * On many platforms, some pointers may have to be aligned, e.g., to 4 byte + * bounderies. + * On 32bit platforms, that makes it possible to store all possible aligned + * 32bit pointers in a 16bit value as long as the total memory is small (e.g., + * with 4 byte alignment, all pointers within 256kb RAM can be represented by a + * 16bit value). This can save memory, at the cost of some instructions for + * compression/decompression. + * + * In order to use pointer compression, ZPTR_BASE needs to be defined to a (4 + * byte aligned) base address. + * + * A printf format macro (PRIzptr) is provided. + * + * You can then use zptr_t instead of a pointer type, using the supplied functions to compress / decompress, + * e.g., + * + * void func(void *ptr) { + * printf("%"PRIzptr"\n", ptr); + * ... + * free(ptr); + * } + * + * ... would become + * + * void func(zptr_t zptr); + * printf("%"PRIzptr"\n", zptr); + * ... + * free(zptrd(zptr)); + * } + * + * + * If ZPTR_BASE is unset, @ref zptr_t / @ref zptrc() / @ref zptrd() will + * transparently and without overhead compile to normal (uncompressed) pointer + * operations. + * + * @{ + * + * @file + * @brief 32bit -> 16bit pointer compression implementation + * + * @author Kaspar Schleiser + */ + +#ifndef ZPTR_H +#define ZPTR_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if ZPTR_BASE || defined(DOXYGEN) + +/** + * @brief zptr type definition + */ +typedef uint16_t zptr_t; + +/** + * @brief zptr printf format definition + */ +#define PRIzptr PRIu16 + +/** + * @brief zptr highest compressible address + */ +#define ZPTR_MAX_ADDR ((uintptr_t)ZPTR_BASE + (1 << 18)) + +/** + * @brief Determine if a pointer is compressable by zptrc() + * @param[in] pointer pointer to check + * @returns 1 if pointer can be compressed, 0 if not + */ +static inline int zptr_check(void *pointer) +{ + uintptr_t int_ptr = (uintptr_t)pointer; + return ((!(int_ptr & 0x3)) \ + && (int_ptr >= (uintptr_t)ZPTR_BASE) \ + && (int_ptr < ZPTR_MAX_ADDR)); +} + +/** + * @brief Compress a pointer (if possible) + * + * Substracts ZPTR_BASE, then right-shifts @p pointer by two. + * + * @param[in] pointer pointer to compress + * @returns compressed pointer + */ +static inline zptr_t zptrc(void *pointer) +{ + assert(zptr_check(pointer)); + return (uint16_t)(((uint32_t)pointer - (uint32_t)ZPTR_BASE) >> 2); +} + +/** + * @brief Decompress a pointer + * + * Left-shifts zptr_t by two, then adds ZPTR_BASE. + * + * @param[in] zptr compressed pointer + * @returns decompressed pointer + */ +static inline void *zptrd(zptr_t zptr) +{ + return (void *)(ZPTR_BASE + ((uint32_t)zptr << 2)); +} + +#else /* ZPTR_BASE */ +/* fallback implementation */ +typedef void *zptr_t; +#define PRIzptr "p" +static inline int zptr_check(void *pointer) { (void)pointer; return 0; } +static inline zptr_t zptrc(void *pointer) { return (zptr_t)pointer; } +static inline void *zptrd(zptr_t zptr) { return (void *)zptr; } +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZPTR_H */ +/** @} */ diff --git a/sys/zptr/Makefile.include b/sys/zptr/Makefile.include new file mode 100644 index 0000000000..b76368512b --- /dev/null +++ b/sys/zptr/Makefile.include @@ -0,0 +1,14 @@ +# zptr can use pointer compression of four byte aligned pointers, by right- +# shifting them by two and stuffing in an uint16_t. +# That only works on 32bit platforms, if total RAM size is <=2**18 and the +# start address is known. +ifneq (,$(filter arch_32bit,$(FEATURES_USED))) + ifneq (,$(RAM_START_ADDR)) + ifneq (,$(RAM_LEN)) + # this handles 0xXXX and xxxK + ifeq (1,$(shell echo $$(($(subst K,*1024,$(RAM_LEN)) <= 262144)))) + CFLAGS += -DZPTR_BASE=$(RAM_START_ADDR) + endif + endif + endif +endif From f3874edd147f18d4afd882add9133fa82371f837 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Tue, 5 Sep 2017 18:54:43 +0200 Subject: [PATCH 3/3] tests/unittests: add basic zptr test --- tests/unittests/tests-zptr/Makefile | 1 + tests/unittests/tests-zptr/Makefile.include | 1 + tests/unittests/tests-zptr/tests-zptr.c | 44 +++++++++++++++++++++ tests/unittests/tests-zptr/tests-zptr.h | 37 +++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 tests/unittests/tests-zptr/Makefile create mode 100644 tests/unittests/tests-zptr/Makefile.include create mode 100644 tests/unittests/tests-zptr/tests-zptr.c create mode 100644 tests/unittests/tests-zptr/tests-zptr.h diff --git a/tests/unittests/tests-zptr/Makefile b/tests/unittests/tests-zptr/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/tests/unittests/tests-zptr/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/tests/unittests/tests-zptr/Makefile.include b/tests/unittests/tests-zptr/Makefile.include new file mode 100644 index 0000000000..ab8b0ccf19 --- /dev/null +++ b/tests/unittests/tests-zptr/Makefile.include @@ -0,0 +1 @@ +USEMODULE += zptr diff --git a/tests/unittests/tests-zptr/tests-zptr.c b/tests/unittests/tests-zptr/tests-zptr.c new file mode 100644 index 0000000000..e08c3e520d --- /dev/null +++ b/tests/unittests/tests-zptr/tests-zptr.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2017 Kaspar Schleiser + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + */ +#include +#include +#include + +#include "embUnit/embUnit.h" + +#include "zptr.h" +#include "tests-zptr.h" + +static void test_zptr_basic(void) +{ + uint32_t val; + TEST_ASSERT(&val == zptrd(zptrc(&val))); +} + +Test *tests_zptr_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_zptr_basic), + }; + + EMB_UNIT_TESTCALLER(zptr_tests, NULL, NULL, fixtures); + + return (Test *)&zptr_tests; +} + +void tests_zptr(void) +{ + TESTS_RUN(tests_zptr_tests()); +} +/** @} */ diff --git a/tests/unittests/tests-zptr/tests-zptr.h b/tests/unittests/tests-zptr/tests-zptr.h new file mode 100644 index 0000000000..4e429fb0aa --- /dev/null +++ b/tests/unittests/tests-zptr/tests-zptr.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 Kaspar Schleiser + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup unittests + * @{ + * + * @file + * @brief Unittests for the ``zptr`` module + * + * @author Kaspar Schleiser + */ +#ifndef TESTS_ZPTR_H +#define TESTS_ZPTR_H + +#include "embUnit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The entry point of this test suite. + */ +void tests_zptr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* TESTS_ZPTR_H */ +/** @} */