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:
parent
bbf274aecc
commit
5dc32b14cc
@ -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
|
||||
|
@ -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
139
sys/include/zptr.h
Normal 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
14
sys/zptr/Makefile.include
Normal 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
|
Loading…
Reference in New Issue
Block a user