Skip to content

Commit

Permalink
AMP Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
FL0WL0W committed Dec 15, 2023
1 parent 0d48eea commit b3954c2
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 104 deletions.
9 changes: 3 additions & 6 deletions components/esp_driver_gpio/src/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
#include "driver/gpio.h"
#include "driver/rtc_io.h"
#include "soc/interrupts.h"
#if !CONFIG_FREERTOS_UNICORE
#include "esp_ipc.h"
#endif

#include "soc/soc_caps.h"
#include "soc/gpio_periph.h"
#include "esp_log.h"
Expand Down Expand Up @@ -605,12 +602,12 @@ esp_err_t gpio_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags,
}
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
esp_err_t ret;
#if CONFIG_FREERTOS_UNICORE
#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
gpio_isr_register_on_core_static(&p);
ret = ESP_OK;
#else /* CONFIG_FREERTOS_UNICORE */
#else /* CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE */
ret = esp_ipc_call_blocking(gpio_context.isr_core_id, gpio_isr_register_on_core_static, (void *)&p);
#endif /* !CONFIG_FREERTOS_UNICORE */
#endif /* !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE */
if (ret != ESP_OK) {
ESP_LOGE(GPIO_TAG, "esp_ipc_call_blocking failed (0x%x)", ret);
return ESP_ERR_NOT_FOUND;
Expand Down
4 changes: 2 additions & 2 deletions components/esp_driver_spi/src/gpspi/spi_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ static inline bool is_valid_host(spi_host_device_t host)
#endif
}

#if (SOC_CPU_CORES_NUM > 1) && (!CONFIG_FREERTOS_UNICORE)
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
typedef struct {
spi_host_t *spi_host;
esp_err_t *err;
Expand Down Expand Up @@ -243,7 +243,7 @@ static esp_err_t spi_master_init_driver(spi_host_device_t host_id)

// interrupts are not allowed on SPI1 bus
if (host_id != SPI1_HOST) {
#if (SOC_CPU_CORES_NUM > 1) && (!CONFIG_FREERTOS_UNICORE)
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
if (bus_attr->bus_cfg.isr_cpu_id > ESP_INTR_CPU_AFFINITY_AUTO) {
SPI_CHECK(bus_attr->bus_cfg.isr_cpu_id <= ESP_INTR_CPU_AFFINITY_1, "invalid core id", ESP_ERR_INVALID_ARG);
spi_ipc_param_t ipc_arg = {
Expand Down
4 changes: 2 additions & 2 deletions components/esp_driver_spi/src/gpspi/spi_slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ static inline void SPI_SLAVE_ISR_ATTR restore_cs(spi_slave_t *host)
}
}

#if (SOC_CPU_CORES_NUM > 1) && (!CONFIG_FREERTOS_UNICORE)
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
typedef struct {
spi_slave_t *host;
esp_err_t *err;
Expand Down Expand Up @@ -244,7 +244,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
}
}

#if (SOC_CPU_CORES_NUM > 1) && (!CONFIG_FREERTOS_UNICORE)
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
if (bus_config->isr_cpu_id > ESP_INTR_CPU_AFFINITY_AUTO) {
spihost[host]->intr_flags = bus_config->intr_flags;
SPI_CHECK(bus_config->isr_cpu_id <= ESP_INTR_CPU_AFFINITY_1, "invalid core id", ESP_ERR_INVALID_ARG);
Expand Down
11 changes: 4 additions & 7 deletions components/esp_hw_support/intr_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@
#include "soc/interrupts.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"

#if !CONFIG_FREERTOS_UNICORE
#include "esp_ipc.h"
#endif

/* For targets that uses a CLIC as their interrupt controller, CPU_INT_LINES_COUNT represents the external interrupts count */
#define CPU_INT_LINES_COUNT 32
Expand Down Expand Up @@ -685,12 +682,12 @@ esp_err_t IRAM_ATTR esp_intr_set_in_iram(intr_handle_t handle, bool is_in_iram)
return ESP_OK;
}

#if !CONFIG_FREERTOS_UNICORE
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
static void esp_intr_free_cb(void *arg)
{
(void)esp_intr_free((intr_handle_t)arg);
}
#endif /* !CONFIG_FREERTOS_UNICORE */
#endif /* !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE */

esp_err_t esp_intr_free(intr_handle_t handle)
{
Expand All @@ -699,13 +696,13 @@ esp_err_t esp_intr_free(intr_handle_t handle)
return ESP_ERR_INVALID_ARG;
}

#if !CONFIG_FREERTOS_UNICORE
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
//Assign this routine to the core where this interrupt is allocated on.
if (handle->vector_desc->cpu != esp_cpu_get_core_id()) {
esp_err_t ret = esp_ipc_call_blocking(handle->vector_desc->cpu, &esp_intr_free_cb, (void *)handle);
return ret == ESP_OK ? ESP_OK : ESP_FAIL;
}
#endif /* !CONFIG_FREERTOS_UNICORE */
#endif /* !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE */

portENTER_CRITICAL(&spinlock);
esp_intr_disable(handle);
Expand Down
6 changes: 3 additions & 3 deletions components/esp_system/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ menu "ESP System Settings"
wait before the device reboots.

config ESP_SYSTEM_SINGLE_CORE_MODE
bool
default n
bool "Only initialize first core."
default "y" if FREERTOS_UNICORE
help
Only initialize and use the main core.
Only initialize and use the main core. (EXPERIMENTAL, Leave this as default if you don't know what this changes)

config ESP_SYSTEM_RTC_EXT_XTAL
# This is a High Layer Kconfig option, invisible, can be selected by other Kconfig option
Expand Down
12 changes: 10 additions & 2 deletions components/esp_system/crosscore_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "esp_intr_alloc.h"
#include "esp_debug_helpers.h"
#include "soc/periph_defs.h"

#include "esp_private/esp_ipc.h"

#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
Expand All @@ -33,6 +33,7 @@
#define REASON_PRINT_BACKTRACE BIT(2)
#define REASON_GDB_CALL BIT(3)
#define REASON_TWDT_ABORT BIT(4)
#define REASON_IPC_HANDLE BIT(5)


static portMUX_TYPE reason_spinlock = portMUX_INITIALIZER_UNLOCKED;
Expand Down Expand Up @@ -103,7 +104,9 @@ static void IRAM_ATTR esp_crosscore_isr(void *arg) {
esp_backtrace_print(100);
}


if(my_reason_val & REASON_IPC_HANDLE) {
ipc_handle(esp_cpu_get_core_id());
}

#if CONFIG_ESP_TASK_WDT_EN
if (my_reason_val & REASON_TWDT_ABORT) {
Expand Down Expand Up @@ -187,6 +190,11 @@ void IRAM_ATTR esp_crosscore_int_send_print_backtrace(int core_id)
esp_crosscore_int_send(core_id, REASON_PRINT_BACKTRACE);
}

void IRAM_ATTR esp_crosscore_int_send_ipc_handle(int core_id)
{
esp_crosscore_int_send(core_id, REASON_IPC_HANDLE);
}

#if CONFIG_ESP_TASK_WDT_EN
void IRAM_ATTR esp_crosscore_int_send_twdt_abort(int core_id) {
esp_crosscore_int_send(core_id, REASON_TWDT_ABORT);
Expand Down
144 changes: 83 additions & 61 deletions components/esp_system/esp_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,82 @@
#include "esp_err.h"
#include "esp_ipc.h"
#include "esp_private/esp_ipc_isr.h"
#include "esp_ipc_isr.h"
#include "esp_attr.h"
#include "esp_private/esp_ipc.h"
#include "esp_private/crosscore_int.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

#if !defined(CONFIG_FREERTOS_UNICORE) || defined(CONFIG_APPTRACE_GCOV_ENABLE)
#if !defined(CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE) || defined(CONFIG_APPTRACE_GCOV_ENABLE)

#if CONFIG_COMPILER_OPTIMIZATION_NONE
#define IPC_STACK_SIZE (CONFIG_ESP_IPC_TASK_STACK_SIZE + 0x100)
#else
#define IPC_STACK_SIZE (CONFIG_ESP_IPC_TASK_STACK_SIZE)
#endif //CONFIG_COMPILER_OPTIMIZATION_NONE

static DRAM_ATTR StaticSemaphore_t s_ipc_mutex_buffer[configNUM_CORES];
static DRAM_ATTR StaticSemaphore_t s_ipc_ack_buffer[configNUM_CORES];
static DRAM_ATTR StaticSemaphore_t s_ipc_mutex_buffer[portNUM_PROCESSORS];
static DRAM_ATTR StaticSemaphore_t s_ipc_ack_buffer[portNUM_PROCESSORS];

static TaskHandle_t s_ipc_task_handle[configNUM_CORES];
static SemaphoreHandle_t s_ipc_mutex[configNUM_CORES]; // This mutex is used as a global lock for esp_ipc_* APIs
static SemaphoreHandle_t s_ipc_ack[configNUM_CORES]; // Semaphore used to acknowledge that task was woken up,
static volatile esp_ipc_func_t s_func[configNUM_CORES] = { 0 }; // Function which should be called by high priority task
static void * volatile s_func_arg[configNUM_CORES]; // Argument to pass into s_func
typedef enum {
IPC_WAIT_NO = 0,
IPC_WAIT_FOR_START,
IPC_WAIT_FOR_END,
} esp_ipc_wait_t;

static TaskHandle_t s_ipc_task_handle[configNUM_CORES];
static SemaphoreHandle_t s_ipc_mutex[portNUM_PROCESSORS]; // This mutex is used as a global lock for esp_ipc_* APIs
static SemaphoreHandle_t s_ipc_ack[portNUM_PROCESSORS]; // Semaphore used to acknowledge that task was woken up,
static volatile esp_ipc_func_t s_func[portNUM_PROCESSORS] = { 0 }; // Function which should be called by high priority task
static void * volatile s_func_arg[portNUM_PROCESSORS]; // Argument to pass into s_func
static volatile esp_ipc_wait_t s_func_wait_for[portNUM_PROCESSORS]; // Wait for function to finish

#if CONFIG_APPTRACE_GCOV_ENABLE
static volatile esp_ipc_func_t s_gcov_func = NULL; // Gcov dump starter function which should be called by high priority task
static void * volatile s_gcov_func_arg; // Argument to pass into s_gcov_func
static esp_ipc_wait_t s_gcov_func_wait_for; // Wait for function to finish
#endif

void IRAM_ATTR ipc_handle(const int cpuid)
{
#if CONFIG_APPTRACE_GCOV_ENABLE
if (s_gcov_func) {
(*s_gcov_func)(s_gcov_func_arg);
s_gcov_func = NULL;
/* we can not interfer with IPC calls so no need for further processing */
// esp_ipc API and gcov_from_isr APIs can be processed together if they came at the same time
if (s_gcov_func_wait_for == IPC_WAIT_NO) {
return;
}
}
#endif // CONFIG_APPTRACE_GCOV_ENABLE

#ifndef CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
if (s_func[cpuid]) {
// we need to cache s_func, s_func_arg and ipc_ack variables locally
// because they can be changed by a subsequent IPC call (after xTaskNotify(caller_task_handle)).
esp_ipc_func_t func = s_func[cpuid];
s_func[cpuid] = NULL;
void* func_arg = s_func_arg[cpuid];
esp_ipc_wait_t func_wait_for = s_func_wait_for[cpuid];
SemaphoreHandle_t ipc_ack = s_ipc_ack[cpuid];

if (func_wait_for == IPC_WAIT_FOR_START) {
xSemaphoreGive(ipc_ack);
(*func)(func_arg);
} else if (func_wait_for == IPC_WAIT_FOR_END) {
(*func)(func_arg);
xSemaphoreGive(ipc_ack);
} else {
abort();
}
}
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
}

static void IRAM_ATTR ipc_task(void* arg)
{
const int cpuid = (int) arg;
Expand All @@ -54,41 +97,10 @@ static void IRAM_ATTR ipc_task(void* arg)
#endif

while (true) {
uint32_t ipc_wait;
xTaskNotifyWait(0, ULONG_MAX, &ipc_wait, portMAX_DELAY);

#if CONFIG_APPTRACE_GCOV_ENABLE
if (s_gcov_func) {
(*s_gcov_func)(s_gcov_func_arg);
s_gcov_func = NULL;
/* we can not interfer with IPC calls so no need for further processing */
// esp_ipc API and gcov_from_isr APIs can be processed together if they came at the same time
if (ipc_wait == IPC_WAIT_NO) {
continue;
}
}
#endif // CONFIG_APPTRACE_GCOV_ENABLE
uint32_t notificationValue;
xTaskNotifyWait(0, ULONG_MAX, &notificationValue, portMAX_DELAY);

#ifndef CONFIG_FREERTOS_UNICORE
if (s_func[cpuid]) {
// we need to cache s_func, s_func_arg and ipc_ack variables locally
// because they can be changed by a subsequent IPC call (after xTaskNotify(caller_task_handle)).
esp_ipc_func_t func = s_func[cpuid];
s_func[cpuid] = NULL;
void* func_arg = s_func_arg[cpuid];
SemaphoreHandle_t ipc_ack = s_ipc_ack[cpuid];

if (ipc_wait == IPC_WAIT_FOR_START) {
xSemaphoreGive(ipc_ack);
(*func)(func_arg);
} else if (ipc_wait == IPC_WAIT_FOR_END) {
(*func)(func_arg);
xSemaphoreGive(ipc_ack);
} else {
abort();
}
}
#endif // !CONFIG_FREERTOS_UNICORE
ipc_handle(cpuid);
}
// TODO: currently this is unreachable code. Introduce esp_ipc_uninit
// function which will signal to both tasks that they can shut down.
Expand All @@ -114,21 +126,37 @@ static void esp_ipc_init(void)
{
char task_name[] = "ipcX"; // up to 10 ipc tasks/cores (0-9)

for (int i = 0; i < configNUM_CORES; ++i) {
task_name[3] = i + (char)'0';
for (int i = 0; i < portNUM_PROCESSORS; ++i) {
s_ipc_mutex[i] = xSemaphoreCreateMutexStatic(&s_ipc_mutex_buffer[i]);
s_ipc_ack[i] = xSemaphoreCreateBinaryStatic(&s_ipc_ack_buffer[i]);
BaseType_t res = xTaskCreatePinnedToCore(ipc_task, task_name, IPC_STACK_SIZE, (void*) i,
configMAX_PRIORITIES - 1, &s_ipc_task_handle[i], i);
assert(res == pdTRUE);
(void)res;
if(i < configNUM_CORES) {
task_name[3] = i + (char)'0';
BaseType_t res = xTaskCreatePinnedToCore(ipc_task, task_name, IPC_STACK_SIZE, (void*) i,
configMAX_PRIORITIES - 1, &s_ipc_task_handle[i], i);
assert(res == pdTRUE);
(void)res;
}
}
}

static esp_err_t esp_ipc_call_and_wait(uint32_t cpu_id, esp_ipc_func_t func, void* arg, esp_ipc_wait_t wait_for)
{
if (cpu_id >= configNUM_CORES) {
return ESP_ERR_INVALID_ARG;
if (cpu_id >= portNUM_PROCESSORS) {
return ESP_ERR_INVALID_ARG;
}
if( cpu_id == xPortGetCoreID()) {
(*func)(arg);
} else {
xSemaphoreTake(s_ipc_mutex[cpu_id], portMAX_DELAY);
s_func[cpu_id] = func;
s_func_arg[cpu_id] = arg;
s_func_wait_for[cpu_id] = wait_for;
esp_crosscore_int_send_ipc_handle(cpu_id);
xSemaphoreTake(s_ipc_ack[cpu_id], portMAX_DELAY);
xSemaphoreGive(s_ipc_mutex[cpu_id]);
}
return ESP_OK;
}
if (s_ipc_task_handle[cpu_id] == NULL) {
return ESP_ERR_INVALID_STATE;
Expand All @@ -145,22 +173,15 @@ static esp_err_t esp_ipc_call_and_wait(uint32_t cpu_id, esp_ipc_func_t func, voi
vTaskPrioritySet(s_ipc_task_handle[cpu_id], priority_of_current_task);
}

xSemaphoreTake(s_ipc_mutex[cpu_id], portMAX_DELAY);
vTaskPrioritySet(s_ipc_task_handle[cpu_id], priority_of_current_task);
#else
xSemaphoreTake(s_ipc_mutex[0], portMAX_DELAY);
#endif

xSemaphoreTake(s_ipc_mutex[cpu_id], portMAX_DELAY);
s_func[cpu_id] = func;
s_func_arg[cpu_id] = arg;
xTaskNotify(s_ipc_task_handle[cpu_id], wait_for, eSetValueWithOverwrite);
s_func_wait_for[cpu_id] = wait_for;
xTaskNotify(s_ipc_task_handle[cpu_id], 0, eSetValueWithOverwrite);
xSemaphoreTake(s_ipc_ack[cpu_id], portMAX_DELAY);

#ifdef CONFIG_ESP_IPC_USES_CALLERS_PRIORITY
xSemaphoreGive(s_ipc_mutex[cpu_id]);
#else
xSemaphoreGive(s_ipc_mutex[0]);
#endif
return ESP_OK;
}

Expand All @@ -187,9 +208,10 @@ esp_err_t esp_ipc_start_gcov_from_isr(uint32_t cpu_id, esp_ipc_func_t func, void
if (s_gcov_func == NULL) {
s_gcov_func_arg = arg;
s_gcov_func = func;
s_gcov_func_wait_for = IPC_WAIT_NO;

// If the target task already has a notification pending then its notification value is not updated (WithoutOverwrite).
xTaskNotifyFromISR(s_ipc_task_handle[cpu_id], IPC_WAIT_NO, eSetValueWithoutOverwrite, NULL);
xTaskNotifyFromISR(s_ipc_task_handle[cpu_id], 0, eSetValueWithoutOverwrite, NULL);
return ESP_OK;
}

Expand All @@ -198,4 +220,4 @@ esp_err_t esp_ipc_start_gcov_from_isr(uint32_t cpu_id, esp_ipc_func_t func, void
}
#endif // CONFIG_APPTRACE_GCOV_ENABLE

#endif // !defined(CONFIG_FREERTOS_UNICORE) || defined(CONFIG_APPTRACE_GCOV_ENABLE)
#endif // !defined(CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE) || defined(CONFIG_APPTRACE_GCOV_ENABLE)
Loading

0 comments on commit b3954c2

Please sign in to comment.