From c0c3280d1271b8088d55a544fedf5b1b1baad36f Mon Sep 17 00:00:00 2001
From: Angus Gratton <gus@projectgus.com>
Date: Sat, 28 Nov 2015 18:01:03 +1100
Subject: [PATCH] Removed INLINED (force inline) macro.

Progress towards #57.
---
 core/esp_iomux.c                              | 19 ++++----
 core/include/common_macros.h                  | 24 +++++++++-
 core/include/esp/gpio.h                       | 41 +++--------------
 core/include/esp/interrupts.h                 | 14 +++---
 core/include/esp/iomux.h                      |  8 +---
 core/include/esp/iomux_private.h              | 46 -------------------
 examples/blink/blink.c                        | 11 ++---
 .../unaligned_load/unaligned_load.c           |  2 +-
 8 files changed, 55 insertions(+), 110 deletions(-)
 delete mode 100644 core/include/esp/iomux_private.h

diff --git a/core/esp_iomux.c b/core/esp_iomux.c
index fb4ec67..414da19 100644
--- a/core/esp_iomux.c
+++ b/core/esp_iomux.c
@@ -7,14 +7,15 @@
 #include "esp/iomux.h"
 #include "common_macros.h"
 
-/* These are non-static versions of the GPIO mapping tables in
-   iomux.h, so if they need to be linked only one copy is linked for
-   the entire program.
+const static IRAM_DATA uint32_t IOMUX_TO_GPIO[] = { 12, 13, 14, 15, 3, 1, 6, 7, 8, 9, 10, 11, 0, 2, 4, 5 };
+const static IRAM_DATA uint32_t GPIO_TO_IOMUX[] = { 12, 5, 13, 4, 14, 15, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3 };
 
-   These are only ever linked in if the arguments to gpio_to_ionum
-   or ionum_to_gpio are not known at compile time.
+uint8_t IRAM gpio_to_iomux(const uint8_t gpio_number)
+{
+    return GPIO_TO_IOMUX[gpio_number];
+}
 
-   Arrays are declared as 32-bit integers in IROM to save RAM.
-*/
-const IROM uint32_t GPIO_TO_IOMUX_MAP[] = _GPIO_TO_IOMUX;
-const IROM uint32_t IOMUX_TO_GPIO_MAP[] = _IOMUX_TO_GPIO;
+uint8_t IRAM iomux_to_gpio(const uint8_t iomux_number)
+{
+    return IOMUX_TO_GPIO[iomux_number];
+}
diff --git a/core/include/common_macros.h b/core/include/common_macros.h
index 355248b..7c6dd56 100644
--- a/core/include/common_macros.h
+++ b/core/include/common_macros.h
@@ -53,8 +53,30 @@
     #define IROM __attribute__((section(".irom0.literal"))) const
 #endif
 
-#define INLINED inline static __attribute__((always_inline)) __attribute__((unused))
+/* Use this macro to place functions into Instruction RAM (IRAM)
+   instead of flash memory (IROM).
 
+   This is useful 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.
+
+   Bear in mind IRAM is limited (32KB), compared to up to 1MB of flash.
+*/
 #define IRAM __attribute__((section(".iram1.text")))
 
+/* Use this macro to place read-only data into Instruction RAM (IRAM)
+   instead of loaded into rodata which resides in DRAM.
+
+   This may be useful to free up data RAM. However all data read from
+   the instruction space must be 32-bit aligned word reads
+   (non-aligned reads will use an interrupt routine to "fix" them and
+   still work, but are very slow..
+*/
+#ifdef	__cplusplus
+    #define IRAM_DATA __attribute__((section(".iram1.rodata")))
+#else
+    #define IRAM_DATA __attribute__((section(".iram1.rodata"))) const
+#endif
+
 #endif
diff --git a/core/include/esp/gpio.h b/core/include/esp/gpio.h
index da7bcfa..b5efcaf 100644
--- a/core/include/esp/gpio.h
+++ b/core/include/esp/gpio.h
@@ -23,41 +23,14 @@ typedef enum {
 /* Enable GPIO on the specified pin, and set it to input/output/ with
  *  pullup as needed
  */
-INLINED void gpio_enable(const uint8_t gpio_num, const gpio_direction_t direction)
-{
-    uint32_t iomux_flags;
-
-    switch(direction) {
-    case GPIO_INPUT:
-        iomux_flags = 0;
-        break;
-    case GPIO_OUTPUT:
-        iomux_flags = IOMUX_PIN_OUTPUT_ENABLE;
-        break;
-    case GPIO_OUT_OPEN_DRAIN:
-        iomux_flags = IOMUX_PIN_OUTPUT_ENABLE;
-        break;
-    case GPIO_INPUT_PULLUP:
-        iomux_flags = IOMUX_PIN_PULLUP;
-        break;
-    }
-    iomux_set_gpio_function(gpio_num, iomux_flags);
-    if(direction == GPIO_OUT_OPEN_DRAIN)
-        GPIO.CONF[gpio_num] |= GPIO_CONF_OPEN_DRAIN;
-    else
-        GPIO.CONF[gpio_num] &= ~GPIO_CONF_OPEN_DRAIN;
-    if (iomux_flags & IOMUX_PIN_OUTPUT_ENABLE)
-        GPIO.ENABLE_OUT_SET = BIT(gpio_num);
-    else
-        GPIO.ENABLE_OUT_CLEAR = BIT(gpio_num);
-}
+void gpio_enable(const uint8_t gpio_num, const gpio_direction_t direction);
 
 /* Disable GPIO on the specified pin, and set it Hi-Z.
  *
  * If later muxing this pin to a different function, make sure to set
  * IOMUX_PIN_OUTPUT_ENABLE if necessary to enable the output buffer.
  */
-INLINED void gpio_disable(const uint8_t gpio_num)
+static inline void gpio_disable(const uint8_t gpio_num)
 {
     GPIO.ENABLE_OUT_CLEAR = BIT(gpio_num);
     *gpio_iomux_reg(gpio_num) &= ~IOMUX_PIN_OUTPUT_ENABLE;
@@ -67,7 +40,7 @@ INLINED void gpio_disable(const uint8_t gpio_num)
  *
  * Only works if pin has been set to GPIO_OUTPUT via gpio_enable()
  */
-INLINED void gpio_write(const uint8_t gpio_num, const bool set)
+static inline void gpio_write(const uint8_t gpio_num, const bool set)
 {
     if(set)
         GPIO.OUT_SET = BIT(gpio_num);
@@ -79,7 +52,7 @@ INLINED void gpio_write(const uint8_t gpio_num, const bool set)
  *
  * Only works if pin has been set to GPIO_OUTPUT via gpio_enable()
  */
-INLINED void gpio_toggle(const uint8_t gpio_num)
+static inline void gpio_toggle(const uint8_t gpio_num)
 {
     /* Why implement like this instead of GPIO_OUT_REG ^= xxx?
        Concurrency. If an interrupt or higher priority task writes to
@@ -98,7 +71,7 @@ INLINED void gpio_toggle(const uint8_t gpio_num)
  * If pin is set as an input, this reads the value on the pin.
  * If pin is set as an output, this reads the last value written to the pin.
  */
-INLINED bool gpio_read(const uint8_t gpio_num)
+static inline bool gpio_read(const uint8_t gpio_num)
 {
     return GPIO.IN & BIT(gpio_num);
 }
@@ -109,7 +82,7 @@ extern void gpio_interrupt_handler(void);
  *
  * If int_type is not GPIO_INTTYPE_NONE, the gpio_interrupt_handler will be attached and unmasked.
  */
-INLINED void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type)
+static inline void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type)
 {
     GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type);
     if(int_type != GPIO_INTTYPE_NONE) {
@@ -119,7 +92,7 @@ INLINED void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int
 }
 
 /* Return the interrupt type set for a pin */
-INLINED gpio_inttype_t gpio_get_interrupt(const uint8_t gpio_num)
+static inline gpio_inttype_t gpio_get_interrupt(const uint8_t gpio_num)
 {
     return (gpio_inttype_t)FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_num]);
 }
diff --git a/core/include/esp/interrupts.h b/core/include/esp/interrupts.h
index 55a115c..a6e779a 100644
--- a/core/include/esp/interrupts.h
+++ b/core/include/esp/interrupts.h
@@ -39,7 +39,7 @@ void sdk__xt_tick_timer_init (void);
 void sdk__xt_timer_int(void);
 void sdk__xt_timer_int1(void);
 
-INLINED uint32_t _xt_get_intlevel(void)
+static inline uint32_t _xt_get_intlevel(void)
 {
     uint32_t level;
     __asm__ volatile("rsr %0, intlevel" : "=a"(level));
@@ -53,7 +53,7 @@ INLINED uint32_t _xt_get_intlevel(void)
    portDISABLE_INTERRUPTS/portENABLE_INTERRUPTS for
    non-FreeRTOS & non-portable code.
 */
-INLINED uint32_t _xt_disable_interrupts(void)
+static inline uint32_t _xt_disable_interrupts(void)
 {
     uint32_t old_level;
     __asm__ volatile ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) : "=a" (old_level));
@@ -61,14 +61,14 @@ INLINED uint32_t _xt_disable_interrupts(void)
 }
 
 /* Restore PS level. Intended to be used with _xt_disable_interrupts */
-INLINED void _xt_restore_interrupts(uint32_t new_ps)
+static inline void _xt_restore_interrupts(uint32_t new_ps)
 {
     __asm__ volatile ("wsr %0, ps; rsync" :: "a" (new_ps));
 }
 
 /* ESPTODO: the mask/unmask functions aren't thread safe */
 
-INLINED void _xt_isr_unmask(uint32_t unmask)
+static inline void _xt_isr_unmask(uint32_t unmask)
 {
     uint32_t intenable;
     asm volatile ("rsr %0, intenable" : "=a" (intenable));
@@ -76,7 +76,7 @@ INLINED void _xt_isr_unmask(uint32_t unmask)
     asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
 }
 
-INLINED void _xt_isr_mask (uint32_t mask)
+static inline void _xt_isr_mask (uint32_t mask)
 {
     uint32_t intenable;
     asm volatile ("rsr %0, intenable" : "=a" (intenable));
@@ -84,14 +84,14 @@ INLINED void _xt_isr_mask (uint32_t mask)
     asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
 }
 
-INLINED uint32_t _xt_read_ints (void)
+static inline uint32_t _xt_read_ints (void)
 {
     uint32_t interrupt;
     asm volatile ("rsr %0, interrupt" : "=a" (interrupt));
     return interrupt;
 }
 
-INLINED void _xt_clear_ints(uint32_t mask)
+static inline void _xt_clear_ints(uint32_t mask)
 {
     asm volatile ("wsr %0, intclear; esync" :: "a" (mask));
 }
diff --git a/core/include/esp/iomux.h b/core/include/esp/iomux.h
index a893f4e..214c9e8 100644
--- a/core/include/esp/iomux.h
+++ b/core/include/esp/iomux.h
@@ -22,7 +22,7 @@ extern "C" {
  * known at compile time, or return the result from a lookup table if not.
  *
  */
-inline static uint8_t gpio_to_iomux(const uint8_t gpio_number);
+uint8_t IRAM gpio_to_iomux(const uint8_t gpio_number);
 
 /**
  * Convert an iomux register index to a GPIO pin number.
@@ -31,7 +31,7 @@ inline static uint8_t gpio_to_iomux(const uint8_t gpio_number);
  * known at compile time, or return the result from a lookup table if not.
  *
  */
-inline static uint8_t iomux_to_gpio(const uint8_t iomux_num);
+uint8_t IRAM iomux_to_gpio(const uint8_t iomux_num);
 
 /**
  * Directly get the IOMUX register for a particular gpio number
@@ -64,10 +64,6 @@ inline static void iomux_set_gpio_function(const uint8_t gpio_number, const uint
     IOMUX.PIN[reg_idx] = func | flags;
 }
 
-/* esp_iomux_private contains implementation parts of the inline functions
-   declared above */
-#include "esp/iomux_private.h"
-
 #ifdef	__cplusplus
 }
 #endif
diff --git a/core/include/esp/iomux_private.h b/core/include/esp/iomux_private.h
deleted file mode 100644
index d3cb780..0000000
--- a/core/include/esp/iomux_private.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/** esp/iomux_private.h
- *
- * Private implementation parts of iomux registers. In headers to
- * allow compile-time optimisations.
- *
- * Part of esp-open-rtos
- * Copyright (C) 2015 Superhouse Automation Pty Ltd
- * BSD Licensed as described in the file LICENSE
- */
-
-/* Mapping from register index to GPIO and from GPIO index to register
-   number. DO NOT USE THESE IN YOUR CODE, call gpio_to_iomux(xxx) or
-   iomux_to_gpio(xxx) instead.
-*/
-#ifndef _IOMUX_PRIVATE
-#define _IOMUX_PRIVATE
-
-#include "common_macros.h"
-
-#define _IOMUX_TO_GPIO { 12, 13, 14, 15, 3, 1, 6, 7, 8, 9, 10, 11, 0, 2, 4, 5 }
-#define _GPIO_TO_IOMUX { 12, 5, 13, 4, 14, 15, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3 }
-
-extern const IROM uint32_t GPIO_TO_IOMUX_MAP[];
-extern const IROM uint32_t IOMUX_TO_GPIO_MAP[];
-
-INLINED uint8_t gpio_to_iomux(const uint8_t gpio_number)
-{
-    if(__builtin_constant_p(gpio_number)) {
-        static const uint8_t _regs[] = _GPIO_TO_IOMUX;
-        return _regs[gpio_number];
-    } else {
-        return GPIO_TO_IOMUX_MAP[gpio_number];
-    }
-}
-
-INLINED uint8_t iomux_to_gpio(const uint8_t iomux_number)
-{
-    if(__builtin_constant_p(iomux_number)) {
-        static const uint8_t _regs[] = _IOMUX_TO_GPIO;
-        return _regs[iomux_number];
-    } else {
-        return IOMUX_TO_GPIO_MAP[iomux_number];
-    }
-}
-
-#endif
diff --git a/examples/blink/blink.c b/examples/blink/blink.c
index 00388b5..92fe700 100644
--- a/examples/blink/blink.c
+++ b/examples/blink/blink.c
@@ -12,9 +12,6 @@ const int gpio = 14;
 
 /* This task uses the high level GPIO API (esp_gpio.h) to blink an LED.
  *
- * Even though it reads better than the register-level version in blinkenRegisterTask,
- * they compile to the exact same instructions (except gpio_enable also set the output type in
- * the GPIO control register).
  */
 void blinkenTask(void *pvParameters)
 {
@@ -28,10 +25,12 @@ void blinkenTask(void *pvParameters)
 }
 
 
-/* This task uses all raw register operations to set the pins.
+/* This task demonstrates an alternative way to use raw register
+   operations to blink an LED.
 
-   It's not fully parameterised, as the IOMUX_GPIO# macros involve a non-linear
-   mapping from GPIO to IOMUX ports.
+   The step that sets the iomux register can't be automatically
+   updated from the 'gpio' constant variable, so you need to change
+   the line that sets IOMUX_GPIO14 if you change 'gpio'.
 
    There is no significant performance benefit to this way over the
    blinkenTask version, so it's probably better to use the blinkenTask
diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c
index 48016af..258b4d0 100644
--- a/examples/experiments/unaligned_load/unaligned_load.c
+++ b/examples/experiments/unaligned_load/unaligned_load.c
@@ -17,7 +17,7 @@ const char *dramtest = TESTSTRING;
 const __attribute__((section(".iram1.notrodata"))) char iramtest[] = TESTSTRING;
 const __attribute__((section(".text.notrodata"))) char iromtest[] = TESTSTRING;
 
-INLINED uint32_t get_ccount (void)
+static inline uint32_t get_ccount (void)
 {
     uint32_t ccount;
     asm volatile ("rsr.ccount %0" : "=a" (ccount));