mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-21 06:22:21 +02:00
fix(mdns): Refactor freertos linux compat layers
Move it to a separate component that could be shared by multiple network libs.
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
idf_component_register(SRCS freertos_linux.c queue_unique_ptr.cpp
|
idf_component_register(SRCS freertos_linux.c
|
||||||
|
osal/queue.cpp osal/event_group.cpp osal/mutex.cpp
|
||||||
INCLUDE_DIRS include)
|
INCLUDE_DIRS include)
|
||||||
|
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
272
common_components/linux_compat/freertos/freertos_linux.c
Normal file
272
common_components/linux_compat/freertos/freertos_linux.c
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "osal/osal_api.h"
|
||||||
|
|
||||||
|
static uint64_t s_semaphore_data = 0;
|
||||||
|
|
||||||
|
typedef enum queue_type_tag {
|
||||||
|
MUTEX_REC,
|
||||||
|
MUTEX,
|
||||||
|
SEMA,
|
||||||
|
QUEUE,
|
||||||
|
} queue_type_t;
|
||||||
|
|
||||||
|
struct generic_queue_handle {
|
||||||
|
queue_type_t type;
|
||||||
|
size_t item_size;
|
||||||
|
void *q;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct generic_queue_handle *create_generic_queue(queue_type_t type, uint32_t len, uint32_t item_size)
|
||||||
|
{
|
||||||
|
struct generic_queue_handle *h = calloc(1, sizeof(struct generic_queue_handle));
|
||||||
|
h->item_size = len;
|
||||||
|
h->type = type;
|
||||||
|
switch (type) {
|
||||||
|
default:
|
||||||
|
case QUEUE:
|
||||||
|
case SEMA:
|
||||||
|
h->q = osal_queue_create();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MUTEX:
|
||||||
|
case MUTEX_REC:
|
||||||
|
h->q = osal_mutex_create();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueHandle_t xQueueCreate(uint32_t uxQueueLength, uint32_t uxItemSize )
|
||||||
|
{
|
||||||
|
return (QueueHandle_t)create_generic_queue(QUEUE, uxQueueLength, uxItemSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait)
|
||||||
|
{
|
||||||
|
struct generic_queue_handle *h = xQueue;
|
||||||
|
return osal_queue_send(h->q, (uint8_t *)pvItemToQueue, h->item_size) ? pdTRUE : pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait )
|
||||||
|
{
|
||||||
|
return xQueueSend(xQueue, pvItemToQueue, xTicksToWait);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait)
|
||||||
|
{
|
||||||
|
struct generic_queue_handle *h = xQueue;
|
||||||
|
return osal_queue_recv(h->q, (uint8_t *)pvBuffer, h->item_size, xTicksToWait) ? pdTRUE : pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t xSemaphoreGive( QueueHandle_t xQueue)
|
||||||
|
{
|
||||||
|
struct generic_queue_handle *h = xQueue;
|
||||||
|
if (h->type == MUTEX) {
|
||||||
|
osal_mutex_give(h->q);
|
||||||
|
return pdTRUE;
|
||||||
|
}
|
||||||
|
return xQueueSend(xQueue, &s_semaphore_data, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
|
||||||
|
{
|
||||||
|
struct generic_queue_handle *h = xQueue;
|
||||||
|
if (h->type == MUTEX_REC) {
|
||||||
|
osal_mutex_give(h->q);
|
||||||
|
return pdTRUE;
|
||||||
|
}
|
||||||
|
return pdFALSE;
|
||||||
|
}
|
||||||
|
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
||||||
|
{
|
||||||
|
struct generic_queue_handle *h = xQueue;
|
||||||
|
if (h->type == MUTEX) {
|
||||||
|
osal_mutex_take(h->q);
|
||||||
|
return pdTRUE;
|
||||||
|
}
|
||||||
|
return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
|
||||||
|
{
|
||||||
|
struct generic_queue_handle *h = xQueue;
|
||||||
|
if (h->type == MUTEX_REC) {
|
||||||
|
osal_mutex_take(h->q);
|
||||||
|
return pdTRUE;
|
||||||
|
}
|
||||||
|
return pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void vQueueDelete( QueueHandle_t xQueue )
|
||||||
|
{
|
||||||
|
struct generic_queue_handle *h = xQueue;
|
||||||
|
if (h->q) {
|
||||||
|
if (h->type == MUTEX) {
|
||||||
|
osal_mutex_delete(h->q);
|
||||||
|
} else {
|
||||||
|
osal_queue_delete(h->q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(xQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueHandle_t xSemaphoreCreateBinary(void)
|
||||||
|
{
|
||||||
|
QueueHandle_t sempaphore = xQueueCreate(1, 1);
|
||||||
|
return sempaphore;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueHandle_t xSemaphoreCreateMutex(void)
|
||||||
|
{
|
||||||
|
return (QueueHandle_t)create_generic_queue(MUTEX, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueHandle_t xSemaphoreCreateRecursiveMutex(void)
|
||||||
|
{
|
||||||
|
return (QueueHandle_t)create_generic_queue(MUTEX_REC, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vTaskDelete(TaskHandle_t *task)
|
||||||
|
{
|
||||||
|
if (task == NULL) {
|
||||||
|
pthread_exit(0);
|
||||||
|
}
|
||||||
|
void *thread_rval = NULL;
|
||||||
|
pthread_join((pthread_t)task, &thread_rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vTaskSuspend(void *task)
|
||||||
|
{
|
||||||
|
vTaskDelete(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
TickType_t xTaskGetTickCount( void )
|
||||||
|
{
|
||||||
|
struct timespec spec;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &spec);
|
||||||
|
return spec.tv_nsec / 1000000 + spec.tv_sec * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vTaskDelay( const TickType_t xTicksToDelay )
|
||||||
|
{
|
||||||
|
usleep(xTicksToDelay * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pthread_task(void *params)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
void *const param;
|
||||||
|
TaskFunction_t task;
|
||||||
|
bool started;
|
||||||
|
} *pthread_params = params;
|
||||||
|
|
||||||
|
void *const param = pthread_params->param;
|
||||||
|
TaskFunction_t task = pthread_params->task;
|
||||||
|
pthread_params->started = true;
|
||||||
|
|
||||||
|
task(param);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
|
||||||
|
const char *const pcName,
|
||||||
|
const uint32_t usStackDepth,
|
||||||
|
void *const pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
TaskHandle_t *const pvCreatedTask,
|
||||||
|
const BaseType_t xCoreID)
|
||||||
|
{
|
||||||
|
xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask);
|
||||||
|
return pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
|
||||||
|
{
|
||||||
|
pthread_t new_thread = (pthread_t)NULL;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
struct {
|
||||||
|
void *const param;
|
||||||
|
TaskFunction_t task;
|
||||||
|
bool started;
|
||||||
|
} pthread_params = { .param = pvParameters, .task = pvTaskCode};
|
||||||
|
int res = pthread_attr_init(&attr);
|
||||||
|
assert(res == 0);
|
||||||
|
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||||
|
assert(res == 0);
|
||||||
|
res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
|
||||||
|
assert(res == 0);
|
||||||
|
|
||||||
|
if (pvCreatedTask) {
|
||||||
|
*pvCreatedTask = (void *)new_thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just wait till the task started so we can unwind params from the stack
|
||||||
|
while (pthread_params.started == false) {
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
return pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xTaskNotifyGive(TaskHandle_t task)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskHandle_t xTaskGetCurrentTaskHandle(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventGroupHandle_t xEventGroupCreate( void )
|
||||||
|
{
|
||||||
|
return osal_signal_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
|
||||||
|
{
|
||||||
|
osal_signal_delete(xEventGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
|
||||||
|
{
|
||||||
|
return osal_signal_clear(xEventGroup, uxBitsToClear);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup)
|
||||||
|
{
|
||||||
|
return osal_signal_get(xEventGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
|
||||||
|
{
|
||||||
|
return osal_signal_set(xEventGroup, uxBitsToSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
|
||||||
|
{
|
||||||
|
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
|
||||||
|
}
|
@ -10,3 +10,4 @@
|
|||||||
|
|
||||||
#define ESP_TASK_PRIO_MAX 25
|
#define ESP_TASK_PRIO_MAX 25
|
||||||
#define ESP_TASKD_EVENT_PRIO 5
|
#define ESP_TASKD_EVENT_PRIO 5
|
||||||
|
#define ESP_TASKD_EVENT_STACK 1024
|
@ -16,7 +16,9 @@
|
|||||||
typedef void *SemaphoreHandle_t;
|
typedef void *SemaphoreHandle_t;
|
||||||
typedef void *QueueHandle_t;
|
typedef void *QueueHandle_t;
|
||||||
typedef void *TaskHandle_t;
|
typedef void *TaskHandle_t;
|
||||||
|
typedef void *EventGroupHandle_t;
|
||||||
typedef uint32_t TickType_t;
|
typedef uint32_t TickType_t;
|
||||||
|
typedef TickType_t EventBits_t;
|
||||||
|
|
||||||
typedef void (*TaskFunction_t)( void * );
|
typedef void (*TaskFunction_t)( void * );
|
||||||
typedef unsigned int UBaseType_t;
|
typedef unsigned int UBaseType_t;
|
@ -0,0 +1,6 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
@ -3,11 +3,4 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
//
|
#pragma once
|
||||||
// Created by david on 1/13/23.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _QUEUE_H_
|
|
||||||
#define _QUEUE_H_
|
|
||||||
|
|
||||||
#endif //_QUEUE_H_
|
|
@ -3,11 +3,4 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
//
|
#pragma once
|
||||||
// Created by david on 1/13/23.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _SEMAPHR_H_
|
|
||||||
#define _SEMAPHR_H_
|
|
||||||
|
|
||||||
#endif //_SEMAPHR_H_
|
|
@ -26,7 +26,7 @@ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
|
|||||||
TaskHandle_t *const pvCreatedTask,
|
TaskHandle_t *const pvCreatedTask,
|
||||||
const BaseType_t xCoreID);
|
const BaseType_t xCoreID);
|
||||||
|
|
||||||
void xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask);
|
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask);
|
||||||
|
|
||||||
TickType_t xTaskGetTickCount( void );
|
TickType_t xTaskGetTickCount( void );
|
||||||
|
|
||||||
@ -35,11 +35,16 @@ void vQueueDelete( QueueHandle_t xQueue );
|
|||||||
QueueHandle_t xSemaphoreCreateBinary(void);
|
QueueHandle_t xSemaphoreCreateBinary(void);
|
||||||
|
|
||||||
QueueHandle_t xSemaphoreCreateMutex(void);
|
QueueHandle_t xSemaphoreCreateMutex(void);
|
||||||
|
QueueHandle_t xSemaphoreCreateRecursiveMutex(void);
|
||||||
|
|
||||||
BaseType_t xSemaphoreGive( QueueHandle_t xQueue);
|
BaseType_t xSemaphoreGive( QueueHandle_t xQueue);
|
||||||
|
|
||||||
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask );
|
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask );
|
||||||
|
|
||||||
|
BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue);
|
||||||
|
|
||||||
|
BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask );
|
||||||
|
|
||||||
void vTaskDelete(TaskHandle_t *task);
|
void vTaskDelete(TaskHandle_t *task);
|
||||||
|
|
||||||
QueueHandle_t xQueueCreate( uint32_t uxQueueLength,
|
QueueHandle_t xQueueCreate( uint32_t uxQueueLength,
|
||||||
@ -48,3 +53,23 @@ QueueHandle_t xQueueCreate( uint32_t uxQueueLength,
|
|||||||
uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);
|
uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);
|
||||||
|
|
||||||
uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);
|
uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);
|
||||||
|
|
||||||
|
void vTaskSuspend(void *task);
|
||||||
|
|
||||||
|
EventGroupHandle_t xEventGroupCreate( void );
|
||||||
|
void vEventGroupDelete( EventGroupHandle_t xEventGroup );
|
||||||
|
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear );
|
||||||
|
|
||||||
|
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xClearOnExit,
|
||||||
|
const BaseType_t xWaitForAllBits,
|
||||||
|
TickType_t xTicksToWait );
|
||||||
|
|
||||||
|
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup);
|
||||||
|
|
||||||
|
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet );
|
||||||
|
|
||||||
|
uint32_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait );
|
111
common_components/linux_compat/freertos/osal/event_group.cpp
Normal file
111
common_components/linux_compat/freertos/osal/event_group.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include "osal_api.h"
|
||||||
|
|
||||||
|
struct SignalGroupInternal {
|
||||||
|
std::condition_variable notify;
|
||||||
|
std::mutex m;
|
||||||
|
uint32_t flags{ 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
using SignalT = std::unique_ptr<SignalGroupInternal>;
|
||||||
|
|
||||||
|
class SignalGroup {
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit SignalGroup(): event_group(std::make_unique<SignalGroupInternal>()) {}
|
||||||
|
|
||||||
|
void set(uint32_t bits)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(event_group->m);
|
||||||
|
event_group->flags |= bits;
|
||||||
|
event_group->notify.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get()
|
||||||
|
{
|
||||||
|
return event_group->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(uint32_t bits)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(event_group->m);
|
||||||
|
event_group->flags &= ~bits;
|
||||||
|
event_group->notify.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
// waiting for all and clearing if set
|
||||||
|
bool wait(uint32_t flags, uint32_t time_ms)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(event_group->m);
|
||||||
|
return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&] {
|
||||||
|
if ((flags & event_group->flags) == flags)
|
||||||
|
{
|
||||||
|
event_group->flags &= ~flags;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// waiting for any bit, not clearing them
|
||||||
|
bool wait_any(uint32_t flags, uint32_t time_ms)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(event_group->m);
|
||||||
|
return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&] { return flags & event_group->flags; });
|
||||||
|
}
|
||||||
|
|
||||||
|
~SignalGroup() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SignalT event_group;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void *osal_signal_create()
|
||||||
|
{
|
||||||
|
auto signal = new SignalGroup;
|
||||||
|
return signal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void osal_signal_delete(void *s)
|
||||||
|
{
|
||||||
|
delete static_cast<SignalGroup *>(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t osal_signal_clear(void *s, uint32_t bits)
|
||||||
|
{
|
||||||
|
auto signal = static_cast<SignalGroup *>(s);
|
||||||
|
signal->clear(bits);
|
||||||
|
return signal->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t osal_signal_set(void *s, uint32_t bits)
|
||||||
|
{
|
||||||
|
auto signal = static_cast<SignalGroup *>(s);
|
||||||
|
signal->set(bits);
|
||||||
|
return signal->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t osal_signal_get(void *s)
|
||||||
|
{
|
||||||
|
auto signal = static_cast<SignalGroup *>(s);
|
||||||
|
return signal->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t osal_signal_wait(void *s, uint32_t flags, bool all, uint32_t timeout)
|
||||||
|
{
|
||||||
|
auto signal = static_cast<SignalGroup *>(s);
|
||||||
|
if (all) {
|
||||||
|
signal->wait(flags, timeout);
|
||||||
|
} else {
|
||||||
|
signal->wait_any(flags, timeout);
|
||||||
|
}
|
||||||
|
return signal->get();
|
||||||
|
}
|
31
common_components/linux_compat/freertos/osal/mutex.cpp
Normal file
31
common_components/linux_compat/freertos/osal/mutex.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <queue>
|
||||||
|
#include <mutex>
|
||||||
|
#include "osal_api.h"
|
||||||
|
|
||||||
|
void *osal_mutex_create()
|
||||||
|
{
|
||||||
|
auto mut = new std::recursive_mutex();
|
||||||
|
return mut;
|
||||||
|
}
|
||||||
|
|
||||||
|
void osal_mutex_delete(void *mut)
|
||||||
|
{
|
||||||
|
delete static_cast<std::recursive_mutex *>(mut);
|
||||||
|
}
|
||||||
|
|
||||||
|
void osal_mutex_take(void *m)
|
||||||
|
{
|
||||||
|
auto mut = static_cast<std::recursive_mutex *>(m);
|
||||||
|
mut->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void osal_mutex_give(void *m)
|
||||||
|
{
|
||||||
|
auto mut = static_cast<std::recursive_mutex *>(m);
|
||||||
|
mut->unlock();
|
||||||
|
}
|
34
common_components/linux_compat/freertos/osal/osal_api.h
Normal file
34
common_components/linux_compat/freertos/osal/osal_api.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// queue api
|
||||||
|
void *osal_queue_create(void);
|
||||||
|
void osal_queue_delete(void *q);
|
||||||
|
bool osal_queue_send(void *q, uint8_t *data, size_t len);
|
||||||
|
bool osal_queue_recv(void *q, uint8_t *data, size_t len, uint32_t ms);
|
||||||
|
|
||||||
|
// mutex api
|
||||||
|
void *osal_mutex_create(void);
|
||||||
|
void osal_mutex_delete(void *m);
|
||||||
|
void osal_mutex_take(void *m);
|
||||||
|
void osal_mutex_give(void *m);
|
||||||
|
|
||||||
|
// event groups
|
||||||
|
void *osal_signal_create(void);
|
||||||
|
void osal_signal_delete(void *s);
|
||||||
|
uint32_t osal_signal_clear(void *s, uint32_t bits);
|
||||||
|
uint32_t osal_signal_set(void *s, uint32_t bits);
|
||||||
|
uint32_t osal_signal_get(void *s);
|
||||||
|
uint32_t osal_signal_wait(void *s, uint32_t flags, bool all, uint32_t timeout);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
79
common_components/linux_compat/freertos/osal/queue.cpp
Normal file
79
common_components/linux_compat/freertos/osal/queue.cpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstring>
|
||||||
|
#include <queue>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <atomic>
|
||||||
|
#include "osal_api.h"
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class Queue {
|
||||||
|
public:
|
||||||
|
Queue(): q(), m(), c() {}
|
||||||
|
~Queue() {}
|
||||||
|
|
||||||
|
void send(std::unique_ptr<T> t)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m);
|
||||||
|
q.push(std::move(t));
|
||||||
|
c.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<T> receive(uint32_t ms)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m);
|
||||||
|
while (q.empty()) {
|
||||||
|
if (c.wait_for(lock, std::chrono::milliseconds(ms)) == std::cv_status::timeout) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::unique_ptr<T> val = std::move(q.front());
|
||||||
|
q.pop();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::queue<std::unique_ptr<T>> q;
|
||||||
|
mutable std::mutex m;
|
||||||
|
std::condition_variable c;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *osal_queue_create(void)
|
||||||
|
{
|
||||||
|
auto *q = new Queue<std::vector<uint8_t>>();
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
void osal_queue_delete(void *q)
|
||||||
|
{
|
||||||
|
auto *queue = static_cast<Queue<std::vector<uint8_t>> *>(q);
|
||||||
|
delete (queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool osal_queue_send(void *q, uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
auto v = std::make_unique<std::vector<uint8_t>>(len);
|
||||||
|
v->assign(data, data + len);
|
||||||
|
auto queue = static_cast<Queue<std::vector<uint8_t>> *>(q);
|
||||||
|
queue->send(std::move(v));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool osal_queue_recv(void *q, uint8_t *data, size_t len, uint32_t ms)
|
||||||
|
{
|
||||||
|
auto queue = static_cast<Queue<std::vector<uint8_t>> *>(q);
|
||||||
|
auto v = queue->receive(ms);
|
||||||
|
if (v == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(data, (void *)v->data(), len);
|
||||||
|
return true;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
set(EXTRA_COMPONENT_DIRS "../..")
|
set(EXTRA_COMPONENT_DIRS "../.. ../../../../common_components/linux_compat/freertos")
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
set(COMPONENTS main esp_netif_linux)
|
set(COMPONENTS main esp_netif_linux)
|
||||||
|
@ -1,174 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void *create_q(void);
|
|
||||||
|
|
||||||
void destroy_q(void *q);
|
|
||||||
|
|
||||||
bool send_q(void *q, uint8_t *data, size_t len);
|
|
||||||
|
|
||||||
bool recv_q(void *q, uint8_t *data, size_t len, uint32_t ms);
|
|
||||||
|
|
||||||
static uint64_t s_semaphore_data = 0;
|
|
||||||
|
|
||||||
struct queue_handle {
|
|
||||||
size_t item_size;
|
|
||||||
void *q;
|
|
||||||
};
|
|
||||||
|
|
||||||
QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize )
|
|
||||||
{
|
|
||||||
struct queue_handle *h = calloc(1, sizeof(struct queue_handle));
|
|
||||||
h->item_size = uxItemSize;
|
|
||||||
h->q = create_q();
|
|
||||||
return (QueueHandle_t)h;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait)
|
|
||||||
{
|
|
||||||
struct queue_handle *h = xQueue;
|
|
||||||
return send_q(h->q, (uint8_t *)pvItemToQueue, h->item_size) ? pdTRUE : pdFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait)
|
|
||||||
{
|
|
||||||
struct queue_handle *h = xQueue;
|
|
||||||
return recv_q(h->q, (uint8_t *)pvBuffer, h->item_size, xTicksToWait) ? pdTRUE : pdFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseType_t xSemaphoreGive( QueueHandle_t xQueue)
|
|
||||||
{
|
|
||||||
return xQueueSend(xQueue, &s_semaphore_data, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
|
||||||
{
|
|
||||||
return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vQueueDelete( QueueHandle_t xQueue )
|
|
||||||
{
|
|
||||||
struct queue_handle *h = xQueue;
|
|
||||||
if (h->q) {
|
|
||||||
destroy_q(h->q);
|
|
||||||
}
|
|
||||||
free(xQueue);
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueHandle_t xSemaphoreCreateBinary(void)
|
|
||||||
{
|
|
||||||
QueueHandle_t sempaphore = xQueueCreate(1, 1);
|
|
||||||
return sempaphore;
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueHandle_t xSemaphoreCreateMutex(void)
|
|
||||||
{
|
|
||||||
QueueHandle_t sempaphore = xQueueCreate(1, 1);
|
|
||||||
if (sempaphore) {
|
|
||||||
xSemaphoreGive(sempaphore);
|
|
||||||
}
|
|
||||||
return sempaphore;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vTaskDelete(TaskHandle_t *task)
|
|
||||||
{
|
|
||||||
if (task == NULL) {
|
|
||||||
pthread_exit(0);
|
|
||||||
}
|
|
||||||
void *thread_rval = NULL;
|
|
||||||
pthread_join((pthread_t)task, &thread_rval);
|
|
||||||
}
|
|
||||||
|
|
||||||
TickType_t xTaskGetTickCount( void )
|
|
||||||
{
|
|
||||||
struct timespec spec;
|
|
||||||
clock_gettime(CLOCK_REALTIME, &spec);
|
|
||||||
return spec.tv_nsec / 1000000 + spec.tv_sec * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vTaskDelay( const TickType_t xTicksToDelay )
|
|
||||||
{
|
|
||||||
usleep(xTicksToDelay * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *pthread_task(void *params)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
void *const param;
|
|
||||||
TaskFunction_t task;
|
|
||||||
bool started;
|
|
||||||
} *pthread_params = params;
|
|
||||||
|
|
||||||
void *const param = pthread_params->param;
|
|
||||||
TaskFunction_t task = pthread_params->task;
|
|
||||||
pthread_params->started = true;
|
|
||||||
|
|
||||||
task(param);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
|
|
||||||
const char *const pcName,
|
|
||||||
const uint32_t usStackDepth,
|
|
||||||
void *const pvParameters,
|
|
||||||
UBaseType_t uxPriority,
|
|
||||||
TaskHandle_t *const pvCreatedTask,
|
|
||||||
const BaseType_t xCoreID)
|
|
||||||
{
|
|
||||||
xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask);
|
|
||||||
return pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
|
|
||||||
{
|
|
||||||
pthread_t new_thread = (pthread_t)NULL;
|
|
||||||
pthread_attr_t attr;
|
|
||||||
struct {
|
|
||||||
void *const param;
|
|
||||||
TaskFunction_t task;
|
|
||||||
bool started;
|
|
||||||
} pthread_params = { .param = pvParameters, .task = pvTaskCode};
|
|
||||||
int res = pthread_attr_init(&attr);
|
|
||||||
assert(res == 0);
|
|
||||||
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
||||||
assert(res == 0);
|
|
||||||
res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
|
|
||||||
assert(res == 0);
|
|
||||||
|
|
||||||
if (pvCreatedTask) {
|
|
||||||
*pvCreatedTask = (void *)new_thread;
|
|
||||||
}
|
|
||||||
|
|
||||||
// just wait till the task started so we can unwind params from the stack
|
|
||||||
while (pthread_params.started == false) {
|
|
||||||
usleep(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void xTaskNotifyGive(TaskHandle_t task)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskHandle_t xTaskGetCurrentTaskHandle(void)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "queue_unique_ptr.hpp"
|
|
||||||
#include <cstdint>
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
extern "C" void *create_q(void)
|
|
||||||
{
|
|
||||||
auto *q = new QueueMock<std::vector<uint8_t>>();
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void destroy_q(void *q)
|
|
||||||
{
|
|
||||||
auto *queue = static_cast<QueueMock<std::vector<uint8_t>> *>(q);
|
|
||||||
delete (queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" bool send_q(void *q, uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
auto v = std::make_unique<std::vector<uint8_t>>(len);
|
|
||||||
v->assign(data, data + len);
|
|
||||||
auto queue = static_cast<QueueMock<std::vector<uint8_t>> *>(q);
|
|
||||||
queue->send(std::move(v));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" bool recv_q(void *q, uint8_t *data, size_t len, uint32_t ms)
|
|
||||||
{
|
|
||||||
auto queue = static_cast<QueueMock<std::vector<uint8_t>> *>(q);
|
|
||||||
auto v = queue->receive(ms);
|
|
||||||
if (v == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
memcpy(data, (void *)v->data(), len);
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <mutex>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <memory>
|
|
||||||
#include <thread>
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class QueueMock {
|
|
||||||
public:
|
|
||||||
QueueMock(void): q(), m(), c() {}
|
|
||||||
~QueueMock(void) {}
|
|
||||||
|
|
||||||
void send(std::unique_ptr<T> t)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m);
|
|
||||||
q.push(std::move(t));
|
|
||||||
c.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<T> receive(uint32_t ms)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(m);
|
|
||||||
while (q.empty()) {
|
|
||||||
if (c.wait_for(lock, std::chrono::milliseconds(ms)) == std::cv_status::timeout) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::unique_ptr<T> val = std::move(q.front());
|
|
||||||
q.pop();
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::queue<std::unique_ptr<T>> q;
|
|
||||||
mutable std::mutex m;
|
|
||||||
std::condition_variable c;
|
|
||||||
};
|
|
Reference in New Issue
Block a user