kopia lustrzana https://github.com/espressif/esp-idf
freertos: riscv port now uses interrupt allocator and crosscore interrupt
rodzic
09bc1580be
commit
f4781d3b1d
|
@ -77,19 +77,23 @@
|
|||
#include <string.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "portmacro.h"
|
||||
#include "riscv/interrupt.h"
|
||||
#include "riscv/rvruntime-frames.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "soc/periph_defs.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "soc/interrupt_reg.h"
|
||||
#include "hal/systimer_hal.h"
|
||||
#include "hal/systimer_ll.h"
|
||||
|
||||
#include "riscv/rvruntime-frames.h"
|
||||
#include "riscv/riscv_interrupts.h"
|
||||
#include "riscv/interrupt.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_private/crosscore_int.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
/**
|
||||
|
@ -98,7 +102,7 @@
|
|||
* 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.
|
||||
*/
|
||||
static UBaseType_t uxCriticalNesting = 0;
|
||||
static UBaseType_t uxCriticalNesting = 0;
|
||||
static UBaseType_t uxSavedInterruptState = 0;
|
||||
BaseType_t uxSchedulerRunning = 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 void vPortSysTickHandler(void);
|
||||
static void vPortSysTickHandler(void *arg);
|
||||
static void vPortSetupTimer(void);
|
||||
static void vPortSetupSoftwareInterrupt(void);
|
||||
static void vPortSoftwareInterrupt(void);
|
||||
static void prvTaskExitError(void);
|
||||
|
||||
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)
|
||||
{
|
||||
/* register the interrupt handler */
|
||||
intr_handler_set(ETS_SYSTICK_INUM, (intr_handler_t)&vPortSysTickHandler, NULL);
|
||||
|
||||
/* 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);
|
||||
/* set system timer interrupt vector */
|
||||
esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE, ESP_INTR_FLAG_IRAM, vPortSysTickHandler, NULL, NULL);
|
||||
assert(err == ESP_OK);
|
||||
|
||||
/* configure the timer */
|
||||
systimer_hal_init();
|
||||
|
@ -164,24 +159,6 @@ void vPortSetupTimer(void)
|
|||
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)
|
||||
{
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
|
@ -213,9 +190,6 @@ int vPortSetInterruptMask(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters)
|
||||
{
|
||||
extern uint32_t __global_pointer$;
|
||||
|
@ -232,11 +206,15 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
|
|||
frame->a1 = 0x11111111;
|
||||
frame->a2 = 0x22222222;
|
||||
frame->a3 = 0x33333333;
|
||||
|
||||
//TODO: IDF-2393
|
||||
return (StackType_t *)frame;
|
||||
}
|
||||
|
||||
void vPortSysTickHandler(void)
|
||||
IRAM_ATTR void vPortSysTickHandler(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0);
|
||||
|
||||
if (!uxSchedulerRunning) {
|
||||
|
@ -249,15 +227,18 @@ void vPortSysTickHandler(void)
|
|||
}
|
||||
|
||||
BaseType_t xPortStartScheduler(void)
|
||||
{
|
||||
vPortSetupTimer();
|
||||
vPortSetupSoftwareInterrupt();
|
||||
{
|
||||
uxInterruptNesting = 0;
|
||||
uxCriticalNesting = 0;
|
||||
uxSchedulerRunning = 0; /* this means first yield */
|
||||
uxSchedulerRunning = 0;
|
||||
|
||||
vPortSetupTimer();
|
||||
|
||||
esprv_intc_int_set_threshold(1); /* set global INTC masking level */
|
||||
riscv_global_interrupts_enable();
|
||||
|
||||
vPortYield();
|
||||
|
||||
/*Should not get here*/
|
||||
return pdFALSE;
|
||||
}
|
||||
|
@ -265,20 +246,18 @@ BaseType_t xPortStartScheduler(void)
|
|||
void vPortEndScheduler(void)
|
||||
{
|
||||
/* very unlikely this function will be called, so just trap here */
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void vPortSoftwareInterrupt(void)
|
||||
{
|
||||
uxSchedulerRunning = 1;
|
||||
REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
|
||||
abort();
|
||||
}
|
||||
|
||||
void vPortYieldOtherCore(BaseType_t coreid)
|
||||
{
|
||||
(void)coreid;
|
||||
vPortYield();
|
||||
esp_crosscore_int_send_yield(coreid);
|
||||
}
|
||||
|
||||
void vPortYieldFromISR( void )
|
||||
{
|
||||
uxSchedulerRunning = 1;
|
||||
xPortSwitchFlag = 1;
|
||||
}
|
||||
|
||||
void vPortYield(void)
|
||||
|
@ -286,9 +265,8 @@ void vPortYield(void)
|
|||
if (uxInterruptNesting) {
|
||||
vPortYieldFromISR();
|
||||
} 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
|
||||
interrupt and the CPU interrupt happening. Make sure it happened before
|
||||
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)pxStackStart; // TODO ESP32-C3 IDF-2207
|
||||
|
@ -328,24 +301,24 @@ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
|
|||
|
||||
void vPortCPUInitializeMutex(portMUX_TYPE *mux)
|
||||
{
|
||||
(void)mux;
|
||||
(void)mux; //TODO: IDF-2393
|
||||
}
|
||||
|
||||
void vPortCPUAcquireMutex(portMUX_TYPE *mux)
|
||||
{
|
||||
(void)mux;
|
||||
(void)mux; //TODO: IDF-2393
|
||||
}
|
||||
|
||||
bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles)
|
||||
{
|
||||
(void)mux;
|
||||
(void)mux; //TODO: IDF-2393
|
||||
(void)timeout_cycles;
|
||||
return true;
|
||||
}
|
||||
|
||||
void vPortCPUReleaseMutex(portMUX_TYPE *mux)
|
||||
{
|
||||
(void)mux;
|
||||
(void)mux; //TODO: IDF-2393
|
||||
}
|
||||
|
||||
void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
|
||||
|
|
|
@ -70,18 +70,18 @@ rtos_int_exit:
|
|||
beq t0,zero, rtos_exit_end
|
||||
|
||||
/* update nesting interrupts counter */
|
||||
la t2, uxInterruptNesting
|
||||
lw t3, 0x0(t2)
|
||||
la t2, uxInterruptNesting
|
||||
lw t3, 0x0(t2)
|
||||
|
||||
/* Already zero, protect againts underflow */
|
||||
beq t3, zero, isr_skip_decrement
|
||||
addi t3,t3, -1
|
||||
sw t3, 0x0(t2)
|
||||
/* Already zero, protect againts underflow */
|
||||
beq t3, zero, isr_skip_decrement
|
||||
addi t3,t3, -1
|
||||
sw t3, 0x0(t2)
|
||||
|
||||
isr_skip_decrement:
|
||||
|
||||
/* may still have interrupts pending, skip section below and exit */
|
||||
bne t3,zero,rtos_exit_end
|
||||
/* may still have interrupts pending, skip section below and exit */
|
||||
bne t3,zero,rtos_exit_end
|
||||
|
||||
/* Schedule the next task if a yield is pending */
|
||||
la t0, xPortSwitchFlag
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
#include "soc/soc_caps.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
|
||||
const int_desc_t interrupt_descriptor_table[32] = {
|
||||
{ 1, INTTP_LEVEL, {INTDESC_RESVD } }, //0
|
||||
|
|
|
@ -99,7 +99,6 @@
|
|||
|
||||
.global rtos_int_enter
|
||||
.global rtos_int_exit
|
||||
.global uxInterruptNesting
|
||||
.global _global_interrupt_handler
|
||||
|
||||
.section .exception_vectors.text
|
||||
|
|
Ładowanie…
Reference in New Issue