From: bernie Date: Wed, 13 Aug 2008 10:27:12 +0000 (+0000) Subject: pgm, byteorder: move from mware/ to cpu/ X-Git-Tag: 2.0.0~302 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=4b681f454badd9055c35b60d9a3ecd8da11c4b80;p=bertos.git pgm, byteorder: move from mware/ to cpu/ git-svn-id: https://src.develer.com/svnoss/bertos/trunk@1632 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/bertos/cpu/byteorder.h b/bertos/cpu/byteorder.h new file mode 100644 index 00000000..3dd7825e --- /dev/null +++ b/bertos/cpu/byteorder.h @@ -0,0 +1,269 @@ +/** + * \file + * + * + * \brief Functions to convert integers to/from host byte-order. + * + * \version $Id$ + * + * \author Bernie Innocenti + * \author Stefano Fedrigo + */ + +#ifndef MWARE_BYTEORDER_H +#define MWARE_BYTEORDER_H + +#include +#include + +/** + * Swap upper and lower bytes in a 16-bit value. + */ +INLINE uint16_t swab16(uint16_t x) +{ + return ((x & (uint16_t)0x00FFU) << 8) + | ((x & (uint16_t)0xFF00U) >> 8); +} + +/** + * Reverse bytes in a 32-bit value (e.g.: 0x12345678 -> 0x78563412). + */ +INLINE uint32_t swab32(uint32_t x) +{ + return ((x & (uint32_t)0x000000FFUL) << 24) + | ((x & (uint32_t)0x0000FF00UL) << 8) + | ((x & (uint32_t)0x00FF0000UL) >> 8) + | ((x & (uint32_t)0xFF000000UL) >> 24); +} + +/** + * Reverse bytes in a 64-bit value. + */ +INLINE uint64_t swab64(uint64_t x) +{ + return (uint64_t)swab32(x >> 32) + | ((uint64_t)swab32(x & 0xFFFFFFFFUL) << 32); +} + +/** + * Reverse bytes in a float value. + */ +INLINE float swab_float(float x) +{ + /* Avoid breaking strict aliasing rules. */ + char *cx = (char *)(&x); + STATIC_ASSERT(sizeof(float) == 4); + #define BYTEORDER_SWAP(a, b) ((a) ^= (b) ^= (a) ^= (b)) + BYTEORDER_SWAP(cx[0], cx[3]); + BYTEORDER_SWAP(cx[1], cx[2]); + #undef BYTEORDER_SWAP + return x; +} + +INLINE uint16_t cpu_to_be16(uint16_t x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab16(x) : x; +} + +INLINE uint16_t cpu_to_le16(uint16_t x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab16(x) : x; +} + +INLINE uint32_t cpu_to_be32(uint32_t x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab32(x) : x; +} + +INLINE uint32_t cpu_to_le32(uint32_t x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab32(x) : x; +} + +INLINE uint64_t cpu_to_be64(uint64_t x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab64(x) : x; +} + +INLINE uint64_t cpu_to_le64(uint64_t x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab64(x) : x; +} + +INLINE float cpu_to_be_float(float x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab_float(x) : x; +} + +INLINE float cpu_to_le_float(float x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab_float(x) : x; +} + +INLINE uint16_t be16_to_cpu(uint16_t x) +{ + return cpu_to_be16(x); +} + +INLINE uint16_t le16_to_cpu(uint16_t x) +{ + return cpu_to_le16(x); +} + +INLINE uint32_t be32_to_cpu(uint32_t x) +{ + return cpu_to_be32(x); +} + +INLINE uint32_t le32_to_cpu(uint32_t x) +{ + return cpu_to_le32(x); +} + +INLINE uint64_t be64_to_cpu(uint64_t x) +{ + return cpu_to_be64(x); +} + +INLINE uint64_t le64_to_cpu(uint64_t x) +{ + return cpu_to_le64(x); +} + +INLINE float be_float_to_cpu(float x) +{ + return cpu_to_be_float(x); +} + +INLINE float le_float_to_cpu(float x) +{ + return cpu_to_le_float(x); +} + +INLINE uint16_t host_to_net16(uint16_t x) +{ + return cpu_to_be16(x); +} + +INLINE uint16_t net_to_host16(uint16_t x) +{ + return be16_to_cpu(x); +} + +INLINE uint32_t host_to_net32(uint32_t x) +{ + return cpu_to_be32(x); +} + +INLINE uint32_t net_to_host32(uint32_t x) +{ + return be32_to_cpu(x); +} + +INLINE uint64_t host_to_net64(uint64_t x) +{ + return cpu_to_be64(x); +} + +INLINE uint64_t net_to_host64(uint64_t x) +{ + return be64_to_cpu(x); +} + +INLINE float host_to_net_float(float x) +{ + return cpu_to_be_float(x); +} + +INLINE float net_to_host_float(float x) +{ + return be_float_to_cpu(x); +} + +#ifdef __cplusplus + +/// Type generic byte swapping. +template +INLINE T swab(T x); + +template<> INLINE uint16_t swab(uint16_t x) { return swab16(x); } +template<> INLINE uint32_t swab(uint32_t x) { return swab32(x); } +template<> INLINE uint64_t swab(uint64_t x) { return swab64(x); } +template<> INLINE int16_t swab(int16_t x) { return static_cast(swab16(static_cast(x))); } +template<> INLINE int32_t swab(int32_t x) { return static_cast(swab32(static_cast(x))); } +template<> INLINE int64_t swab(int64_t x) { return static_cast(swab64(static_cast(x))); } +template<> INLINE float swab(float x) { return swab_float(x); } + +/// Type generic conversion from CPU byte order to big-endian byte order. +template +INLINE T cpu_to_be(T x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab(x) : x; +} + +/// Type generic conversion from CPU byte-order to little-endian. +template +INLINE T cpu_to_le(T x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab(x) : x; +} + +/// Type generic conversion from big endian byte-order to CPU byte order. +template +INLINE T be_to_cpu(T x) +{ + return cpu_to_be(x); +} + +/// Type generic conversion from little-endian byte order to CPU byte order. +template +INLINE T le_to_cpu(T x) +{ + return cpu_to_le(x); +} + +/// Type generic conversion from network byte order to host byte order. +template +INLINE T net_to_host(T x) +{ + return be_to_cpu(x); +} + +/// Type generic conversion from host byte order to network byte order. +template +INLINE T host_to_net(T x) +{ + return net_to_host(x); +} + +#endif /* __cplusplus */ + +#endif /* MWARE_BYTEORDER_H */ diff --git a/bertos/cpu/pgm.h b/bertos/cpu/pgm.h new file mode 100644 index 00000000..eebe87fe --- /dev/null +++ b/bertos/cpu/pgm.h @@ -0,0 +1,211 @@ +/** + * \file + * + * + * \brief Support for reading program memory on Harvard architectures. + * + * Support is currently provided for AVR microcontrollers only. + * + * These macros allow building code twice, with and without + * pgm support (e.g.: strcpy() and strcpy_P()). + * + * Set the _PROGMEM predefine to compile in conditional + * program-memory support. + * + * + * \note This module contains code ripped out from avr-libc, + * which is distributed under a 3-clause BSD license. + */ +#ifndef MWARE_PGM_H +#define MWARE_PGM_H + +#include /* For intXX_t */ +#include +#include /* For CPU_HARVARD */ +#include /* For SIZEOF_INT */ + +#if CPU_AVR + + #ifdef __AVR_ENHANCED__ + #define pgm_read_char(addr) \ + ({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint8_t __result; \ + __asm__ \ + ( \ + "lpm %0, Z" "\n\t" \ + : "=r" (__result) \ + : "z" (__addr16) \ + ); \ + __result; \ + }) + #define pgm_read_uint16_t(addr) \ + ({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint16_t __result; \ + __asm__ \ + ( \ + "lpm %A0, Z+" "\n\t" \ + "lpm %B0, Z" "\n\t" \ + : "=r" (__result), "=z" (__addr16) \ + : "1" (__addr16) \ + ); \ + __result; \ + }) + + + #else /* !__AVR_ENHANCED__ */ + + #define pgm_read_char(addr) \ + ({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint8_t __result; \ + __asm__ \ + ( \ + "lpm" "\n\t" \ + "mov %0, r0" "\n\t" \ + : "=r" (__result) \ + : "z" (__addr16) \ + : "r0" \ + ); \ + __result; \ + }) + #define pgm_read_uint16_t(addr) \ + ({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint16_t __result; \ + __asm__ \ + ( \ + "lpm" "\n\t" \ + "mov %A0, r0" "\n\t" \ + "adiw r30, 1" "\n\t" \ + "lpm" "\n\t" \ + "mov %B0, r0" "\n\t" \ + : "=r" (__result), "=z" (__addr16) \ + : "1" (__addr16) \ + : "r0" \ + ); \ + __result; \ + }) + + #endif /* !__AVR_ENHANCED__ */ + + #if SIZEOF_INT == 2 + #define pgm_read_int(addr) ((int)pgm_read_uint16_t(addr)) + #else + #error Missing support for CPU word size != 16bit + #endif + + #ifndef PROGMEM + #define PROGMEM __attribute__((__progmem__)) + #endif + #ifndef PSTR + #define PSTR(s) ({ static const char __c[] PROGMEM = (s); &__c[0]; }) + #endif + #ifndef PFUNC + #define PFUNC(x) x ## _P + #endif + +#elif CPU_HARVARD + #error Missing CPU support +#endif + +#ifndef PSTR +#define PSTR /* nothing */ +#endif + +#ifndef PFUNC +#define PFUNC(x) x +#endif + +#ifndef PROGMEM +#define PROGMEM /* nothing */ +#endif + +/** + * \name Types for variables stored in program memory (harvard processors). + * \{ + */ +typedef PROGMEM char pgm_char; +typedef PROGMEM int8_t pgm_int8_t; +typedef PROGMEM uint8_t pgm_uint8_t; +typedef PROGMEM int16_t pgm_int16_t; +typedef PROGMEM uint16_t pgm_uint16_t; +typedef PROGMEM int32_t pgm_int32_t; +typedef PROGMEM uint32_t pgm_uint32_t; +/*\}*/ + +/** + * \name PGM support macros. + * + * These macros enable dual compilation of code for both program + * and data memory. + * + * Such a function may be defined like this: + * + * \code + * void PGM_FUNC(lcd_puts)(PGM_ATTR const char *str) + * { + * char c; + * while ((c = PGM_READ_CHAR(str++)) + * lcd_putchar(c); + * } + * \endcode + * + * The above code can be compiled twice: once with the _PROGMEM preprocessor + * symbol defined, and once without. The two object modules can then be + * linked in the same application for use by client code: + * + * \code + * lcd_puts("Hello, world!"); + * lcd_puts_P(PSTR("Hello, world!")); + * + * // To be used when invoking inside other PGM_FUNC functions: + * PGM_FUNC(lcd_puts)(some_string); + * \endcode + * + * \{ + */ +#ifdef _PROGMEM + #define PGM_READ_CHAR(s) pgm_read_char(s) + #define PGM_FUNC(x) PFUNC(x) + #define PGM_STR(x) PSTR(x) + #define PGM_ATTR PROGMEM +#else + #define PGM_READ_CHAR(s) (*(s)) + #define PGM_FUNC(x) x + #define PGM_STR(x) x + #define PGM_ATTR /* nothing */ +#endif +/* \} */ + + +#endif /* MWARE_PGM_H */ diff --git a/bertos/mware/byteorder.h b/bertos/mware/byteorder.h deleted file mode 100644 index 3dd7825e..00000000 --- a/bertos/mware/byteorder.h +++ /dev/null @@ -1,269 +0,0 @@ -/** - * \file - * - * - * \brief Functions to convert integers to/from host byte-order. - * - * \version $Id$ - * - * \author Bernie Innocenti - * \author Stefano Fedrigo - */ - -#ifndef MWARE_BYTEORDER_H -#define MWARE_BYTEORDER_H - -#include -#include - -/** - * Swap upper and lower bytes in a 16-bit value. - */ -INLINE uint16_t swab16(uint16_t x) -{ - return ((x & (uint16_t)0x00FFU) << 8) - | ((x & (uint16_t)0xFF00U) >> 8); -} - -/** - * Reverse bytes in a 32-bit value (e.g.: 0x12345678 -> 0x78563412). - */ -INLINE uint32_t swab32(uint32_t x) -{ - return ((x & (uint32_t)0x000000FFUL) << 24) - | ((x & (uint32_t)0x0000FF00UL) << 8) - | ((x & (uint32_t)0x00FF0000UL) >> 8) - | ((x & (uint32_t)0xFF000000UL) >> 24); -} - -/** - * Reverse bytes in a 64-bit value. - */ -INLINE uint64_t swab64(uint64_t x) -{ - return (uint64_t)swab32(x >> 32) - | ((uint64_t)swab32(x & 0xFFFFFFFFUL) << 32); -} - -/** - * Reverse bytes in a float value. - */ -INLINE float swab_float(float x) -{ - /* Avoid breaking strict aliasing rules. */ - char *cx = (char *)(&x); - STATIC_ASSERT(sizeof(float) == 4); - #define BYTEORDER_SWAP(a, b) ((a) ^= (b) ^= (a) ^= (b)) - BYTEORDER_SWAP(cx[0], cx[3]); - BYTEORDER_SWAP(cx[1], cx[2]); - #undef BYTEORDER_SWAP - return x; -} - -INLINE uint16_t cpu_to_be16(uint16_t x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab16(x) : x; -} - -INLINE uint16_t cpu_to_le16(uint16_t x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab16(x) : x; -} - -INLINE uint32_t cpu_to_be32(uint32_t x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab32(x) : x; -} - -INLINE uint32_t cpu_to_le32(uint32_t x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab32(x) : x; -} - -INLINE uint64_t cpu_to_be64(uint64_t x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab64(x) : x; -} - -INLINE uint64_t cpu_to_le64(uint64_t x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab64(x) : x; -} - -INLINE float cpu_to_be_float(float x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab_float(x) : x; -} - -INLINE float cpu_to_le_float(float x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab_float(x) : x; -} - -INLINE uint16_t be16_to_cpu(uint16_t x) -{ - return cpu_to_be16(x); -} - -INLINE uint16_t le16_to_cpu(uint16_t x) -{ - return cpu_to_le16(x); -} - -INLINE uint32_t be32_to_cpu(uint32_t x) -{ - return cpu_to_be32(x); -} - -INLINE uint32_t le32_to_cpu(uint32_t x) -{ - return cpu_to_le32(x); -} - -INLINE uint64_t be64_to_cpu(uint64_t x) -{ - return cpu_to_be64(x); -} - -INLINE uint64_t le64_to_cpu(uint64_t x) -{ - return cpu_to_le64(x); -} - -INLINE float be_float_to_cpu(float x) -{ - return cpu_to_be_float(x); -} - -INLINE float le_float_to_cpu(float x) -{ - return cpu_to_le_float(x); -} - -INLINE uint16_t host_to_net16(uint16_t x) -{ - return cpu_to_be16(x); -} - -INLINE uint16_t net_to_host16(uint16_t x) -{ - return be16_to_cpu(x); -} - -INLINE uint32_t host_to_net32(uint32_t x) -{ - return cpu_to_be32(x); -} - -INLINE uint32_t net_to_host32(uint32_t x) -{ - return be32_to_cpu(x); -} - -INLINE uint64_t host_to_net64(uint64_t x) -{ - return cpu_to_be64(x); -} - -INLINE uint64_t net_to_host64(uint64_t x) -{ - return be64_to_cpu(x); -} - -INLINE float host_to_net_float(float x) -{ - return cpu_to_be_float(x); -} - -INLINE float net_to_host_float(float x) -{ - return be_float_to_cpu(x); -} - -#ifdef __cplusplus - -/// Type generic byte swapping. -template -INLINE T swab(T x); - -template<> INLINE uint16_t swab(uint16_t x) { return swab16(x); } -template<> INLINE uint32_t swab(uint32_t x) { return swab32(x); } -template<> INLINE uint64_t swab(uint64_t x) { return swab64(x); } -template<> INLINE int16_t swab(int16_t x) { return static_cast(swab16(static_cast(x))); } -template<> INLINE int32_t swab(int32_t x) { return static_cast(swab32(static_cast(x))); } -template<> INLINE int64_t swab(int64_t x) { return static_cast(swab64(static_cast(x))); } -template<> INLINE float swab(float x) { return swab_float(x); } - -/// Type generic conversion from CPU byte order to big-endian byte order. -template -INLINE T cpu_to_be(T x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab(x) : x; -} - -/// Type generic conversion from CPU byte-order to little-endian. -template -INLINE T cpu_to_le(T x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab(x) : x; -} - -/// Type generic conversion from big endian byte-order to CPU byte order. -template -INLINE T be_to_cpu(T x) -{ - return cpu_to_be(x); -} - -/// Type generic conversion from little-endian byte order to CPU byte order. -template -INLINE T le_to_cpu(T x) -{ - return cpu_to_le(x); -} - -/// Type generic conversion from network byte order to host byte order. -template -INLINE T net_to_host(T x) -{ - return be_to_cpu(x); -} - -/// Type generic conversion from host byte order to network byte order. -template -INLINE T host_to_net(T x) -{ - return net_to_host(x); -} - -#endif /* __cplusplus */ - -#endif /* MWARE_BYTEORDER_H */ diff --git a/bertos/mware/pgm.h b/bertos/mware/pgm.h deleted file mode 100644 index eebe87fe..00000000 --- a/bertos/mware/pgm.h +++ /dev/null @@ -1,211 +0,0 @@ -/** - * \file - * - * - * \brief Support for reading program memory on Harvard architectures. - * - * Support is currently provided for AVR microcontrollers only. - * - * These macros allow building code twice, with and without - * pgm support (e.g.: strcpy() and strcpy_P()). - * - * Set the _PROGMEM predefine to compile in conditional - * program-memory support. - * - * - * \note This module contains code ripped out from avr-libc, - * which is distributed under a 3-clause BSD license. - */ -#ifndef MWARE_PGM_H -#define MWARE_PGM_H - -#include /* For intXX_t */ -#include -#include /* For CPU_HARVARD */ -#include /* For SIZEOF_INT */ - -#if CPU_AVR - - #ifdef __AVR_ENHANCED__ - #define pgm_read_char(addr) \ - ({ \ - uint16_t __addr16 = (uint16_t)(addr); \ - uint8_t __result; \ - __asm__ \ - ( \ - "lpm %0, Z" "\n\t" \ - : "=r" (__result) \ - : "z" (__addr16) \ - ); \ - __result; \ - }) - #define pgm_read_uint16_t(addr) \ - ({ \ - uint16_t __addr16 = (uint16_t)(addr); \ - uint16_t __result; \ - __asm__ \ - ( \ - "lpm %A0, Z+" "\n\t" \ - "lpm %B0, Z" "\n\t" \ - : "=r" (__result), "=z" (__addr16) \ - : "1" (__addr16) \ - ); \ - __result; \ - }) - - - #else /* !__AVR_ENHANCED__ */ - - #define pgm_read_char(addr) \ - ({ \ - uint16_t __addr16 = (uint16_t)(addr); \ - uint8_t __result; \ - __asm__ \ - ( \ - "lpm" "\n\t" \ - "mov %0, r0" "\n\t" \ - : "=r" (__result) \ - : "z" (__addr16) \ - : "r0" \ - ); \ - __result; \ - }) - #define pgm_read_uint16_t(addr) \ - ({ \ - uint16_t __addr16 = (uint16_t)(addr); \ - uint16_t __result; \ - __asm__ \ - ( \ - "lpm" "\n\t" \ - "mov %A0, r0" "\n\t" \ - "adiw r30, 1" "\n\t" \ - "lpm" "\n\t" \ - "mov %B0, r0" "\n\t" \ - : "=r" (__result), "=z" (__addr16) \ - : "1" (__addr16) \ - : "r0" \ - ); \ - __result; \ - }) - - #endif /* !__AVR_ENHANCED__ */ - - #if SIZEOF_INT == 2 - #define pgm_read_int(addr) ((int)pgm_read_uint16_t(addr)) - #else - #error Missing support for CPU word size != 16bit - #endif - - #ifndef PROGMEM - #define PROGMEM __attribute__((__progmem__)) - #endif - #ifndef PSTR - #define PSTR(s) ({ static const char __c[] PROGMEM = (s); &__c[0]; }) - #endif - #ifndef PFUNC - #define PFUNC(x) x ## _P - #endif - -#elif CPU_HARVARD - #error Missing CPU support -#endif - -#ifndef PSTR -#define PSTR /* nothing */ -#endif - -#ifndef PFUNC -#define PFUNC(x) x -#endif - -#ifndef PROGMEM -#define PROGMEM /* nothing */ -#endif - -/** - * \name Types for variables stored in program memory (harvard processors). - * \{ - */ -typedef PROGMEM char pgm_char; -typedef PROGMEM int8_t pgm_int8_t; -typedef PROGMEM uint8_t pgm_uint8_t; -typedef PROGMEM int16_t pgm_int16_t; -typedef PROGMEM uint16_t pgm_uint16_t; -typedef PROGMEM int32_t pgm_int32_t; -typedef PROGMEM uint32_t pgm_uint32_t; -/*\}*/ - -/** - * \name PGM support macros. - * - * These macros enable dual compilation of code for both program - * and data memory. - * - * Such a function may be defined like this: - * - * \code - * void PGM_FUNC(lcd_puts)(PGM_ATTR const char *str) - * { - * char c; - * while ((c = PGM_READ_CHAR(str++)) - * lcd_putchar(c); - * } - * \endcode - * - * The above code can be compiled twice: once with the _PROGMEM preprocessor - * symbol defined, and once without. The two object modules can then be - * linked in the same application for use by client code: - * - * \code - * lcd_puts("Hello, world!"); - * lcd_puts_P(PSTR("Hello, world!")); - * - * // To be used when invoking inside other PGM_FUNC functions: - * PGM_FUNC(lcd_puts)(some_string); - * \endcode - * - * \{ - */ -#ifdef _PROGMEM - #define PGM_READ_CHAR(s) pgm_read_char(s) - #define PGM_FUNC(x) PFUNC(x) - #define PGM_STR(x) PSTR(x) - #define PGM_ATTR PROGMEM -#else - #define PGM_READ_CHAR(s) (*(s)) - #define PGM_FUNC(x) x - #define PGM_STR(x) x - #define PGM_ATTR /* nothing */ -#endif -/* \} */ - - -#endif /* MWARE_PGM_H */