mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-04 00:51:42 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			108 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: Apache-2.0
 | 
						|
 */
 | 
						|
 | 
						|
#include "esp_openthread_task_queue.h"
 | 
						|
#include "esp_check.h"
 | 
						|
#include "esp_err.h"
 | 
						|
#include "esp_openthread_common_macro.h"
 | 
						|
#include "esp_openthread_platform.h"
 | 
						|
#include "esp_openthread_types.h"
 | 
						|
#include "esp_vfs.h"
 | 
						|
#include "esp_vfs_eventfd.h"
 | 
						|
#include "freertos/FreeRTOS.h"
 | 
						|
#include "freertos/portmacro.h"
 | 
						|
#include "freertos/queue.h"
 | 
						|
 | 
						|
static QueueHandle_t s_task_queue = NULL;
 | 
						|
static int s_task_queue_event_fd = -1;
 | 
						|
static const char *task_queue_workflow = "task_queue";
 | 
						|
 | 
						|
typedef struct {
 | 
						|
    esp_openthread_task_t task;
 | 
						|
    void *arg;
 | 
						|
} task_storage_t;
 | 
						|
 | 
						|
esp_err_t esp_openthread_task_queue_init(const esp_openthread_platform_config_t *config)
 | 
						|
{
 | 
						|
    s_task_queue_event_fd = eventfd(0, EFD_SUPPORT_ISR);
 | 
						|
    ESP_RETURN_ON_FALSE(s_task_queue_event_fd >= 0, ESP_FAIL, OT_PLAT_LOG_TAG,
 | 
						|
                        "Failed to create OpenThread task queue event fd");
 | 
						|
    s_task_queue = xQueueCreate(config->port_config.task_queue_size, sizeof(task_storage_t));
 | 
						|
    ESP_RETURN_ON_FALSE(s_task_queue != NULL, ESP_ERR_NO_MEM, OT_PLAT_LOG_TAG,
 | 
						|
                        "Failed to create OpenThread task queue");
 | 
						|
    return esp_openthread_platform_workflow_register(&esp_openthread_task_queue_update,
 | 
						|
                                                     &esp_openthread_task_queue_process, task_queue_workflow);
 | 
						|
}
 | 
						|
 | 
						|
esp_err_t IRAM_ATTR esp_openthread_task_queue_post(esp_openthread_task_t task, void *arg)
 | 
						|
{
 | 
						|
    task_storage_t task_storage = {
 | 
						|
        .task = task,
 | 
						|
        .arg = arg,
 | 
						|
    };
 | 
						|
    uint64_t val = 1;
 | 
						|
    ssize_t ret;
 | 
						|
    BaseType_t task_woken = pdFALSE;
 | 
						|
 | 
						|
    if (!xPortCanYield()) {
 | 
						|
        ESP_RETURN_ON_FALSE_ISR(xQueueSendFromISR(s_task_queue, &task_storage, &task_woken), ESP_FAIL, OT_PLAT_LOG_TAG,
 | 
						|
                                "Failed to post task to OpenThread task queue");
 | 
						|
    } else {
 | 
						|
        ESP_RETURN_ON_FALSE(xQueueSend(s_task_queue, &task_storage, portMAX_DELAY), ESP_FAIL, OT_PLAT_LOG_TAG,
 | 
						|
                            "Failed to post task to OpenThread task queue");
 | 
						|
    }
 | 
						|
    ret = write(s_task_queue_event_fd, &val, sizeof(val));
 | 
						|
    assert(ret == sizeof(val));
 | 
						|
 | 
						|
    if (task_woken) {
 | 
						|
        portYIELD_FROM_ISR_NO_ARG();
 | 
						|
    }
 | 
						|
    return ESP_OK;
 | 
						|
}
 | 
						|
 | 
						|
void esp_openthread_task_queue_update(esp_openthread_mainloop_context_t *mainloop)
 | 
						|
{
 | 
						|
    if (s_task_queue_event_fd >= 0) {
 | 
						|
        FD_SET(s_task_queue_event_fd, &mainloop->read_fds);
 | 
						|
        if (s_task_queue_event_fd > mainloop->max_fd) {
 | 
						|
            mainloop->max_fd = s_task_queue_event_fd;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
esp_err_t esp_openthread_task_queue_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop)
 | 
						|
{
 | 
						|
    task_storage_t task_storage;
 | 
						|
 | 
						|
    if (FD_ISSET(s_task_queue_event_fd, &mainloop->read_fds)) {
 | 
						|
        uint64_t val;
 | 
						|
        ssize_t ret = read(s_task_queue_event_fd, &val, sizeof(val));
 | 
						|
        assert(ret == sizeof(val));
 | 
						|
    }
 | 
						|
 | 
						|
    ESP_RETURN_ON_FALSE(s_task_queue != NULL, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG,
 | 
						|
                        "OpenThread task queue not initialized");
 | 
						|
    while (xQueueReceive(s_task_queue, &task_storage, 0) == pdTRUE) {
 | 
						|
        task_storage.task(task_storage.arg);
 | 
						|
    }
 | 
						|
 | 
						|
    return ESP_OK;
 | 
						|
}
 | 
						|
 | 
						|
esp_err_t esp_openthread_task_queue_deinit(void)
 | 
						|
{
 | 
						|
    if (s_task_queue) {
 | 
						|
        vQueueDelete(s_task_queue);
 | 
						|
        s_task_queue = NULL;
 | 
						|
    }
 | 
						|
    if (s_task_queue_event_fd >= 0) {
 | 
						|
        close(s_task_queue_event_fd);
 | 
						|
        s_task_queue_event_fd = -1;
 | 
						|
    }
 | 
						|
    esp_openthread_platform_workflow_unregister(task_queue_workflow);
 | 
						|
    return ESP_OK;
 | 
						|
}
 |