From 913188fdf39f8c04789a142a9ff52841255fa178 Mon Sep 17 00:00:00 2001 From: dongheng Date: Wed, 27 Mar 2019 16:28:22 +0800 Subject: [PATCH] feat(freertos): Simplify xtensa platform code All normal ISRs are called by "_xt_isr_handler". --- components/esp8266/include/driver/soc.h | 65 +++++++ .../esp8266/include/esp8266/eagle_soc.h | 1 + components/esp8266/include/rom/ets_sys.h | 1 + components/esp8266/source/task_wdt.c | 3 +- .../port/esp8266/include/freertos/portmacro.h | 2 - .../esp8266/include/freertos/xtensa_timer.h | 1 - components/freertos/port/esp8266/os_cpu_a.S | 167 +++--------------- components/freertos/port/esp8266/port.c | 65 +++---- .../freertos/port/esp8266/xtensa_init.c | 54 ------ .../freertos/port/esp8266/xtensa_vectors.S | 31 +--- 10 files changed, 125 insertions(+), 265 deletions(-) delete mode 100644 components/freertos/port/esp8266/xtensa_init.c diff --git a/components/esp8266/include/driver/soc.h b/components/esp8266/include/driver/soc.h index 10d9b88b..cbbfcd6b 100644 --- a/components/esp8266/include/driver/soc.h +++ b/components/esp8266/include/driver/soc.h @@ -20,6 +20,7 @@ extern "C" { #endif +#define ETS_INT_MASK 0x00003FFF #define ESP_TICKS_MAX UINT32_MAX typedef uint32_t esp_tick_t; @@ -63,6 +64,70 @@ static inline void soc_restore_local_irq(esp_irqflag_t flag) ); } +static inline void soc_set_ccompare(uint32_t ticks) +{ + __asm__ __volatile__( + "wsr %0, ccompare0\n" + : + : "a"(ticks) + : "memory" + ); +} + +static inline uint32_t soc_get_ccompare(void) +{ + uint32_t ticks; + + __asm__ __volatile__( + "rsr %0, ccompare0\n" + : "=a"(ticks) + : + : "memory" + ); + + return ticks; +} + +static inline uint32_t soc_get_ccount(void) +{ + uint32_t ticks; + + __asm__ __volatile__( + "rsr %0, ccount\n" + : "=a"(ticks) + : + : "memory" + ); + + return ticks; +} + +static inline void soc_clear_int_mask(uint32_t mask) +{ + __asm__ __volatile__( + "wsr %0, intclear\n" + : + : "a"(mask) + : "memory" + ); +} + +static inline uint32_t soc_get_int_mask(void) +{ + uint32_t mask, enable; + + __asm__ __volatile__( + "rsr %0, interrupt\n" + "rsr %1, intenable\n" + "rsync\n" + : "=a"(mask), "=a"(enable) + : + : "memory" + ); + + return mask & enable & ETS_INT_MASK; +} + #ifdef __cplusplus } #endif diff --git a/components/esp8266/include/esp8266/eagle_soc.h b/components/esp8266/include/esp8266/eagle_soc.h index aef152cf..490ecab9 100644 --- a/components/esp8266/include/esp8266/eagle_soc.h +++ b/components/esp8266/include/esp8266/eagle_soc.h @@ -26,6 +26,7 @@ #define _EAGLE_SOC_H_ #include +#include "driver/soc.h" /* IO definitions (access restrictions to peripheral registers) */ diff --git a/components/esp8266/include/rom/ets_sys.h b/components/esp8266/include/rom/ets_sys.h index 9b18e2cb..45bac4e2 100644 --- a/components/esp8266/include/rom/ets_sys.h +++ b/components/esp8266/include/rom/ets_sys.h @@ -42,6 +42,7 @@ extern "C" { #define ETS_SOFT_INUM 7 #define ETS_WDT_INUM 8 #define ETS_FRC_TIMER1_INUM 9 +#define ETS_INT_MAX 14 extern char NMIIrqIsOn; extern uint32_t WDEV_INTEREST_EVENT; diff --git a/components/esp8266/source/task_wdt.c b/components/esp8266/source/task_wdt.c index 2b9d951f..872d9415 100644 --- a/components/esp8266/source/task_wdt.c +++ b/components/esp8266/source/task_wdt.c @@ -19,6 +19,7 @@ #include "esp_task_wdt.h" #include "portmacro.h" #include "esp8266/eagle_soc.h" +#include "driver/soc.h" static const char *TAG = "wdt"; @@ -46,7 +47,7 @@ esp_err_t esp_task_wdt_init(void) const uint32_t panic_time_param = 11; // Just for soft restart - _xt_clear_ints(1 << ETS_WDT_INUM); + soc_clear_int_mask(1 << ETS_WDT_INUM); _xt_isr_attach(ETS_WDT_INUM, esp_task_wdt_isr, NULL); _xt_isr_unmask(1 << ETS_WDT_INUM); diff --git a/components/freertos/port/esp8266/include/freertos/portmacro.h b/components/freertos/port/esp8266/include/freertos/portmacro.h index 2bb02c4d..673c16b2 100644 --- a/components/freertos/port/esp8266/include/freertos/portmacro.h +++ b/components/freertos/port/esp8266/include/freertos/portmacro.h @@ -158,8 +158,6 @@ void _xt_user_exit (void); void _xt_tick_timer_init (void); void _xt_isr_unmask (uint32_t unmask); void _xt_isr_mask (uint32_t mask); -uint32_t _xt_read_ints (void); -void _xt_clear_ints(uint32_t mask); /* interrupt related */ typedef void (* _xt_isr)(void *arg); diff --git a/components/freertos/port/esp8266/include/freertos/xtensa_timer.h b/components/freertos/port/esp8266/include/freertos/xtensa_timer.h index ff97830f..49559b45 100644 --- a/components/freertos/port/esp8266/include/freertos/xtensa_timer.h +++ b/components/freertos/port/esp8266/include/freertos/xtensa_timer.h @@ -140,7 +140,6 @@ Derviation of clock divisor for timer tick and interrupt (one per tick). #else #ifndef __ASSEMBLER__ extern unsigned _xt_tick_divisor; -extern void _xt_tick_divisor_init(void); #endif #define XT_TICK_DIVISOR _xt_tick_divisor #endif diff --git a/components/freertos/port/esp8266/os_cpu_a.S b/components/freertos/port/esp8266/os_cpu_a.S index f1d04b7d..101a09f7 100644 --- a/components/freertos/port/esp8266/os_cpu_a.S +++ b/components/freertos/port/esp8266/os_cpu_a.S @@ -117,119 +117,6 @@ _xt_int_exit: l32i a0, sp, XT_STK_EXIT ret -/* -********************************************************************************************************** -* _xt_timer_int -* void _xt_timer_int(void) -* -* Implements the Xtensa RTOS porting layer's XT_RTOS_TIMER_INT function for uC/OS-II. -* Called every timer interrupt. -* Manages the tick timer and calls OSTimeTick() every tick, and calls OSTmrSignal() when required. -* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h. -* -* Callable from C (obeys ABI conventions). Implemented in assmebly code for performance. -* -********************************************************************************************************** -*/ - /* Define local variable offsets in stack frame for Call0 ABI. */ - #define __xt_timer_int_a0 0 /* ENTRY()/RET() saves/restores */ - #define __xt_timer_int_a2 4 /* preserve a2 */ - #define __xt_timer_int_a3 8 /* preserve a3 */ - - .globl _xt_timer_int - .type _xt_timer_int,@function - .align 4 -_xt_timer_int: - - /* - Xtensa timers work by comparing a cycle counter with a preset value. Once the match occurs - an interrupt is generated, and the handler has to set a new cycle count into the comparator. - To avoid clock drift due to interrupt latency, the new cycle count is computed from the old, - not the time the interrupt was serviced. However if a timer interrupt is ever serviced more - than one tick late, it is necessary to process multiple ticks until the new cycle count is - in the future, otherwise the next timer interrupt would not occur until after the cycle - counter had wrapped (2^32 cycles later). - - do { - ticks++; - old_ccompare = read_ccompare_i(); - write_ccompare_i( old_ccompare + divisor ); - service one tick; - diff = read_ccount() - old_ccompare; - } while ( diff > divisor ); - */ - - ENTRY(16) - -.L_xt_timer_int_catchup: - - /* Update the timer comparator for the next tick. */ - #ifdef XT_CLOCK_FREQ - movi a2, XT_TICK_DIVISOR /* a2 = comparator increment */ - #else - movi a3, _xt_tick_divisor - l32i a2, a3, 0 /* a2 = comparator increment */ - #endif - rsr a3, XT_CCOMPARE /* a3 = old comparator value */ - add a4, a3, a2 /* a4 = new comparator value */ - wsr a4, XT_CCOMPARE /* update comp. and clear interrupt */ - esync - - /* Preserve a2 and a3 across C calls. */ - s32i a2, sp, __xt_timer_int_a2 - s32i a3, sp, __xt_timer_int_a3 - -#ifndef CONFIG_TASK_SWITCH_FASTER - movi a0, xPortSysTickHandle - callx0 a0 -#else - call0 xPortSysTickHandle -#endif - - /* Restore a2 and a3. */ - l32i a2, sp, __xt_timer_int_a2 - l32i a3, sp, __xt_timer_int_a3 - - /* Check if we need to process more ticks to catch up. */ - esync /* ensure comparator update complete */ - rsr a4, CCOUNT /* a4 = cycle count */ - sub a4, a4, a3 /* diff = ccount - old comparator */ - blt a2, a4, .L_xt_timer_int_catchup /* repeat while diff > divisor */ - - RET(16) - - - - #define __xt_timer_int1_a0 0 /* ENTRY()/RET() saves/restores */ - #define __xt_timer_int1_a2 4 /* preserve a2 */ - #define __xt_timer_int1_a3 8 /* preserve a3 */ - - .globl _xt_timer_int1 - .type _xt_timer_int1,@function - .align 4 -_xt_timer_int1: - - ENTRY(16) - - /* Preserve a2 and a3 across C calls. */ - s32i a2, sp, __xt_timer_int1_a2 - s32i a3, sp, __xt_timer_int1_a3 - - /* Call the uCOS-II tick handler. */ -#ifndef CONFIG_TASK_SWITCH_FASTER - movi a0, vTaskSwitchContext - callx0 a0 -#else - call0 vTaskSwitchContext -#endif - - /* Restore a2 and a3. */ - l32i a2, sp, __xt_timer_int1_a2 - l32i a3, sp, __xt_timer_int1_a3 - - RET(16) - - /* ********************************************************************************************************** @@ -241,9 +128,10 @@ _xt_timer_int1: * ********************************************************************************************************** */ - .globl _xt_tick_timer_init - .type _xt_tick_timer_init,@function - .align 4 + .section .text._xt_tick_timer_init, "ax" + .globl _xt_tick_timer_init + .type _xt_tick_timer_init,@function + .align 4 _xt_tick_timer_init: ENTRY(16) @@ -268,10 +156,10 @@ _xt_tick_timer_init: RET(16) - - .globl _xt_set_xt_ccompare_val - .type _xt_set_xt_ccompare_val,@function - .align 4 + .section .text._xt_set_xt_ccompare_val, "ax" + .globl _xt_set_xt_ccompare_val + .type _xt_set_xt_ccompare_val,@function + .align 4 _xt_set_xt_ccompare_val: ENTRY(16) @@ -282,9 +170,10 @@ _xt_set_xt_ccompare_val: esync RET(16) - .globl ResetCcountVal - .type ResetCcountVal,@function - .align 4 + .section .text.ResetCcountVal, "ax" + .globl ResetCcountVal + .type ResetCcountVal,@function + .align 4 ResetCcountVal: ENTRY(16) wsr a2, ccount @@ -296,10 +185,10 @@ ResetCcountVal: ********************************************************************************************************** */ - - .globl _xt_isr_unmask - .type _xt_isr_unmask,@function - .align 4 + .section .text._xt_isr_unmask, "ax" + .globl _xt_isr_unmask + .type _xt_isr_unmask,@function + .align 4 _xt_isr_unmask: ENTRY(16) @@ -313,9 +202,10 @@ _xt_isr_unmask: RET(16) - .globl _xt_isr_mask - .type _xt_isr_mask,@function - .align 4 + .section .text._xt_isr_mask, "ax" + .globl _xt_isr_mask + .type _xt_isr_mask,@function + .align 4 _xt_isr_mask: ENTRY(16) @@ -330,23 +220,6 @@ _xt_isr_mask: RET(16) - .global _xt_read_ints - .type _xt_read_ints,@function - .align 4 -_xt_read_ints: - ENTRY(16) - rsr a2, INTERRUPT - RET(16) - - .global _xt_clear_ints - .type _xt_clear_ints,@function - .align 4 -_xt_clear_ints: - ENTRY(16) - wsr a2, INTCLEAR - RET(16) - - .section .text._xt_enter_first_task, "ax" .globl _xt_enter_first_task .type _xt_enter_first_task, @function diff --git a/components/freertos/port/esp8266/port.c b/components/freertos/port/esp8266/port.c index 988b032c..f16ab865 100644 --- a/components/freertos/port/esp8266/port.c +++ b/components/freertos/port/esp8266/port.c @@ -53,7 +53,9 @@ extern char NMIIrqIsOn; static int SWReq = 0; -unsigned cpu_sr; +uint32_t cpu_sr; + +uint32_t _xt_tick_divisor; /* Each task maintains its own interrupt status in the critical nesting variable. */ @@ -65,8 +67,6 @@ uint64_t g_os_ticks = 0; void vPortEnterCritical(void); void vPortExitCritical(void); -void _xt_timer_int1(void); - uint8_t *__cpu_init_stk(uint8_t *stack_top, void (*_entry)(void *), void *param, void (*_exit)(void)) { @@ -121,7 +121,7 @@ void TASK_SW_ATTR SoftIsrHdl(void* arg) extern int MacIsrSigPostDefHdl(void); if (MacIsrSigPostDefHdl() || (SWReq == 1)) { - _xt_timer_int1(); + vTaskSwitchContext(); SWReq = 0; } } @@ -138,8 +138,12 @@ void esp_increase_tick_cnt(const TickType_t ticks) soc_restore_local_irq(flag); } -void TASK_SW_ATTR xPortSysTickHandle(void) +void TASK_SW_ATTR xPortSysTickHandle(void *p) { + const uint32_t cpu_clk_cnt = soc_get_ccount() + _xt_tick_divisor; + + soc_set_ccompare(cpu_clk_cnt); + g_cpu_ticks = soc_get_ticks(); g_os_ticks++; @@ -167,8 +171,11 @@ portBASE_TYPE xPortStartScheduler(void) _xt_isr_attach(ETS_SOFT_INUM, SoftIsrHdl, NULL); _xt_isr_unmask(1 << ETS_SOFT_INUM); + _xt_isr_attach(ETS_MAX_INUM, xPortSysTickHandle, NULL); + /* Initialize system tick timer interrupt and schedule the first tick. */ - _xt_tick_divisor_init(); + _xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC; + _xt_tick_timer_init(); vTaskSwitchContext(); @@ -255,44 +262,40 @@ bool interrupt_is_disable(void) return tmp & 0xFUL ? true : false; } -_xt_isr_entry isr[16]; -char _xt_isr_status = 0; +static _xt_isr_entry s_isr[16]; +static uint8_t s_xt_isr_status = 0; void _xt_isr_attach(uint8_t i, _xt_isr func, void* arg) { - isr[i].handler = func; - isr[i].arg = arg; + s_isr[i].handler = func; + s_isr[i].arg = arg; } -uint16_t TASK_SW_ATTR _xt_isr_handler(uint16_t i) +void IRAM_ATTR _xt_isr_handler(void) { - uint8_t index; + do { + uint32_t mask = soc_get_int_mask(); - if (i & (1 << ETS_WDT_INUM)) { - index = ETS_WDT_INUM; - } else if (i & (1 << ETS_GPIO_INUM)) { - index = ETS_GPIO_INUM; - } else { - index = __builtin_ffs(i) - 1; + for (int i = 0; i < ETS_INT_MAX && mask; i++) { + int bit = 1 << i; - if (index == ETS_MAX_INUM) { - i &= ~(1 << ETS_MAX_INUM); - index = __builtin_ffs(i) - 1; + if (!(bit & mask) || !s_isr[i].handler) + continue; + + soc_clear_int_mask(bit); + + s_xt_isr_status = 1; + s_isr[i].handler(s_isr[i].arg); + s_xt_isr_status = 0; + + mask &= ~bit; } - } - - _xt_clear_ints(1 << index); - - _xt_isr_status = 1; - isr[index].handler(isr[index].arg); - _xt_isr_status = 0; - - return i & ~(1 << index); + } while (soc_get_int_mask()); } int xPortInIsrContext(void) { - return _xt_isr_status != 0; + return s_xt_isr_status != 0; } void __attribute__((weak, noreturn)) vApplicationStackOverflowHook(xTaskHandle xTask, const char *pcTaskName) diff --git a/components/freertos/port/esp8266/xtensa_init.c b/components/freertos/port/esp8266/xtensa_init.c deleted file mode 100644 index 9b37253c..00000000 --- a/components/freertos/port/esp8266/xtensa_init.c +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* -Copyright (c) 2006-2009 by Tensilica Inc. ALL RIGHTS RESERVED. -These coded instructions, statements, and computer programs are the -copyrighted works and confidential proprietary information of Tensilica Inc. -They may not be modified, copied, reproduced, distributed, or disclosed to -third parties in any manner, medium, or form, in whole or in part, without -the prior written consent of Tensilica Inc. --------------------------------------------------------------------------------- - - XTENSA INITIALIZATION ROUTINES CODED IN C - -This header is a place to put miscellaneous Xtensa RTOS-generic initialization -functions that are implemented in C. - -This header contains definitions and macros for use primarily by Xtensa -RTOS assembly coded source files. It includes and uses the Xtensa hardware -abstraction layer (HAL) to deal with config specifics. It may also be -included in C source files. - -*******************************************************************************/ - -#ifndef XTENSA_INIT_H -#define XTENSA_INIT_H - -#ifdef XT_BOARD -#include -#endif - -#include "freertos/xtensa_rtos.h" - - -#ifdef XT_RTOS_TIMER_INT -#ifndef XT_CLOCK_FREQ - -unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */ - -/* -Compute and initialize at run-time the tick divisor (the number of -processor clock cycles in an RTOS tick, used to set the tick timer). -Called when the processor clock frequency is not known at compile-time. -*/ -void _xt_tick_divisor_init(void) -{ - #ifdef XT_BOARD - _xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC; - #else - #error "No way to obtain processor clock frequency" - #endif /* XT_BOARD */ -} - -#endif /* XT_CLOCK_FREQ */ -#endif /* XT_RTOS_TIMER_INT */ - -#endif /* XTENSA_INIT_H */ diff --git a/components/freertos/port/esp8266/xtensa_vectors.S b/components/freertos/port/esp8266/xtensa_vectors.S index 702a8170..476d0afc 100644 --- a/components/freertos/port/esp8266/xtensa_vectors.S +++ b/components/freertos/port/esp8266/xtensa_vectors.S @@ -675,16 +675,6 @@ _xt_user_entry1: /* Handle level 1 interrupts. No need to enable med-pri interrupts now. */ .L_xt_user_int: - /* - Get mask of pending, enabled interrupts at this level into a2. - Comment this out if there is only one interrupt at this level. - */ - rsr a2, INTENABLE - rsr a3, INTERRUPT - movi a4, XCHAL_INTLEVEL1_MASK - and a2, a2, a3 - and a2, a2, a4 - /* USER_EDIT: ADD LOW PRIORITY LEVEL 1 INTERRUPT HANDLER CODE HERE, OR CALL C HANDLER. @@ -695,16 +685,6 @@ _xt_user_entry1: When done, ensure a2 contains a mask of unhandled (still pending) enabled ints at this level, and fall through. */ -.Ln_xt_user_int_timer: - movi a3, 0xFFBF - and a3, a2, a3 - bnez a3, 3f - /* Interrupt handler for the RTOS tick timer if at this level. */ - movi a3, XT_TIMER_INTEN /* timer interrupt bit */ - sub a12, a2, a3 /* clear timer int and save mask */ - call0 XT_RTOS_TIMER_INT - mov a2, a12 /* recover mask of remaining ints */ - beqz a2, 4f 3: movi a0, _chip_interrupt_tmp s32i a1, a0, 0 @@ -720,13 +700,6 @@ _xt_user_entry1: movi a0, _chip_interrupt_tmp l32i a1, a0, 0 - bnez a2, .Ln_xt_user_int_timer -4: - /* All interrupts at this level should have been handled now. */ - beqz a2, .L_xt_user_done - - call0 _xt_ext_panic - /* Done handling after XT_RTOS_INT_ENTER. Give control to RTOS. */ .L_xt_user_done: call0 XT_RTOS_INT_EXIT /* does not return directly here */ @@ -797,7 +770,7 @@ nmi_common: s32i a1, a0, HESF_AR(1) l32i a2, a2, 0 // get dispatcher address s32i a3, a0, HESF_AR(3) - xsr a2, EXCSAVE_LEVEL // get saved a0, restore dispatcher address + xsr a2, EXCSAVE_LEVEL // get saved a0, restore dispatcher address s32i a4, a0, HESF_AR(4) s32i a2, a0, HESF_AR(0) @@ -819,7 +792,7 @@ nmi_common: rsr a4, EXCCAUSE s32i a3, a0, HESF_EPC1 s32i a4, a0, HESF_EXCCAUSE - rsr a3, EXCVADDR + rsr a3, EXCVADDR s32i a3, a0, HESF_EXCVADDR rsr a4, EXCSAVE1 s32i a4, a0, HESF_EXCSAVE1