freertos: riscv port now uses interrupt allocator and crosscore interrupt

pull/6416/head
Felipe Neves 2020-11-13 16:03:50 -03:00 zatwierdzone przez morris
rodzic 09bc1580be
commit f4781d3b1d
4 zmienionych plików z 46 dodań i 77 usunięć

Wyświetl plik

@ -77,19 +77,23 @@
#include <string.h> #include <string.h>
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "sdkconfig.h"
#include "portmacro.h" #include "portmacro.h"
#include "riscv/interrupt.h"
#include "riscv/rvruntime-frames.h" #include "sdkconfig.h"
#include "soc/periph_defs.h" #include "soc/periph_defs.h"
#include "soc/system_reg.h" #include "soc/system_reg.h"
#include "soc/interrupt_reg.h"
#include "hal/systimer_hal.h" #include "hal/systimer_hal.h"
#include "hal/systimer_ll.h" #include "hal/systimer_ll.h"
#include "riscv/rvruntime-frames.h"
#include "riscv/riscv_interrupts.h" #include "riscv/riscv_interrupts.h"
#include "riscv/interrupt.h" #include "riscv/interrupt.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "esp_private/crosscore_int.h"
#include "esp_attr.h"
#include "esp_log.h" #include "esp_log.h"
/** /**
@ -98,7 +102,7 @@
* to ensure interrupts don't inadvertently become unmasked before the scheduler starts. * to ensure interrupts don't inadvertently become unmasked before the scheduler starts.
* As it is stored as part of the task context it will automatically be set to 0 when the first task is started. * As it is stored as part of the task context it will automatically be set to 0 when the first task is started.
*/ */
static UBaseType_t uxCriticalNesting = 0; static UBaseType_t uxCriticalNesting = 0;
static UBaseType_t uxSavedInterruptState = 0; static UBaseType_t uxSavedInterruptState = 0;
BaseType_t uxSchedulerRunning = 0; BaseType_t uxSchedulerRunning = 0;
UBaseType_t uxInterruptNesting = 0; UBaseType_t uxInterruptNesting = 0;
@ -108,10 +112,8 @@ StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOIN
static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but
static void vPortSysTickHandler(void); static void vPortSysTickHandler(void *arg);
static void vPortSetupTimer(void); static void vPortSetupTimer(void);
static void vPortSetupSoftwareInterrupt(void);
static void vPortSoftwareInterrupt(void);
static void prvTaskExitError(void); static void prvTaskExitError(void);
extern void esprv_intc_int_set_threshold(int); // FIXME, this function is in ROM only extern void esprv_intc_int_set_threshold(int); // FIXME, this function is in ROM only
@ -144,16 +146,9 @@ void vPortExitCritical(void)
*/ */
void vPortSetupTimer(void) void vPortSetupTimer(void)
{ {
/* register the interrupt handler */ /* set system timer interrupt vector */
intr_handler_set(ETS_SYSTICK_INUM, (intr_handler_t)&vPortSysTickHandler, NULL); esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE, ESP_INTR_FLAG_IRAM, vPortSysTickHandler, NULL, NULL);
assert(err == ESP_OK);
/* pass the timer interrupt through the interrupt matrix */
intr_matrix_route(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE, ETS_SYSTICK_INUM);
/* enable the interrupt in the INTC */
esprv_intc_int_enable(BIT(ETS_SYSTICK_INUM));
esprv_intc_int_set_type(BIT(ETS_SYSTICK_INUM), INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_SYSTICK_INUM, 1);
/* configure the timer */ /* configure the timer */
systimer_hal_init(); systimer_hal_init();
@ -164,24 +159,6 @@ void vPortSetupTimer(void)
systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1); systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1);
} }
/* setup software interrupt */
void vPortSetupSoftwareInterrupt(void)
{
/* register the interrupt handler, see interrupt.h */
intr_handler_set(ETS_CPU_INTR0_INUM, (intr_handler_t)&vPortSoftwareInterrupt, NULL);
/* pass the "FROM_CPU_0", a.k.a. cross-core interrupt, through the interrupt matrix */
intr_matrix_route(ETS_FROM_CPU_INTR0_SOURCE, ETS_CPU_INTR0_INUM);
/* enable the interrupt in the INTC */
esprv_intc_int_enable(BIT(ETS_CPU_INTR0_INUM));
esprv_intc_int_set_type(BIT(ETS_CPU_INTR0_INUM), INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_CPU_INTR0_INUM, 1);
// TODO ESP32-C3 IDF-2126, maybe can use interrupt allocation API for all of the above? unsure...
esp_intr_reserve(ETS_CPU_INTR0_INUM, xPortGetCoreID());
}
void prvTaskExitError(void) void prvTaskExitError(void)
{ {
/* A function that implements a task must not exit or attempt to return to /* A function that implements a task must not exit or attempt to return to
@ -213,9 +190,6 @@ int vPortSetInterruptMask(void)
return ret; return ret;
} }
/*
* See header file for description.
*/
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters)
{ {
extern uint32_t __global_pointer$; extern uint32_t __global_pointer$;
@ -232,11 +206,15 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
frame->a1 = 0x11111111; frame->a1 = 0x11111111;
frame->a2 = 0x22222222; frame->a2 = 0x22222222;
frame->a3 = 0x33333333; frame->a3 = 0x33333333;
//TODO: IDF-2393
return (StackType_t *)frame; return (StackType_t *)frame;
} }
void vPortSysTickHandler(void) IRAM_ATTR void vPortSysTickHandler(void *arg)
{ {
(void)arg;
systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0); systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0);
if (!uxSchedulerRunning) { if (!uxSchedulerRunning) {
@ -249,15 +227,18 @@ void vPortSysTickHandler(void)
} }
BaseType_t xPortStartScheduler(void) BaseType_t xPortStartScheduler(void)
{ {
vPortSetupTimer();
vPortSetupSoftwareInterrupt();
uxInterruptNesting = 0; uxInterruptNesting = 0;
uxCriticalNesting = 0; uxCriticalNesting = 0;
uxSchedulerRunning = 0; /* this means first yield */ uxSchedulerRunning = 0;
vPortSetupTimer();
esprv_intc_int_set_threshold(1); /* set global INTC masking level */ esprv_intc_int_set_threshold(1); /* set global INTC masking level */
riscv_global_interrupts_enable(); riscv_global_interrupts_enable();
vPortYield(); vPortYield();
/*Should not get here*/ /*Should not get here*/
return pdFALSE; return pdFALSE;
} }
@ -265,20 +246,18 @@ BaseType_t xPortStartScheduler(void)
void vPortEndScheduler(void) void vPortEndScheduler(void)
{ {
/* very unlikely this function will be called, so just trap here */ /* very unlikely this function will be called, so just trap here */
while (1) abort();
;
}
void vPortSoftwareInterrupt(void)
{
uxSchedulerRunning = 1;
REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
} }
void vPortYieldOtherCore(BaseType_t coreid) void vPortYieldOtherCore(BaseType_t coreid)
{ {
(void)coreid; esp_crosscore_int_send_yield(coreid);
vPortYield(); }
void vPortYieldFromISR( void )
{
uxSchedulerRunning = 1;
xPortSwitchFlag = 1;
} }
void vPortYield(void) void vPortYield(void)
@ -286,9 +265,8 @@ void vPortYield(void)
if (uxInterruptNesting) { if (uxInterruptNesting) {
vPortYieldFromISR(); vPortYieldFromISR();
} else { } else {
xPortSwitchFlag = 1;
REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 1);
esp_crosscore_int_send_yield(0);
/* There are 3-4 instructions of latency between triggering the software /* There are 3-4 instructions of latency between triggering the software
interrupt and the CPU interrupt happening. Make sure it happened before interrupt and the CPU interrupt happening. Make sure it happened before
we return, otherwise vTaskDelay() may return and execute 1-2 we return, otherwise vTaskDelay() may return and execute 1-2
@ -304,11 +282,6 @@ void vPortYield(void)
} }
void vPortYieldFromISR( void )
{
xPortSwitchFlag = 1;
}
void vPortSetStackWatchpoint(void *pxStackStart) void vPortSetStackWatchpoint(void *pxStackStart)
{ {
(void)pxStackStart; // TODO ESP32-C3 IDF-2207 (void)pxStackStart; // TODO ESP32-C3 IDF-2207
@ -328,24 +301,24 @@ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
void vPortCPUInitializeMutex(portMUX_TYPE *mux) void vPortCPUInitializeMutex(portMUX_TYPE *mux)
{ {
(void)mux; (void)mux; //TODO: IDF-2393
} }
void vPortCPUAcquireMutex(portMUX_TYPE *mux) void vPortCPUAcquireMutex(portMUX_TYPE *mux)
{ {
(void)mux; (void)mux; //TODO: IDF-2393
} }
bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles) bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles)
{ {
(void)mux; (void)mux; //TODO: IDF-2393
(void)timeout_cycles; (void)timeout_cycles;
return true; return true;
} }
void vPortCPUReleaseMutex(portMUX_TYPE *mux) void vPortCPUReleaseMutex(portMUX_TYPE *mux)
{ {
(void)mux; (void)mux; //TODO: IDF-2393
} }
void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)

Wyświetl plik

@ -70,18 +70,18 @@ rtos_int_exit:
beq t0,zero, rtos_exit_end beq t0,zero, rtos_exit_end
/* update nesting interrupts counter */ /* update nesting interrupts counter */
la t2, uxInterruptNesting la t2, uxInterruptNesting
lw t3, 0x0(t2) lw t3, 0x0(t2)
/* Already zero, protect againts underflow */ /* Already zero, protect againts underflow */
beq t3, zero, isr_skip_decrement beq t3, zero, isr_skip_decrement
addi t3,t3, -1 addi t3,t3, -1
sw t3, 0x0(t2) sw t3, 0x0(t2)
isr_skip_decrement: isr_skip_decrement:
/* may still have interrupts pending, skip section below and exit */ /* may still have interrupts pending, skip section below and exit */
bne t3,zero,rtos_exit_end bne t3,zero,rtos_exit_end
/* Schedule the next task if a yield is pending */ /* Schedule the next task if a yield is pending */
la t0, xPortSwitchFlag la t0, xPortSwitchFlag

Wyświetl plik

@ -16,9 +16,6 @@
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "soc/soc.h" #include "soc/soc.h"
// TODO ESP32-C3 IDF-2126 check this table is correct, some interrupts may be unnecessarily reserved or not reserved
// or marked as the wrong type
//This is basically a software-readable version of the interrupt usage table in include/soc/soc.h //This is basically a software-readable version of the interrupt usage table in include/soc/soc.h
const int_desc_t interrupt_descriptor_table[32] = { const int_desc_t interrupt_descriptor_table[32] = {
{ 1, INTTP_LEVEL, {INTDESC_RESVD } }, //0 { 1, INTTP_LEVEL, {INTDESC_RESVD } }, //0

Wyświetl plik

@ -99,7 +99,6 @@
.global rtos_int_enter .global rtos_int_enter
.global rtos_int_exit .global rtos_int_exit
.global uxInterruptNesting
.global _global_interrupt_handler .global _global_interrupt_handler
.section .exception_vectors.text .section .exception_vectors.text