From 822533fd922f2c67169599b472605c87569c1f2d Mon Sep 17 00:00:00 2001 From: Angus Gratton <gus@projectgus.com> Date: Mon, 8 Jun 2015 18:00:44 +1000 Subject: [PATCH] Interrupt support refactor Write inline versions for SDK-based interrupt convenience functions. --- FreeRTOS/Source/portable/esp8266/port.c | 40 ++++++++++----- FreeRTOS/Source/portable/esp8266/portmacro.h | 14 +----- core/include/esp/cpu.h | 26 ++++++++++ core/include/esp8266.h | 1 + include/xtensa_interrupts.h | 53 ++++++++++++++++++++ 5 files changed, 109 insertions(+), 25 deletions(-) create mode 100644 core/include/esp/cpu.h create mode 100644 include/xtensa_interrupts.h diff --git a/FreeRTOS/Source/portable/esp8266/port.c b/FreeRTOS/Source/portable/esp8266/port.c index d40340e..ae2b579 100644 --- a/FreeRTOS/Source/portable/esp8266/port.c +++ b/FreeRTOS/Source/portable/esp8266/port.c @@ -131,7 +131,7 @@ void IRAM PendSV(enum SVC_ReqType req) else if(req == SVC_MACLayer) pending_maclayer_sv= 1; - xthal_set_intset(1<<ETS_SOFT_INUM); + xthal_set_intset(BIT(INUM_SOFT)); vPortExitCritical(); } @@ -162,7 +162,6 @@ void xPortSysTickHandle (void) { if(xTaskIncrementTick() !=pdFALSE ) { - //GPIO_REG_WRITE(GPIO_STATUS_W1TS_ADDRESS, 0x40); vTaskSwitchContext(); } } @@ -174,8 +173,8 @@ void xPortSysTickHandle (void) */ portBASE_TYPE xPortStartScheduler( void ) { - _xt_isr_attach(ETS_SOFT_INUM, SV_ISR); - sdk__xt_isr_unmask(1<<ETS_SOFT_INUM); + _xt_isr_attach(INUM_SOFT, SV_ISR); + _xt_isr_unmask(BIT(INUM_SOFT)); /* Initialize system tick timer interrupt and schedule the first tick. */ sdk__xt_tick_timer_init(); @@ -236,25 +235,42 @@ void _xt_isr_attach(uint8_t i, _xt_isr func) isr[i] = func; } -uint16_t _xt_isr_handler(uint16_t i) +uint16_t IRAM _xt_isr_handler(uint16_t i) { uint8_t index; - if (i & (1 << ETS_WDT_INUM)) { - index = ETS_WDT_INUM; + /* I think this is implementing some kind of interrupt priority or + short-circuiting an expensive ffs for most common interrupts - ie + WDT And GPIO are common or high priority, then remaining flags. + */ + if (i & (1 << INUM_WDT)) { + index = INUM_WDT; } - else if (i & (1 << ETS_GPIO_INUM)) { - index = ETS_GPIO_INUM; + else if (i & (1 << INUM_GPIO)) { + index = INUM_GPIO; }else { index = __builtin_ffs(i) - 1; - if (index == ETS_MAX_INUM) { - i &= ~(1 << ETS_MAX_INUM); + if (index == INUM_MAX) { + /* I don't understand what happens here. INUM_MAX is not + the highest interrupt number listed (and the isr array + has 16 entries). + + Clearing that flag and then setting index to + __builtin_ffs(i)-1 may result in index == 255 if no + higher flags are set, unless this is guarded against + somehow by the caller? + + I also don't understand why the code is written like + this in esp_iot_rtos_sdk instead of just putting the i + &= line near the top... Probably no good reason? + */ + i &= ~(1 << INUM_MAX); index = __builtin_ffs(i) - 1; } } - sdk__xt_clear_ints(1<<index); + _xt_clear_ints(1<<index); isr[index](); diff --git a/FreeRTOS/Source/portable/esp8266/portmacro.h b/FreeRTOS/Source/portable/esp8266/portmacro.h index 1391275..242c253 100644 --- a/FreeRTOS/Source/portable/esp8266/portmacro.h +++ b/FreeRTOS/Source/portable/esp8266/portmacro.h @@ -75,6 +75,7 @@ extern "C" { #include <stdint.h> #include <xtruntime.h> #include "xtensa_rtos.h" +#include "xtensa_interrupts.h" /*----------------------------------------------------------- * Port specific definitions for ESP8266 @@ -187,19 +188,6 @@ not necessary for to use this port. They are defined so the common demo files /* ESPTODO: These parts of the FreeRTOS support are still in binary libraries */ #define vApplicationStackOverflowHook sdk_vApplicationStackOverflowHook -/* XTensa interrupt management functions, used in port.c. - Some (w/ sdk_ prefix) are implemented in blob libs */ -void sdk__xt_int_exit (void); -void sdk__xt_user_exit (void); -void sdk__xt_tick_timer_init (void); -void sdk__xt_isr_unmask (uint32_t unmask); -void sdk__xt_isr_mask (uint32_t mask); -uint32_t sdk__xt_read_ints (void); -void sdk__xt_clear_ints(uint32_t mask); -typedef void (* _xt_isr)(void); -void _xt_isr_attach (uint8_t i, _xt_isr func); -void sdk__xt_timer_int1(void); - #ifdef __cplusplus } #endif diff --git a/core/include/esp/cpu.h b/core/include/esp/cpu.h new file mode 100644 index 0000000..0a029c8 --- /dev/null +++ b/core/include/esp/cpu.h @@ -0,0 +1,26 @@ +/* esp/cpu.h + * + * Details relating to the ESP8266 Xtensa core. + * + */ +#ifndef _ESP_CPU_H +#define _ESP_CPU_H + +/* Interrupt numbers for level 1 exception handler. + * + * Currently the UserExceptionVector calls down to _xt_isr_handler, + * defined in port.c, for at least some of these interrupts. Some are handled + * on the SDK side, though. + */ +typedef enum { + INUM_SPI = 2, + INUM_GPIO = 4, + INUM_UART = 5, + INUM_MAX = 6, + INUM_SOFT = 7, + INUM_WDT = 8, + INUM_FRC_TIMER1 = 9, +} xt_isr_num_t; + +#endif + diff --git a/core/include/esp8266.h b/core/include/esp8266.h index ce7a4c7..f6ede41 100644 --- a/core/include/esp8266.h +++ b/core/include/esp8266.h @@ -13,6 +13,7 @@ #include "common_macros.h" #include "esp/registers.h" +#include "esp/cpu.h" #include "esp/iomux.h" #include "esp/gpio.h" diff --git a/include/xtensa_interrupts.h b/include/xtensa_interrupts.h new file mode 100644 index 0000000..f2c75f8 --- /dev/null +++ b/include/xtensa_interrupts.h @@ -0,0 +1,53 @@ +/* Xtensa interrupt management functions + * + * Some (w/ sdk_ prefix) are implemented in binary libs, rest are + * inlines replacing functions in the binary libraries. + * + * Part of esp-open-rtos + * Copyright (C) 2015 Superhouse Automation Pty Ltd + * BSD Licensed as described in the file LICENSE + */ +#ifndef _XTENSA_INTERRUPTS_H +#define _XTENSA_INTERRUPTS_H +#include <stdint.h> +#include <xtensa/hal.h> + +void sdk__xt_int_exit (void); +void sdk__xt_user_exit (void); +void sdk__xt_tick_timer_init (void); +void sdk__xt_timer_int1(void); + +INLINED void _xt_isr_unmask (uint32_t unmask) +{ + uint32_t intenable; + asm volatile ("rsr %0, intenable" : "=a" (intenable)); + intenable |= unmask; + asm volatile ("wsr %0, intenable" :: "a" (intenable)); +} + +INLINED void _xt_isr_mask (uint32_t mask) +{ + uint32_t intenable; + asm volatile ("rsr %0, intenable" : "=a" (intenable)); + intenable &= ~mask; + asm volatile ("wsr %0, intenable" :: "a" (intenable)); +} + +INLINED 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) +{ + asm volatile ("wsr %0, intclear" :: "a" (mask)); +} + +typedef void (* _xt_isr)(void); +/* This function is implemeneted in FreeRTOS port.c at the moment, + should be moved or converted to an inline */ +void _xt_isr_attach (uint8_t i, _xt_isr func); + +#endif