2015-06-05 01:46:25 +00:00
|
|
|
/* Some common compiler macros
|
2015-05-30 09:11:04 +00:00
|
|
|
*
|
2015-06-05 01:46:25 +00:00
|
|
|
* Not esp8266-specific.
|
2015-05-30 09:11:04 +00:00
|
|
|
*
|
2015-06-02 05:06:40 +00:00
|
|
|
* Part of esp-open-rtos
|
2015-06-05 01:46:25 +00:00
|
|
|
* Copyright (C) 2015 Superhouse Automation Pty Ltd
|
2015-05-30 09:11:04 +00:00
|
|
|
* BSD Licensed as described in the file LICENSE
|
|
|
|
*/
|
|
|
|
|
2015-06-05 01:46:25 +00:00
|
|
|
#ifndef _COMMON_MACROS_H
|
|
|
|
#define _COMMON_MACROS_H
|
|
|
|
|
2015-08-26 01:11:31 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
|
2015-06-05 01:46:25 +00:00
|
|
|
#define UNUSED __attributed((unused))
|
|
|
|
|
|
|
|
#ifndef BIT
|
2015-06-17 23:00:02 +00:00
|
|
|
#define BIT(X) (1<<(X))
|
2015-06-05 01:46:25 +00:00
|
|
|
#endif
|
2015-05-30 09:11:04 +00:00
|
|
|
|
2015-08-19 00:38:31 +00:00
|
|
|
/* These macros convert values to/from bitfields specified by *_M and *_S (mask
|
|
|
|
* and shift) constants. Used primarily with ESP8266 register access.
|
|
|
|
*/
|
|
|
|
|
2015-08-26 00:07:06 +00:00
|
|
|
#define VAL2FIELD(fieldname, value) ((value) << fieldname##_S)
|
2015-08-19 00:38:31 +00:00
|
|
|
#define FIELD2VAL(fieldname, regbits) (((regbits) >> fieldname##_S) & fieldname##_M)
|
|
|
|
|
2015-08-19 05:46:25 +00:00
|
|
|
#define FIELD_MASK(fieldname) (fieldname##_M << fieldname##_S)
|
|
|
|
#define SET_FIELD(regbits, fieldname, value) (((regbits) & ~FIELD_MASK(fieldname)) | VAL2FIELD(fieldname, value))
|
2015-08-19 00:38:31 +00:00
|
|
|
|
2015-08-26 00:07:06 +00:00
|
|
|
/* VAL2FIELD/SET_FIELD do not normally check to make sure that the passed value
|
|
|
|
* will fit in the specified field (without clobbering other bits). This makes
|
|
|
|
* them faster and is usually fine. If you do need to make sure that the value
|
|
|
|
* will not overflow the field, use VAL2FIELD_M or SET_FIELD_M (which will
|
|
|
|
* first mask the supplied value to only the allowed number of bits) instead.
|
|
|
|
*/
|
|
|
|
#define VAL2FIELD_M(fieldname, value) (((value) & fieldname##_M) << fieldname##_S)
|
|
|
|
#define SET_FIELD_M(regbits, fieldname, value) (((regbits) & ~FIELD_MASK(fieldname)) | VAL2FIELD_M(fieldname, value))
|
|
|
|
|
2016-08-16 07:10:35 +00:00
|
|
|
/* Set bits in reg with specified mask.
|
|
|
|
*/
|
|
|
|
#define SET_MASK_BITS(reg, mask) (reg) |= (mask)
|
|
|
|
|
|
|
|
/* Clear bits in reg with specified mask
|
|
|
|
*/
|
|
|
|
#define CLEAR_MASK_BITS(reg, mask) (reg) &= ~(mask)
|
|
|
|
|
2016-05-28 02:29:28 +00:00
|
|
|
/* Use the IRAM macro to place functions into Instruction RAM (IRAM)
|
|
|
|
instead of flash (aka irom).
|
2015-05-30 09:11:04 +00:00
|
|
|
|
2016-05-28 02:29:28 +00:00
|
|
|
(This is the opposite to the Espressif SDK, where functions default
|
|
|
|
to being placed in IRAM but the ICACHE_FLASH_ATTR attribute will
|
|
|
|
place them in flash.)
|
2015-05-30 09:11:04 +00:00
|
|
|
|
2016-05-28 02:29:28 +00:00
|
|
|
Use the IRAM attribute for functions which are called when the
|
|
|
|
flash may not be available (for example during NMI exceptions), or
|
|
|
|
for functions which are called very frequently and need high
|
|
|
|
performance.
|
2015-05-30 09:11:04 +00:00
|
|
|
|
2016-05-28 02:29:28 +00:00
|
|
|
Usage example:
|
2015-05-30 09:11:04 +00:00
|
|
|
|
2016-05-28 02:29:28 +00:00
|
|
|
void IRAM high_performance_function(void)
|
|
|
|
{
|
|
|
|
// do important thing here
|
|
|
|
}
|
2015-11-28 07:01:03 +00:00
|
|
|
|
|
|
|
Bear in mind IRAM is limited (32KB), compared to up to 1MB of flash.
|
|
|
|
*/
|
2015-06-08 07:54:46 +00:00
|
|
|
#define IRAM __attribute__((section(".iram1.text")))
|
|
|
|
|
2016-05-28 02:29:28 +00:00
|
|
|
/* Use the RAM macro to place constant data (rodata) into RAM (data
|
|
|
|
RAM) instead of the default placement in flash. This is useful for
|
|
|
|
constant data which needs high performance access.
|
|
|
|
|
|
|
|
Usage example:
|
|
|
|
|
|
|
|
const RAM uint8_t constants[] = { 1, 2, 3, 7 };
|
2015-11-28 07:01:03 +00:00
|
|
|
|
2016-05-28 02:29:28 +00:00
|
|
|
When placing string literals in RAM, they need to be declared with
|
|
|
|
the type "const char[]" not "const char *"
|
|
|
|
|
|
|
|
Usage example:
|
|
|
|
|
|
|
|
const RAM char hello_world[] = "Hello World";
|
|
|
|
*/
|
|
|
|
#define RAM __attribute__((section(".data")))
|
|
|
|
|
|
|
|
/* Use the IRAM_DATA macro to place data into Instruction RAM (IRAM)
|
|
|
|
instead of the default of flash (for constant data) or data RAM
|
|
|
|
(for non-constant data).
|
2016-05-16 23:08:53 +00:00
|
|
|
|
2015-11-28 07:01:03 +00:00
|
|
|
This may be useful to free up data RAM. However all data read from
|
2016-05-28 02:29:28 +00:00
|
|
|
any instruction space (either IRAM or Flash) must be 32-bit aligned
|
|
|
|
word reads. Reading unaligned data stored with IRAM_DATA will be
|
|
|
|
slower than reading data stored in RAM. You can't perform unaligned
|
|
|
|
writes to IRAM.
|
|
|
|
*/
|
|
|
|
#define IRAM_DATA __attribute__((section(".iram1.data")))
|
|
|
|
|
|
|
|
/* Use the IROM macro to store constant values in IROM flash. In
|
|
|
|
esp-open-rtos this is already the default location for most constant
|
|
|
|
data (rodata), so you don't need this attribute in 99% of cases.
|
|
|
|
|
|
|
|
The exceptions are to mark data in the core & freertos libraries,
|
|
|
|
where the default for constant data storage is RAM.
|
|
|
|
|
|
|
|
(Unlike the Espressif SDK you don't need to use an attribute like
|
|
|
|
ICACHE_FLASH_ATTR for functions, they go into flash by default.)
|
|
|
|
|
|
|
|
Important to note: IROM flash is accessed via 32-bit word aligned
|
|
|
|
reads. esp-open-rtos does some magic to "fix" unaligned reads, but
|
|
|
|
performance is reduced.
|
2015-11-28 07:01:03 +00:00
|
|
|
*/
|
2016-05-28 02:29:28 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
#define IROM __attribute__((section(".irom0.literal")))
|
|
|
|
#else
|
|
|
|
#define IROM __attribute__((section(".irom0.literal"))) const
|
|
|
|
#endif
|
|
|
|
|
2015-11-28 07:01:03 +00:00
|
|
|
|
2015-05-30 09:11:04 +00:00
|
|
|
#endif
|