1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-28 23:29:45 +01:00

sys: zptr: initial commit

Provides functionality to compress pointers from 32bit to 16bit if
possible.
This commit is contained in:
Kaspar Schleiser 2016-07-18 16:03:55 +02:00
parent bbf274aecc
commit 5dc32b14cc
4 changed files with 158 additions and 0 deletions

View File

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

View File

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

139
sys/include/zptr.h Normal file
View File

@ -0,0 +1,139 @@
/*
* Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
*
* 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 <kaspar@schleiser.de>
*/
#ifndef ZPTR_H
#define ZPTR_H
#include <assert.h>
#include <stdint.h>
#include <inttypes.h>
#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 */
/** @} */

14
sys/zptr/Makefile.include Normal file
View File

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