feat(freertos): Simplify xtensa platform code

All normal ISRs are called by "_xt_isr_handler".
This commit is contained in:
dongheng
2019-03-27 16:28:22 +08:00
parent b05cf79870
commit 913188fdf3
10 changed files with 125 additions and 265 deletions

View File

@ -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

View File

@ -26,6 +26,7 @@
#define _EAGLE_SOC_H_
#include <stdint.h>
#include "driver/soc.h"
/* IO definitions (access restrictions to peripheral registers) */

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 <xtensa/xtbsp.h>
#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 */

View File

@ -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