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 <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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Ładowanie…
Reference in New Issue