更新模板到最新状态
This commit is contained in:
131
sal/esp32/chip/uart_esp32.c
Executable file
131
sal/esp32/chip/uart_esp32.c
Executable file
@@ -0,0 +1,131 @@
|
||||
#include "drivers/chip/uart.h"
|
||||
|
||||
#include "driver/uart.h"
|
||||
|
||||
#define SYS_LOG_DOMAIN "uart"
|
||||
#include "sys_log.h"
|
||||
|
||||
void drv_uart_pin_configure_txd(hal_id_t id, uint8_t pin)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
void drv_uart_pin_configure_rxd(hal_id_t id, uint8_t pin)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
void drv_uart_enable(hal_id_t id)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
void drv_uart_disable(hal_id_t id)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
void drv_uart_init(hal_id_t id, const uart_param_t *param)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
void drv_uart_deinit(hal_id_t id)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
void drv_uart_set_br(hal_id_t id, unsigned clk, unsigned baudrate)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
unsigned drv_uart_get_br(hal_id_t id, unsigned clk)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int drv_uart_poll_read(hal_id_t id, void *data)
|
||||
{
|
||||
return uart_read_bytes(id, data, 1, 0);
|
||||
}
|
||||
|
||||
int drv_uart_poll_write(hal_id_t id, uint8_t data)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_uart_fifo_read(hal_id_t id, void *data, int size)
|
||||
{
|
||||
int ret = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if (drv_uart_poll_read(id, &((char *)data)[i]) <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_uart_fifo_fill(hal_id_t id, const void *data, int size)
|
||||
{
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
{
|
||||
if (drv_uart_poll_write(id, ((char *)data)[i]) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
int drv_uart_irq_callback_enable(hal_id_t id, uart_isr_cb_fn cb)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int drv_uart_irq_callback_disable(hal_id_t id)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void drv_uart_irq_tx_enable(hal_id_t id, int priority)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
void drv_uart_irq_tx_disable(hal_id_t id)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
void drv_uart_irq_rx_enable(hal_id_t id, int priority)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
void drv_uart_irq_rx_disable(hal_id_t id)
|
||||
{
|
||||
SYS_LOG_ERR("func not set");
|
||||
}
|
||||
|
||||
bool drv_uart_wait_tx_busy(hal_id_t id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool drv_uart_is_tx_ready(hal_id_t id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool drv_uart_is_rx_ready(hal_id_t id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
27
sal/esp32/kernel/os_debug.h
Executable file
27
sal/esp32/kernel/os_debug.h
Executable file
@@ -0,0 +1,27 @@
|
||||
#ifndef _OS_DEBUG_H_
|
||||
#define _OS_DEBUG_H_
|
||||
|
||||
#undef CONFIG_SYS_LOG_LEVEL
|
||||
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
|
||||
#define SYS_LOG_DOMAIN "OS"
|
||||
#include "sys_log.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define OS_LOG(FLAG, FMT, ...) _DO_SYS_LOG(FLAG, FMT, ##__VA_ARGS__)
|
||||
#define OS_DBG(FMT, ...) SYS_LOG_DBG(FMT, ##__VA_ARGS__)
|
||||
#define OS_INF(FMT, ...) SYS_LOG_INF(FMT, ##__VA_ARGS__)
|
||||
#define OS_WRN(FMT, ...) SYS_LOG_WRN(FMT, ##__VA_ARGS__)
|
||||
#define OS_ERR(FMT, ...) SYS_LOG_ERR(FMT, ##__VA_ARGS__)
|
||||
|
||||
#define OS_ASS_ISR() SYS_ASSERT(!os_is_isr_context(), "function '%s' exec in ISR contex", __FUNCTION__)
|
||||
#define OS_ASS_HDL(EXP, HANDLE) SYS_ASSERT(EXP, "handle %p", HANDLE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OS_DEBUG_H_ */
|
||||
46
sal/esp32/kernel/os_heap.c
Executable file
46
sal/esp32/kernel/os_heap.c
Executable file
@@ -0,0 +1,46 @@
|
||||
#include "os/os.h"
|
||||
#include "os_util.h"
|
||||
#include "portable.h"
|
||||
#include <string.h>
|
||||
|
||||
void *os_malloc(size_t size)
|
||||
{
|
||||
return pvPortMalloc(size);
|
||||
}
|
||||
|
||||
void *os_calloc(size_t size)
|
||||
{
|
||||
void *ret = os_malloc(size);
|
||||
if (ret)
|
||||
{
|
||||
memset(ret, 0, size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *os_realloc(void *p, size_t size)
|
||||
{
|
||||
#if (configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1)
|
||||
return realloc(p, size);
|
||||
#else
|
||||
OS_DBG("%s() fail @ %d function not support!\r\n", __func__, __LINE__);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void os_free(void *p)
|
||||
{
|
||||
vPortFree(p);
|
||||
}
|
||||
|
||||
void os_heap_info(size_t *used_size, size_t *free_size, size_t *max_block_size)
|
||||
{
|
||||
if (max_block_size)
|
||||
{
|
||||
*max_block_size = 0;
|
||||
}
|
||||
if (used_size)
|
||||
*used_size = 0;
|
||||
if (free_size)
|
||||
*free_size = xPortGetFreeHeapSize();
|
||||
}
|
||||
124
sal/esp32/kernel/os_hook.c
Executable file
124
sal/esp32/kernel/os_hook.c
Executable file
@@ -0,0 +1,124 @@
|
||||
#define SYS_LOG_DOMAIN "OS"
|
||||
#include "os/os.h"
|
||||
#include "sys_log.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];
|
||||
|
||||
void vAssertCalled(void);
|
||||
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName);
|
||||
void vApplicationMallocFailedHook(void);
|
||||
void vApplicationIdleHook(void);
|
||||
void vApplicationTickHook(void);
|
||||
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
|
||||
StackType_t **ppxTimerTaskStackBuffer,
|
||||
uint32_t *pulTimerTaskStackSize);
|
||||
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
|
||||
StackType_t **ppxIdleTaskStackBuffer,
|
||||
uint32_t *pulIdleTaskStackSize);
|
||||
|
||||
void vAssertCalled(void)
|
||||
{
|
||||
volatile unsigned long looping = 0;
|
||||
|
||||
os_interrupt_disable();
|
||||
{
|
||||
/* Use the debugger to set ul to a non-zero value in order to step out
|
||||
* of this function to determine why it was called. */
|
||||
while (looping == 0LU)
|
||||
{
|
||||
}
|
||||
}
|
||||
os_interrupt_enable();
|
||||
}
|
||||
|
||||
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName)
|
||||
{
|
||||
SYS_LOG_ERR("task %p(%s) stack over flow\n", pxTask, pcTaskName);
|
||||
/* Run time stack overflow checking is performed if
|
||||
* configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
|
||||
* function is called if a stack overflow is detected. */
|
||||
taskDISABLE_INTERRUPTS();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void vApplicationMallocFailedHook(void)
|
||||
{
|
||||
/* Called if a call to pvPortMalloc() fails because there is insufficient
|
||||
* free memory available in the FreeRTOS heap. pvPortMalloc() is called
|
||||
* internally by FreeRTOS API functions that create tasks, queues, software
|
||||
* timers, and semaphores. The size of the FreeRTOS heap is set by the
|
||||
* configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
|
||||
taskDISABLE_INTERRUPTS();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void vApplicationIdleHook(void)
|
||||
{
|
||||
/* This is just a trivial example of an idle hook. It is called on each
|
||||
* cycle of the idle task. It must *NOT* attempt to block. In this case the
|
||||
* idle task just queries the amount of FreeRTOS heap that remains. See the
|
||||
* memory management section on the https://www.FreeRTOS.org web site for memory
|
||||
* management options. If there is a lot of heap memory free then the
|
||||
* configTOTAL_HEAP_SIZE value in FreeRTOSConfig.h can be reduced to free up
|
||||
* RAM. */
|
||||
}
|
||||
|
||||
void vApplicationTickHook(void)
|
||||
{
|
||||
}
|
||||
|
||||
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
|
||||
StackType_t **ppxTimerTaskStackBuffer,
|
||||
uint32_t *pulTimerTaskStackSize)
|
||||
{
|
||||
/* If the buffers to be provided to the Timer task are declared inside this
|
||||
* function then they must be declared static - otherwise they will be allocated on
|
||||
* the stack and so not exists after this function exits. */
|
||||
static StaticTask_t xTimerTaskTCB;
|
||||
|
||||
/* Pass out a pointer to the StaticTask_t structure in which the Timer
|
||||
* task's state will be stored. */
|
||||
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
|
||||
|
||||
/* Pass out the array that will be used as the Timer task's stack. */
|
||||
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
|
||||
|
||||
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
|
||||
* Note that, as the array is necessarily of type StackType_t,
|
||||
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
|
||||
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
|
||||
}
|
||||
|
||||
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
|
||||
* implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
|
||||
* used by the Idle task. */
|
||||
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
|
||||
StackType_t **ppxIdleTaskStackBuffer,
|
||||
uint32_t *pulIdleTaskStackSize)
|
||||
{
|
||||
/* If the buffers to be provided to the Idle task are declared inside this
|
||||
* function then they must be declared static - otherwise they will be allocated on
|
||||
* the stack and so not exists after this function exits. */
|
||||
static StaticTask_t xIdleTaskTCB;
|
||||
static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE];
|
||||
|
||||
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
|
||||
* state will be stored. */
|
||||
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
|
||||
|
||||
/* Pass out the array that will be used as the Idle task's stack. */
|
||||
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
|
||||
|
||||
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
|
||||
* Note that, as the array is necessarily of type StackType_t,
|
||||
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
|
||||
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
|
||||
}
|
||||
903
sal/esp32/kernel/os_kit.c
Executable file
903
sal/esp32/kernel/os_kit.c
Executable file
@@ -0,0 +1,903 @@
|
||||
#include "os/os.h"
|
||||
#include "os_util.h"
|
||||
#include "k_kit.h"
|
||||
|
||||
static os_work_q_t s_default_work_q_handle;
|
||||
os_work_q_t *default_os_work_q_hdl = &s_default_work_q_handle;
|
||||
|
||||
static void _os_work_q_thread(void *arg);
|
||||
static void _os_work_q_resume(void *arg);
|
||||
|
||||
static void _os_work_q_thread(void *arg)
|
||||
{
|
||||
os_work_q_list_t *list = arg;
|
||||
for (;;)
|
||||
{
|
||||
k_tick_t tick = k_work_q_handler(&list->work_q_handle);
|
||||
os_sem_take(&list->sem_handle, OS_TicksToMSecs(tick));
|
||||
}
|
||||
}
|
||||
|
||||
static void _os_work_q_resume(void *arg)
|
||||
{
|
||||
os_sem_release(arg);
|
||||
}
|
||||
|
||||
os_state os_work_q_create(os_work_q_t *work_q_handle, // 队列句柄
|
||||
const char *name, // 队列名
|
||||
size_t stack_size, // 栈大小(字节)
|
||||
os_priority priority // 优先级(0 为最低,CONFIG_OS_MAX_PRIORITY 为最高。若输入为负值则表示优先级为 (CONFIG_OS_MAX_PRIORITY + 1 + priority))
|
||||
)
|
||||
{
|
||||
os_work_q_list_t *list = NULL;
|
||||
os_state ret;
|
||||
|
||||
do
|
||||
{
|
||||
if (os_work_q_is_valid(work_q_handle) != false)
|
||||
{
|
||||
OS_WRN("work_q is initialized");
|
||||
ret = OS_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
list = os_malloc(sizeof(*list));
|
||||
if (list == NULL)
|
||||
{
|
||||
ret = OS_E_NOMEM;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(list, 0, sizeof(*list));
|
||||
}
|
||||
|
||||
if (k_work_q_create(&list->work_q_handle) != 0)
|
||||
{
|
||||
ret = OS_E_NOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = os_sem_create(&list->sem_handle, 0, 1);
|
||||
if (ret != OS_OK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ret = os_thread_create(&list->thread,
|
||||
name,
|
||||
_os_work_q_thread,
|
||||
list,
|
||||
stack_size,
|
||||
priority);
|
||||
if (ret != OS_OK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (work_q_handle)
|
||||
{
|
||||
work_q_handle->handle = list;
|
||||
}
|
||||
|
||||
struct os_thread_handle *thread_handle = list->thread.handle;
|
||||
thread_handle->work_q_list = list;
|
||||
|
||||
k_work_q_resume_regist(&list->work_q_handle, _os_work_q_resume, &list->sem_handle);
|
||||
|
||||
ret = OS_OK;
|
||||
|
||||
} while (0);
|
||||
|
||||
if (ret != OS_OK)
|
||||
{
|
||||
if (list)
|
||||
{
|
||||
if (list->thread.handle)
|
||||
os_thread_delete(&list->thread);
|
||||
if (list->sem_handle.handle)
|
||||
os_sem_delete(&list->sem_handle);
|
||||
if (list->work_q_handle.hdl)
|
||||
k_work_q_delete(&list->work_q_handle);
|
||||
os_free(list);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_state os_work_q_delete(os_work_q_t *work_q_handle)
|
||||
{
|
||||
OS_ASS_ISR();
|
||||
|
||||
os_state ret;
|
||||
|
||||
do
|
||||
{
|
||||
if (os_work_q_is_valid(work_q_handle) == false)
|
||||
{
|
||||
OS_WRN("work_q is invalid");
|
||||
ret = OS_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
os_scheduler_suspend();
|
||||
|
||||
os_work_q_list_t *list = work_q_handle->handle;
|
||||
if (list)
|
||||
{
|
||||
os_thread_delete(&list->thread);
|
||||
os_sem_delete(&list->sem_handle);
|
||||
k_work_q_delete(&list->work_q_handle);
|
||||
os_free(list);
|
||||
work_q_handle->handle = NULL;
|
||||
ret = OS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
OS_ERR("err %p", work_q_handle);
|
||||
ret = OS_E_PARAM;
|
||||
}
|
||||
|
||||
os_scheduler_resume();
|
||||
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool os_work_q_is_valid(os_work_q_t *work_q_handle)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (work_q_handle == NULL || work_q_handle->handle == NULL)
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = k_work_q_is_valid(work_q_handle->handle);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool os_work_q_delayed_state(os_work_q_t *work_q_handle)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (os_work_q_is_valid(work_q_handle) == false)
|
||||
{
|
||||
OS_WRN("work_q is invalid");
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = k_work_q_delayed_state(work_q_handle->handle);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool os_work_q_ready_state(os_work_q_t *work_q_handle)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (os_work_q_is_valid(work_q_handle) == false)
|
||||
{
|
||||
OS_WRN("work_q is invalid");
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = k_work_q_ready_state(work_q_handle->handle);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_state os_work_create(os_work_t *work_handle, const char *name, os_work_fn work_route, void *arg, uint8_t sub_prior)
|
||||
{
|
||||
OS_ASS_ISR();
|
||||
k_err_t ret = k_work_create((k_work_t *)work_handle, name, (k_work_fn)work_route, arg, sub_prior);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
return OS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OS_E_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
os_state os_work_create_default(os_work_t *work_handle, const char *name, os_work_fn work_route, void *arg, uint8_t sub_prior, os_time_t delay_ms)
|
||||
{
|
||||
if (!os_work_is_valid(work_handle))
|
||||
{
|
||||
os_state ret = os_work_create(work_handle, name, work_route, arg, sub_prior);
|
||||
if (ret == OS_OK)
|
||||
{
|
||||
os_work_submit(default_os_work_q_hdl, work_handle, delay_ms);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void os_work_delete(os_work_t *work_handle)
|
||||
{
|
||||
OS_ASS_ISR();
|
||||
k_work_delete((k_work_t *)work_handle);
|
||||
}
|
||||
|
||||
bool os_work_is_valid(os_work_t *work_handle)
|
||||
{
|
||||
bool ret = k_work_is_valid((k_work_t *)work_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool os_work_is_pending(os_work_t *work_handle)
|
||||
{
|
||||
bool ret = k_work_is_pending((k_work_t *)work_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_time_t os_work_time_remain(os_work_t *work_handle)
|
||||
{
|
||||
k_tick_t ret = k_work_time_remain((k_work_t *)work_handle);
|
||||
return os_calc_ticks_to_msec(ret);
|
||||
}
|
||||
|
||||
void os_work_submit(os_work_q_t *work_q_handle, os_work_t *work_handle, os_time_t delay_ms)
|
||||
{
|
||||
if (os_work_q_is_valid(work_q_handle) == false)
|
||||
{
|
||||
OS_WRN("work_q is invalid");
|
||||
}
|
||||
else
|
||||
{
|
||||
k_work_submit(work_q_handle->handle, (k_work_t *)work_handle, os_calc_msec_to_ticks(delay_ms));
|
||||
}
|
||||
}
|
||||
|
||||
void os_work_resume(os_work_t *work_handle, os_time_t delay_ms)
|
||||
{
|
||||
k_work_resume((k_work_t *)work_handle, os_calc_msec_to_ticks(delay_ms));
|
||||
}
|
||||
|
||||
void os_work_suspend(os_work_t *work_handle)
|
||||
{
|
||||
k_work_suspend((k_work_t *)work_handle);
|
||||
}
|
||||
|
||||
void os_work_yield(os_time_t ms)
|
||||
{
|
||||
k_work_yield(os_calc_msec_to_ticks(ms));
|
||||
}
|
||||
|
||||
void os_work_sleep(os_time_t ms)
|
||||
{
|
||||
k_work_sleep(os_calc_msec_to_ticks(ms));
|
||||
}
|
||||
|
||||
void os_work_later(os_time_t ms)
|
||||
{
|
||||
k_work_later(os_calc_msec_to_ticks(ms));
|
||||
}
|
||||
|
||||
void os_work_later_until(os_time_t ms)
|
||||
{
|
||||
k_work_later_until(os_calc_msec_to_ticks(ms));
|
||||
}
|
||||
|
||||
#include "os/os.h"
|
||||
#include "os_util.h"
|
||||
|
||||
#include "k_kit.h"
|
||||
#include "os/os_semaphore.h"
|
||||
#include "queue.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static void *_os_wait_memory(void *(*fn)(void *func_handle, va_list arp), void *func_handle, os_sem_t *sem, os_time_t wait_ms, ...);
|
||||
static void *_os_ipc_fifo_take(void *fifo_handle, va_list arp);
|
||||
static void *_os_ipc_queue_recv(void *queue_handle, va_list arp);
|
||||
static void *_os_ipc_queue_send(void *queue_handle, va_list arp);
|
||||
static void *_os_ipc_queue_alloc(void *queue_handle, va_list arp);
|
||||
static void *_os_ipc_queue_take(void *queue_handle, va_list arp);
|
||||
|
||||
struct os_fifo_q_handle
|
||||
{
|
||||
k_fifo_t handle;
|
||||
os_sem_t sem_take;
|
||||
};
|
||||
|
||||
os_state os_fifo_q_create(os_fifo_t *fifo_handle)
|
||||
{
|
||||
os_state ret;
|
||||
|
||||
do
|
||||
{
|
||||
struct os_fifo_q_handle *fifo = os_malloc(sizeof(*fifo));
|
||||
if (fifo == NULL)
|
||||
{
|
||||
fifo_handle->handle = NULL;
|
||||
ret = OS_E_NOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(fifo, 0, sizeof(*fifo));
|
||||
|
||||
if (k_fifo_q_create(&fifo->handle) != 0)
|
||||
{
|
||||
os_free(fifo);
|
||||
ret = OS_E_NOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
os_sem_create(&fifo->sem_take, 0, 1);
|
||||
fifo_handle->handle = fifo;
|
||||
|
||||
ret = OS_OK;
|
||||
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_state os_fifo_q_delete(os_fifo_t *fifo_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_fifo_q_is_valid(fifo_handle), fifo_handle->handle);
|
||||
|
||||
struct os_fifo_q_handle *fifo = fifo_handle->handle;
|
||||
|
||||
os_scheduler_suspend();
|
||||
os_sem_delete(&fifo->sem_take);
|
||||
k_fifo_q_delete(&fifo->handle);
|
||||
os_free(fifo);
|
||||
fifo_handle->handle = NULL;
|
||||
os_scheduler_resume();
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_fifo_q_clr(os_fifo_t *fifo_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_fifo_q_is_valid(fifo_handle), fifo_handle->handle);
|
||||
|
||||
struct os_fifo_q_handle *fifo = fifo_handle->handle;
|
||||
k_fifo_q_clr(&fifo->handle);
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
static void *_os_wait_memory(void *(*fn)(void *func_handle, va_list arp), void *func_handle, os_sem_t *sem, os_time_t wait_ms, ...)
|
||||
{
|
||||
va_list arp;
|
||||
va_start(arp, wait_ms);
|
||||
void *ret = fn(func_handle, arp);
|
||||
va_end(arp);
|
||||
|
||||
if (ret == NULL && os_scheduler_is_running() != false && !os_is_isr_context())
|
||||
{
|
||||
TickType_t wait_ticks = os_calc_msec_to_ticks(wait_ms);
|
||||
int wakeup_tick = os_get_sys_ticks() + wait_ticks;
|
||||
|
||||
if (wait_ms)
|
||||
{
|
||||
while (wait_ticks == portMAX_DELAY || (int)(wakeup_tick - os_get_sys_ticks()) > 0)
|
||||
{
|
||||
os_sem_take(sem, wait_ms);
|
||||
|
||||
va_start(arp, wait_ms);
|
||||
ret = fn(func_handle, arp);
|
||||
va_end(arp);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
os_sem_release(sem);
|
||||
break;
|
||||
}
|
||||
|
||||
wait_ms = wakeup_tick - os_get_sys_ticks();
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == NULL)
|
||||
{
|
||||
OS_DBG("waiting semaphore %p timeout", sem);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void os_fifo_q_regist(os_fifo_t *fifo_handle, os_work_t *work_handle, int delay_ticks)
|
||||
{
|
||||
struct os_fifo_q_handle *fifo = fifo_handle->handle;
|
||||
k_fifo_q_regist(&fifo->handle, (k_work_t *)work_handle, delay_ticks);
|
||||
}
|
||||
|
||||
void os_fifo_q_unregist(os_fifo_t *fifo_handle)
|
||||
{
|
||||
struct os_fifo_q_handle *fifo = fifo_handle->handle;
|
||||
k_fifo_q_unregist(&fifo->handle);
|
||||
}
|
||||
|
||||
void *os_fifo_alloc(size_t size)
|
||||
{
|
||||
OS_ASS_ISR();
|
||||
return k_fifo_alloc(size);
|
||||
}
|
||||
|
||||
os_state os_fifo_free(void *fifo_data)
|
||||
{
|
||||
os_state ret;
|
||||
if (k_fifo_free(fifo_data) == 0)
|
||||
{
|
||||
ret = OS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = OS_E_PARAM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_state os_fifo_put(os_fifo_t *fifo_handle, void *fifo_data)
|
||||
{
|
||||
OS_ASS_HDL(os_fifo_q_is_valid(fifo_handle), fifo_handle->handle);
|
||||
|
||||
struct os_fifo_q_handle *fifo = fifo_handle->handle;
|
||||
os_state ret;
|
||||
|
||||
if (k_fifo_put(&fifo->handle, fifo_data) == 0)
|
||||
{
|
||||
os_sem_release(&fifo->sem_take);
|
||||
ret = OS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = OS_E_PARAM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *_os_ipc_fifo_take(void *fifo_handle, va_list arp)
|
||||
{
|
||||
return k_fifo_take(fifo_handle);
|
||||
}
|
||||
|
||||
void *os_fifo_take(os_fifo_t *fifo_handle, os_time_t wait_ms)
|
||||
{
|
||||
OS_ASS_HDL(os_fifo_q_is_valid(fifo_handle), fifo_handle->handle);
|
||||
|
||||
struct os_fifo_q_handle *fifo = fifo_handle->handle;
|
||||
void *ret = _os_wait_memory(_os_ipc_fifo_take, &fifo->handle, &fifo->sem_take, wait_ms);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *os_fifo_peek_head(os_fifo_t *fifo_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_fifo_q_is_valid(fifo_handle), fifo_handle->handle);
|
||||
struct os_fifo_q_handle *fifo = fifo_handle->handle;
|
||||
void *ret = k_fifo_peek_head(&fifo->handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *os_fifo_peek_tail(os_fifo_t *fifo_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_fifo_q_is_valid(fifo_handle), fifo_handle->handle);
|
||||
struct os_fifo_q_handle *fifo = fifo_handle->handle;
|
||||
void *ret = k_fifo_peek_tail(&fifo->handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool os_fifo_q_is_valid(os_fifo_t *fifo_handle)
|
||||
{
|
||||
if (fifo_handle && fifo_handle->handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct os_queue_handle
|
||||
{
|
||||
k_queue_t handle;
|
||||
os_sem_t sem_send;
|
||||
os_sem_t sem_recv;
|
||||
};
|
||||
|
||||
os_state os_queue_create(os_queue_t *queue_handle, size_t queue_length, size_t item_size)
|
||||
{
|
||||
os_state ret;
|
||||
|
||||
do
|
||||
{
|
||||
struct os_queue_handle *queue = os_malloc(sizeof(*queue));
|
||||
if (queue == NULL)
|
||||
{
|
||||
queue_handle->handle = NULL;
|
||||
ret = OS_E_NOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(queue, 0, sizeof(*queue));
|
||||
|
||||
if (k_queue_create(&queue->handle, queue_length, item_size) != 0)
|
||||
{
|
||||
os_free(queue);
|
||||
ret = OS_E_NOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
os_sem_create(&queue->sem_recv, 0, 1);
|
||||
os_sem_create(&queue->sem_send, 0, 1);
|
||||
queue_handle->handle = queue;
|
||||
|
||||
ret = OS_OK;
|
||||
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_state os_queue_delete(os_queue_t *queue_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_queue_is_valid(queue_handle), queue_handle->handle);
|
||||
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
|
||||
os_scheduler_suspend();
|
||||
os_sem_delete(&queue->sem_recv);
|
||||
os_sem_delete(&queue->sem_send);
|
||||
k_queue_delete(&queue->handle);
|
||||
os_free(queue);
|
||||
queue_handle->handle = NULL;
|
||||
os_scheduler_resume();
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_queue_clr(os_queue_t *queue_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_queue_is_valid(queue_handle), queue_handle->handle);
|
||||
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
k_queue_clr(&queue->handle);
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
void os_queue_regist(os_queue_t *queue_handle, os_work_t *work_handle, int delay_ticks)
|
||||
{
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
k_queue_regist(&queue->handle, (k_work_t *)work_handle, delay_ticks);
|
||||
}
|
||||
|
||||
void os_queue_unregist(os_queue_t *queue_handle)
|
||||
{
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
k_queue_unregist(&queue->handle);
|
||||
}
|
||||
|
||||
static void *_os_ipc_queue_recv(void *queue_handle, va_list arp)
|
||||
{
|
||||
void *dst = va_arg(arp, void *);
|
||||
if (k_queue_recv(queue_handle, dst) == 0)
|
||||
{
|
||||
return (void *)!NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
os_state os_queue_recv(os_queue_t *queue_handle, void *dst, os_time_t wait_ms)
|
||||
{
|
||||
OS_ASS_HDL(os_queue_is_valid(queue_handle), queue_handle->handle);
|
||||
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
os_state ret;
|
||||
if (_os_wait_memory(_os_ipc_queue_recv, &queue->handle, &queue->sem_recv, wait_ms, dst) == NULL)
|
||||
{
|
||||
ret = OS_E_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sem_release(&queue->sem_send);
|
||||
ret = OS_OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *_os_ipc_queue_send(void *queue_handle, va_list arp)
|
||||
{
|
||||
const void *src = va_arg(arp, void *);
|
||||
if (k_queue_send(queue_handle, src) == 0)
|
||||
{
|
||||
return (void *)!NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
os_state os_queue_send(os_queue_t *queue_handle, const void *src, os_time_t wait_ms)
|
||||
{
|
||||
OS_ASS_HDL(os_queue_is_valid(queue_handle), queue_handle->handle);
|
||||
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
os_state ret;
|
||||
|
||||
if (_os_wait_memory(_os_ipc_queue_send, &queue->handle, &queue->sem_send, wait_ms, src) == NULL)
|
||||
{
|
||||
ret = OS_E_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sem_release(&queue->sem_recv);
|
||||
ret = OS_OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *_os_ipc_queue_alloc(void *queue_handle, va_list arp)
|
||||
{
|
||||
return k_queue_alloc(queue_handle);
|
||||
}
|
||||
|
||||
void *os_queue_alloc(os_queue_t *queue_handle, os_time_t wait_ms)
|
||||
{
|
||||
OS_ASS_HDL(os_queue_is_valid(queue_handle), queue_handle->handle);
|
||||
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
void *ret = _os_wait_memory(_os_ipc_queue_alloc, &queue->handle, &queue->sem_send, wait_ms);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_state os_queue_free(void *queue_data)
|
||||
{
|
||||
os_state ret;
|
||||
|
||||
if (k_queue_free(queue_data) == 0)
|
||||
{
|
||||
k_queue_t *handle = k_queue_read_handle(queue_data);
|
||||
struct os_queue_handle *queue = OS_CONTAINER_OF(handle, struct os_queue_handle, handle);
|
||||
os_sem_release(&queue->sem_send);
|
||||
ret = OS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = OS_E_PARAM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_state os_queue_put(void *queue_data)
|
||||
{
|
||||
os_state ret;
|
||||
|
||||
if (k_queue_put(queue_data) == 0)
|
||||
{
|
||||
k_queue_t *handle = k_queue_read_handle(queue_data);
|
||||
struct os_queue_handle *queue = OS_CONTAINER_OF(handle, struct os_queue_handle, handle);
|
||||
os_sem_release(&queue->sem_recv);
|
||||
ret = OS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = OS_E_PARAM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *_os_ipc_queue_take(void *queue_handle, va_list arp)
|
||||
{
|
||||
return k_queue_take(queue_handle);
|
||||
}
|
||||
|
||||
void *os_queue_take(os_queue_t *queue_handle, os_time_t wait_ms)
|
||||
{
|
||||
OS_ASS_HDL(os_queue_is_valid(queue_handle), queue_handle->handle);
|
||||
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
void *ret = _os_wait_memory(_os_ipc_queue_take, &queue->handle, &queue->sem_recv, wait_ms);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *os_queue_peek_head(os_queue_t *queue_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_queue_is_valid(queue_handle), queue_handle->handle);
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
void *ret = k_queue_peek_head(&queue->handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *os_queue_peek_tail(os_queue_t *queue_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_queue_is_valid(queue_handle), queue_handle->handle);
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
void *ret = k_queue_peek_tail(&queue->handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t os_queue_get_item_size(os_queue_t *queue_handle)
|
||||
{
|
||||
struct os_queue_handle *queue = queue_handle->handle;
|
||||
size_t ret = k_queue_get_item_size(&queue->handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool os_queue_is_valid(os_queue_t *queue_handle)
|
||||
{
|
||||
if (queue_handle && queue_handle->handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct os_pipe_handle
|
||||
{
|
||||
k_pipe_t handle;
|
||||
};
|
||||
|
||||
os_state os_pipe_create(os_pipe_t *pipe_handle, size_t pipe_size)
|
||||
{
|
||||
os_state ret;
|
||||
|
||||
do
|
||||
{
|
||||
struct os_pipe_handle *pipe = os_malloc(sizeof(*pipe));
|
||||
if (pipe == NULL)
|
||||
{
|
||||
pipe_handle->handle = NULL;
|
||||
ret = OS_E_NOMEM;
|
||||
}
|
||||
|
||||
memset(pipe, 0, sizeof(*pipe));
|
||||
|
||||
if (k_pipe_create(&pipe->handle, pipe_size) != 0)
|
||||
{
|
||||
os_free(pipe);
|
||||
ret = OS_E_NOMEM;
|
||||
}
|
||||
|
||||
pipe_handle->handle = pipe;
|
||||
|
||||
ret = OS_OK;
|
||||
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_state os_pipe_delete(os_pipe_t *pipe_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_pipe_is_valid(pipe_handle), pipe_handle->handle);
|
||||
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
|
||||
k_pipe_delete(&pipe->handle);
|
||||
os_free(pipe);
|
||||
pipe_handle->handle = NULL;
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_pipe_clr(os_pipe_t *pipe_handle)
|
||||
{
|
||||
OS_ASS_HDL(os_pipe_is_valid(pipe_handle), pipe_handle->handle);
|
||||
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
k_pipe_clr(&pipe->handle);
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
void os_pipe_regist(os_pipe_t *pipe_handle, os_work_t *work_handle, int delay_ticks)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
k_pipe_regist(&pipe->handle, (k_work_t *)work_handle, delay_ticks);
|
||||
}
|
||||
|
||||
void os_pipe_unregist(os_pipe_t *pipe_handle)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
k_pipe_unregist(&pipe->handle);
|
||||
}
|
||||
|
||||
size_t os_pipe_poll_write(os_pipe_t *pipe_handle, uint8_t data)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
size_t ret = k_pipe_poll_write(&pipe->handle, data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t os_pipe_fifo_fill(os_pipe_t *pipe_handle, const void *data, size_t size)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
size_t ret = k_pipe_fifo_fill(&pipe->handle, data, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t os_pipe_poll_read(os_pipe_t *pipe_handle, uint8_t *data)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
size_t ret = k_pipe_poll_read(&pipe->handle, data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t os_pipe_fifo_read(os_pipe_t *pipe_handle, void *data, size_t size)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
size_t ret = k_pipe_fifo_read(&pipe->handle, data, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool os_pipe_is_ne(os_pipe_t *pipe_handle)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
bool ret = k_pipe_is_ne(&pipe->handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t os_pipe_get_valid_size(os_pipe_t *pipe_handle)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
size_t ret = k_pipe_get_valid_size(&pipe->handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t os_pipe_get_empty_size(os_pipe_t *pipe_handle)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
size_t ret = k_pipe_get_empty_size(&pipe->handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void os_pipe_peek_valid(os_pipe_t *pipe_handle, void **dst_base, size_t *dst_size)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
k_pipe_peek_valid(&pipe->handle, dst_base, dst_size);
|
||||
}
|
||||
|
||||
void os_pipe_peek_empty(os_pipe_t *pipe_handle, void **dst_base, size_t *dst_size)
|
||||
{
|
||||
struct os_pipe_handle *pipe = pipe_handle->handle;
|
||||
k_pipe_peek_empty(&pipe->handle, dst_base, dst_size);
|
||||
}
|
||||
|
||||
bool os_pipe_is_valid(os_pipe_t *pipe_handle)
|
||||
{
|
||||
if (pipe_handle && pipe_handle->handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
80
sal/esp32/kernel/os_mutex.c
Executable file
80
sal/esp32/kernel/os_mutex.c
Executable file
@@ -0,0 +1,80 @@
|
||||
#include "os/os.h"
|
||||
#include "os_util.h"
|
||||
#include "semphr.h"
|
||||
|
||||
os_state os_mutex_create(os_mutex_t *mutex)
|
||||
{
|
||||
OS_ASS_HDL(!os_mutex_is_valid(mutex), mutex->handle);
|
||||
|
||||
mutex->handle = xSemaphoreCreateMutex();
|
||||
if (mutex->handle == NULL)
|
||||
{
|
||||
OS_ERR("err %p\r\n", mutex->handle);
|
||||
return OS_FAIL;
|
||||
}
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_mutex_delete(os_mutex_t *mutex)
|
||||
{
|
||||
OS_ASS_HDL(os_mutex_is_valid(mutex), mutex->handle);
|
||||
|
||||
vSemaphoreDelete(mutex->handle);
|
||||
mutex->handle = NULL;
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_mutex_lock(os_mutex_t *mutex, os_time_t wait_ms)
|
||||
{
|
||||
BaseType_t ret;
|
||||
|
||||
OS_ASS_HDL(os_mutex_is_valid(mutex), mutex->handle);
|
||||
|
||||
ret = xSemaphoreTake(mutex->handle, os_calc_msec_to_ticks(wait_ms));
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_DBG("%s() fail @ %d, %u ms\n", __func__, __LINE__, wait_ms);
|
||||
return OS_FAIL;
|
||||
}
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_mutex_unlock(os_mutex_t *mutex)
|
||||
{
|
||||
BaseType_t ret;
|
||||
|
||||
OS_ASS_HDL(os_mutex_is_valid(mutex), mutex->handle);
|
||||
|
||||
ret = xSemaphoreGive(mutex->handle);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_DBG("%s() fail @ %d\n", __func__, __LINE__);
|
||||
return OS_FAIL;
|
||||
}
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_thread_handle_t os_mutex_get_holder(os_mutex_t *mutex)
|
||||
{
|
||||
if (!os_mutex_is_valid(mutex))
|
||||
{
|
||||
return OS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
return (os_thread_handle_t)xSemaphoreGetMutexHolder(mutex->handle);
|
||||
}
|
||||
|
||||
bool os_mutex_is_valid(os_mutex_t *mutex)
|
||||
{
|
||||
if (mutex && mutex->handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
105
sal/esp32/kernel/os_semaphore.c
Executable file
105
sal/esp32/kernel/os_semaphore.c
Executable file
@@ -0,0 +1,105 @@
|
||||
#include "os/os.h"
|
||||
#include "os_util.h"
|
||||
#include "semphr.h"
|
||||
|
||||
os_state os_sem_create(os_sem_t *sem, size_t init_value, size_t max_value)
|
||||
{
|
||||
OS_ASS_HDL(!os_sem_is_valid(sem), sem->handle);
|
||||
|
||||
sem->handle = xSemaphoreCreateCounting(max_value, init_value);
|
||||
if (sem->handle == NULL)
|
||||
{
|
||||
OS_ERR("err %p\r\n", sem->handle);
|
||||
return OS_FAIL;
|
||||
}
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_sem_delete(os_sem_t *sem)
|
||||
{
|
||||
OS_ASS_HDL(os_sem_is_valid(sem), sem->handle);
|
||||
|
||||
vSemaphoreDelete(sem->handle);
|
||||
sem->handle = NULL;
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_sem_take(os_sem_t *sem, os_time_t wait_ms)
|
||||
{
|
||||
BaseType_t ret;
|
||||
BaseType_t taskWoken;
|
||||
|
||||
OS_ASS_HDL(os_sem_is_valid(sem), sem->handle);
|
||||
|
||||
if (os_is_isr_context())
|
||||
{
|
||||
if (wait_ms != 0)
|
||||
{
|
||||
OS_ERR("%s() in ISR, wait %u ms\n", __func__, wait_ms);
|
||||
return OS_E_ISR;
|
||||
}
|
||||
taskWoken = pdFALSE;
|
||||
ret = xSemaphoreTakeFromISR(sem->handle, &taskWoken);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_DBG("%s() fail @ %d\n", __func__, __LINE__);
|
||||
return OS_E_TIMEOUT;
|
||||
}
|
||||
portYIELD_FROM_ISR(taskWoken);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = xSemaphoreTake(sem->handle, os_calc_msec_to_ticks(wait_ms));
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_DBG("%s() fail @ %d, %u ms\n", __func__, __LINE__, wait_ms);
|
||||
return OS_E_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_sem_release(os_sem_t *sem)
|
||||
{
|
||||
BaseType_t ret;
|
||||
BaseType_t taskWoken;
|
||||
|
||||
OS_ASS_HDL(os_sem_is_valid(sem), sem->handle);
|
||||
|
||||
if (os_is_isr_context())
|
||||
{
|
||||
taskWoken = pdFALSE;
|
||||
ret = xSemaphoreGiveFromISR(sem->handle, &taskWoken);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_DBG("%s() fail @ %d\n", __func__, __LINE__);
|
||||
return OS_FAIL;
|
||||
}
|
||||
portYIELD_FROM_ISR(taskWoken);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = xSemaphoreGive(sem->handle);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_DBG("%s() fail @ %d\n", __func__, __LINE__);
|
||||
return OS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
bool os_sem_is_valid(os_sem_t *sem)
|
||||
{
|
||||
if (sem && sem->handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
184
sal/esp32/kernel/os_service.c
Executable file
184
sal/esp32/kernel/os_service.c
Executable file
@@ -0,0 +1,184 @@
|
||||
#include "os/os.h"
|
||||
#include "os_util.h"
|
||||
#include "task.h"
|
||||
|
||||
static size_t int_flag;
|
||||
static portMUX_TYPE s_os_service = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
int os_start(void *heap_mem, size_t heap_size)
|
||||
{
|
||||
extern int os_entry(void *heap, size_t size);
|
||||
return os_entry(heap_mem, heap_size);
|
||||
}
|
||||
|
||||
void os_int_entry(void)
|
||||
{
|
||||
os_interrupt_disable();
|
||||
++int_flag;
|
||||
os_interrupt_enable();
|
||||
}
|
||||
|
||||
void os_int_exit(void)
|
||||
{
|
||||
os_interrupt_disable();
|
||||
int_flag -= !!int_flag;
|
||||
os_interrupt_enable();
|
||||
}
|
||||
|
||||
bool os_is_isr_context(void)
|
||||
{
|
||||
if (int_flag)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void os_interrupt_disable(void)
|
||||
{
|
||||
portENTER_CRITICAL(&s_os_service);
|
||||
}
|
||||
|
||||
void os_interrupt_enable(void)
|
||||
{
|
||||
portEXIT_CRITICAL(&s_os_service);
|
||||
}
|
||||
|
||||
void os_scheduler_suspend(void)
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
}
|
||||
|
||||
void os_scheduler_resume(void)
|
||||
{
|
||||
xTaskResumeAll();
|
||||
}
|
||||
|
||||
bool os_scheduler_is_running(void)
|
||||
{
|
||||
return (bool)(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
|
||||
void os_sys_print_info(void)
|
||||
{
|
||||
const size_t bytes_per_task = 40; /* see vTaskList description */
|
||||
char *task_list_buffer = malloc(uxTaskGetNumberOfTasks() * bytes_per_task);
|
||||
if (task_list_buffer == NULL)
|
||||
{
|
||||
OS_LOG(1, "failed to allocate buffer for vTaskList output\r\n");
|
||||
return;
|
||||
}
|
||||
fputs("Task Name\tStatus\tPrio\tHWM\tTask#", stdout);
|
||||
#ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
|
||||
fputs("\tAffinity", stdout);
|
||||
#endif
|
||||
fputs("\n", stdout);
|
||||
vTaskList(task_list_buffer);
|
||||
fputs(task_list_buffer, stdout);
|
||||
free(task_list_buffer);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void os_sys_print_info(void)
|
||||
{
|
||||
OS_LOG(1, "os_sys_print_info() not supported, please set configUSE_TRACE_FACILITY to 1\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
os_time_t os_get_sys_time(void)
|
||||
{
|
||||
os_time_t ticks_count = xTaskGetTickCount();
|
||||
return OS_TicksToMSecs(ticks_count);
|
||||
}
|
||||
|
||||
size_t os_get_sys_ticks(void)
|
||||
{
|
||||
return (size_t)xTaskGetTickCount();
|
||||
}
|
||||
|
||||
os_time_t os_calc_ticks_to_msec(size_t ticks)
|
||||
{
|
||||
os_time_t msec;
|
||||
|
||||
if (ticks == OS_WAIT_FOREVER)
|
||||
{
|
||||
msec = portMAX_DELAY;
|
||||
}
|
||||
else if (ticks == 0)
|
||||
{
|
||||
msec = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
msec = OS_TicksToMSecs(ticks);
|
||||
if (msec == 0)
|
||||
{
|
||||
msec = 1;
|
||||
}
|
||||
}
|
||||
return msec;
|
||||
}
|
||||
|
||||
size_t os_calc_msec_to_ticks(os_time_t msec)
|
||||
{
|
||||
size_t tick;
|
||||
|
||||
if (msec == OS_WAIT_FOREVER)
|
||||
{
|
||||
tick = portMAX_DELAY;
|
||||
}
|
||||
else if (msec == 0)
|
||||
{
|
||||
tick = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tick = OS_MSecsToTicks(msec);
|
||||
if (tick == 0)
|
||||
{
|
||||
tick = 1;
|
||||
}
|
||||
}
|
||||
return tick;
|
||||
}
|
||||
|
||||
size_t os_cpu_usage(void)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
#if (configUSE_POSIX_ERRNO == 1)
|
||||
|
||||
extern int FreeRTOS_errno;
|
||||
|
||||
int os_get_err(void)
|
||||
{
|
||||
return FreeRTOS_errno;
|
||||
}
|
||||
|
||||
void os_set_err(int err)
|
||||
{
|
||||
FreeRTOS_errno = err;
|
||||
}
|
||||
|
||||
#elif (configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0)
|
||||
|
||||
#define OS_ERRNO_LOCATION_IDX 0
|
||||
|
||||
int os_get_err(void)
|
||||
{
|
||||
return (int)pvTaskGetThreadLocalStoragePointer(NULL, OS_ERRNO_LOCATION_IDX);
|
||||
}
|
||||
|
||||
void os_set_err(int err)
|
||||
{
|
||||
vTaskSetThreadLocalStoragePointer(NULL, OS_ERRNO_LOCATION_IDX, (void *)err);
|
||||
}
|
||||
|
||||
#endif
|
||||
277
sal/esp32/kernel/os_thread.c
Executable file
277
sal/esp32/kernel/os_thread.c
Executable file
@@ -0,0 +1,277 @@
|
||||
#include "os/os.h"
|
||||
#include "os_util.h"
|
||||
#include "task.h"
|
||||
#include "list/slist.h"
|
||||
|
||||
/* Macro used to convert os_priority to the kernel's real priority */
|
||||
#define OS_KERNEL_PRIO(prio) (prio)
|
||||
|
||||
static slist_t s_thread_list;
|
||||
|
||||
static void _os_delete(struct os_thread_handle *thread_handle)
|
||||
{
|
||||
os_scheduler_suspend();
|
||||
|
||||
slist_remove(&s_thread_list, &thread_handle->node);
|
||||
thread_handle->thread->handle = NULL;
|
||||
if (thread_handle->flag_free)
|
||||
{
|
||||
os_free(thread_handle->thread);
|
||||
}
|
||||
os_free(thread_handle);
|
||||
|
||||
os_scheduler_resume();
|
||||
}
|
||||
|
||||
static void _os_thread_start(void *arg)
|
||||
{
|
||||
struct os_thread_handle *thread_handle = arg;
|
||||
thread_handle->entry(thread_handle->arg);
|
||||
_os_delete(thread_handle);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
os_state os_thread_init(os_thread_t *thread,
|
||||
const char *name,
|
||||
os_thread_entry_t entry,
|
||||
void *arg,
|
||||
void *stack_base,
|
||||
size_t stack_size,
|
||||
os_priority priority)
|
||||
{
|
||||
#if (configSUPPORT_STATIC_ALLOCATION == 1)
|
||||
|
||||
OS_ASS_HDL(!os_thread_is_valid(thread), thread->handle);
|
||||
|
||||
if (stack_size <= sizeof(struct os_thread_handle) + sizeof(StaticTask_t))
|
||||
{
|
||||
OS_ERR("err size: %d <= %d\r\n", stack_size, sizeof(struct os_thread_handle) + sizeof(StaticTask_t));
|
||||
return OS_FAIL;
|
||||
}
|
||||
|
||||
struct os_thread_handle *thread_handle = stack_base;
|
||||
StaticTask_t *pxTaskBuffer = (StaticTask_t *)&thread_handle[1];
|
||||
StackType_t *puxStackBuffer = (StackType_t *)&pxTaskBuffer[1];
|
||||
|
||||
thread_handle->thread = thread;
|
||||
thread_handle->entry = entry;
|
||||
thread_handle->arg = arg;
|
||||
thread_handle->flag_free = 0;
|
||||
thread_handle->pxCreatedTask = xTaskCreateStatic(_os_thread_start,
|
||||
name,
|
||||
stack_size / sizeof(StackType_t),
|
||||
thread_handle,
|
||||
OS_KERNEL_PRIO(priority),
|
||||
puxStackBuffer,
|
||||
pxTaskBuffer);
|
||||
thread->handle = thread_handle;
|
||||
return OS_OK;
|
||||
|
||||
#else
|
||||
|
||||
OS_ERR("err configSUPPORT_STATIC_ALLOCATION != 1\r\n");
|
||||
return OS_FAIL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
os_state os_thread_create(os_thread_t *thread,
|
||||
const char *name,
|
||||
os_thread_entry_t entry,
|
||||
void *arg,
|
||||
size_t stack_size,
|
||||
os_priority priority)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (thread)
|
||||
{
|
||||
OS_ASS_HDL(!os_thread_is_valid(thread), thread->handle);
|
||||
}
|
||||
|
||||
struct os_thread_handle *thread_handle = os_malloc(sizeof(struct os_thread_handle));
|
||||
if (thread_handle == NULL)
|
||||
{
|
||||
return OS_E_NOMEM;
|
||||
}
|
||||
|
||||
if (thread == NULL)
|
||||
{
|
||||
thread = os_malloc(sizeof(os_thread_t));
|
||||
if (thread == NULL)
|
||||
{
|
||||
os_free(thread_handle);
|
||||
return OS_E_NOMEM;
|
||||
}
|
||||
memset(thread, 0, sizeof(os_thread_t));
|
||||
thread_handle->flag_free = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
thread_handle->flag_free = 0;
|
||||
}
|
||||
thread->handle = thread_handle;
|
||||
thread_handle->work_q_list = NULL;
|
||||
thread_handle->thread = thread;
|
||||
thread_handle->entry = entry;
|
||||
thread_handle->arg = arg;
|
||||
slist_init_node(&thread_handle->node);
|
||||
|
||||
os_scheduler_suspend();
|
||||
slist_insert_tail(&s_thread_list, &thread_handle->node);
|
||||
os_scheduler_resume();
|
||||
|
||||
ret = xTaskCreatePinnedToCore(_os_thread_start,
|
||||
name,
|
||||
stack_size / sizeof(StackType_t),
|
||||
thread_handle,
|
||||
OS_KERNEL_PRIO(priority),
|
||||
&thread_handle->pxCreatedTask,
|
||||
0);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_ERR("err %d\r\n", ret);
|
||||
|
||||
os_scheduler_suspend();
|
||||
slist_remove(&s_thread_list, &thread_handle->node);
|
||||
os_scheduler_resume();
|
||||
|
||||
if (thread_handle->flag_free == 0)
|
||||
{
|
||||
thread->handle = NULL;
|
||||
}
|
||||
if (thread_handle->thread)
|
||||
{
|
||||
os_free(thread_handle->thread);
|
||||
}
|
||||
os_free(thread_handle);
|
||||
return OS_FAIL;
|
||||
}
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_thread_delete(os_thread_t *thread)
|
||||
{
|
||||
if (thread == NULL) /* delete self */
|
||||
{
|
||||
struct os_thread_handle *thread_handle = os_thread_get_self();
|
||||
_os_delete(thread_handle);
|
||||
vTaskDelete(NULL);
|
||||
return OS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
OS_ASS_HDL(os_thread_is_valid(thread), thread->handle);
|
||||
struct os_thread_handle *thread_handle = thread->handle;
|
||||
vTaskDelete(thread_handle->pxCreatedTask);
|
||||
_os_delete(thread_handle);
|
||||
return OS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void os_thread_sleep(os_time_t msec)
|
||||
{
|
||||
vTaskDelay((TickType_t)os_calc_msec_to_ticks(msec));
|
||||
}
|
||||
|
||||
void os_thread_yield(void)
|
||||
{
|
||||
taskYIELD();
|
||||
}
|
||||
|
||||
void os_thread_suspend(os_thread_t *thread)
|
||||
{
|
||||
if (thread)
|
||||
{
|
||||
OS_ASS_HDL(os_thread_is_valid(thread), thread->handle);
|
||||
struct os_thread_handle *thread_handle = thread->handle;
|
||||
vTaskSuspend(thread_handle->pxCreatedTask);
|
||||
}
|
||||
else
|
||||
{
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void os_thread_resume(os_thread_t *thread)
|
||||
{
|
||||
OS_ASS_HDL(os_thread_is_valid(thread), thread->handle);
|
||||
struct os_thread_handle *thread_handle = thread->handle;
|
||||
vTaskResume(thread_handle->pxCreatedTask);
|
||||
}
|
||||
|
||||
os_thread_handle_t os_thread_get_self(void)
|
||||
{
|
||||
os_thread_handle_t ret = NULL;
|
||||
|
||||
os_scheduler_suspend();
|
||||
TaskHandle_t xTask = xTaskGetCurrentTaskHandle();
|
||||
struct os_thread_handle *thread_handle;
|
||||
struct os_thread_handle *prev_handle = NULL;
|
||||
int cnt = 0;
|
||||
SLIST_FOR_EACH_CONTAINER(&s_thread_list, thread_handle, node)
|
||||
{
|
||||
if (thread_handle->pxCreatedTask == xTask)
|
||||
{
|
||||
ret = thread_handle->thread->handle;
|
||||
break;
|
||||
}
|
||||
prev_handle = thread_handle;
|
||||
cnt++;
|
||||
}
|
||||
if (cnt > 5)
|
||||
{
|
||||
slist_remove_next(&s_thread_list, &prev_handle->node, &thread_handle->node);
|
||||
slist_insert_font(&s_thread_list, &thread_handle->node);
|
||||
}
|
||||
os_scheduler_resume();
|
||||
SYS_ASSERT(ret, "xTask: %p", xTask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *os_thread_get_name(os_thread_t *thread)
|
||||
{
|
||||
struct os_thread_handle *thread_handle = thread->handle;
|
||||
return pcTaskGetName(thread_handle->pxCreatedTask);
|
||||
}
|
||||
|
||||
size_t os_thread_stack_min(os_thread_t *thread)
|
||||
{
|
||||
#if INCLUDE_uxTaskGetStackHighWaterMark
|
||||
TaskHandle_t xTask;
|
||||
|
||||
if (thread != NULL)
|
||||
{
|
||||
if (os_thread_is_valid(thread))
|
||||
{
|
||||
struct os_thread_handle *thread_handle = thread->handle;
|
||||
xTask = thread_handle->pxCreatedTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xTask = NULL;
|
||||
}
|
||||
|
||||
extern UBaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t xTask);
|
||||
return (uxTaskGetStackHighWaterMark(xTask) * sizeof(StackType_t));
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool os_thread_is_valid(os_thread_t *thread)
|
||||
{
|
||||
if (thread && thread->handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
219
sal/esp32/kernel/os_timer.c
Executable file
219
sal/esp32/kernel/os_timer.c
Executable file
@@ -0,0 +1,219 @@
|
||||
#include "os/os.h"
|
||||
#include "os_util.h"
|
||||
#include "timers.h"
|
||||
|
||||
/* TODO: what block time should be used ? */
|
||||
#define OS_TIMER_WAIT_FOREVER portMAX_DELAY
|
||||
#define OS_TIMER_WAIT_NONE 0
|
||||
|
||||
/* Timer private data definition */
|
||||
typedef struct OS_TimerPriv
|
||||
{
|
||||
TimerHandle_t handle; /* Timer handle */
|
||||
os_timer_cb_fn callback; /* Timer expire callback function */
|
||||
void *argument; /* Argument of timer expire callback function */
|
||||
} OS_TimerPriv_t;
|
||||
|
||||
static void _os_timer_cb(TimerHandle_t xTimer)
|
||||
{
|
||||
OS_TimerPriv_t *priv;
|
||||
|
||||
priv = pvTimerGetTimerID(xTimer);
|
||||
if (priv && priv->callback)
|
||||
{
|
||||
priv->callback(priv->argument);
|
||||
}
|
||||
else
|
||||
{
|
||||
OS_WRN("Invalid timer callback\n");
|
||||
}
|
||||
}
|
||||
|
||||
os_state os_timer_create(os_timer_t *timer, os_timer_cb_fn cb, void *arg)
|
||||
{
|
||||
OS_TimerPriv_t *priv;
|
||||
|
||||
OS_ASS_HDL(!os_timer_is_valid(timer), timer->handle);
|
||||
|
||||
priv = os_malloc(sizeof(OS_TimerPriv_t));
|
||||
if (priv == NULL)
|
||||
{
|
||||
return OS_E_NOMEM;
|
||||
}
|
||||
|
||||
priv->callback = cb;
|
||||
priv->argument = arg;
|
||||
priv->handle = xTimerCreate("",
|
||||
os_calc_msec_to_ticks(OS_WAIT_FOREVER),
|
||||
pdFALSE,
|
||||
priv,
|
||||
_os_timer_cb);
|
||||
if (priv->handle == NULL)
|
||||
{
|
||||
OS_ERR("err %p\r\n", priv->handle);
|
||||
os_free(priv);
|
||||
return OS_FAIL;
|
||||
}
|
||||
timer->handle = priv;
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
static TimerHandle_t _os_timer_get_handle(os_timer_t *timer)
|
||||
{
|
||||
OS_TimerPriv_t *priv = timer->handle;
|
||||
return priv->handle;
|
||||
}
|
||||
|
||||
os_state os_timer_delete(os_timer_t *timer)
|
||||
{
|
||||
TimerHandle_t handle;
|
||||
int ret;
|
||||
|
||||
OS_ASS_HDL(os_timer_is_valid(timer), timer->handle);
|
||||
|
||||
handle = _os_timer_get_handle(timer);
|
||||
ret = xTimerDelete(handle, OS_TIMER_WAIT_FOREVER);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_ERR("err %d\r\n", ret);
|
||||
return OS_FAIL;
|
||||
}
|
||||
|
||||
OS_TimerPriv_t *priv = timer->handle;
|
||||
timer->handle = NULL;
|
||||
|
||||
os_free(priv);
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_timer_start(os_timer_t *timer)
|
||||
{
|
||||
TimerHandle_t handle;
|
||||
int ret;
|
||||
BaseType_t taskWoken;
|
||||
|
||||
OS_ASS_HDL(os_timer_is_valid(timer), timer->handle);
|
||||
|
||||
handle = _os_timer_get_handle(timer);
|
||||
|
||||
if (os_is_isr_context())
|
||||
{
|
||||
taskWoken = pdFALSE;
|
||||
ret = xTimerStartFromISR(handle, &taskWoken);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_ERR("err %d\r\n", ret);
|
||||
return OS_FAIL;
|
||||
}
|
||||
portYIELD_FROM_ISR(taskWoken);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = xTimerStart(handle, OS_TIMER_WAIT_NONE);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_ERR("err %d\r\n", ret);
|
||||
return OS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_timer_set_period(os_timer_t *timer, os_timer_type_t type, os_time_t period_ms)
|
||||
{
|
||||
TimerHandle_t handle;
|
||||
TickType_t ticks;
|
||||
int ret;
|
||||
|
||||
OS_ASS_HDL(os_timer_is_valid(timer), timer->handle);
|
||||
|
||||
handle = _os_timer_get_handle(timer);
|
||||
ticks = os_calc_msec_to_ticks(period_ms);
|
||||
|
||||
if (os_is_isr_context())
|
||||
{
|
||||
BaseType_t taskWoken = pdFALSE;
|
||||
ret = xTimerChangePeriodFromISR(handle, ticks, &taskWoken);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_ERR("err %d\r\n", ret);
|
||||
return OS_FAIL;
|
||||
}
|
||||
portYIELD_FROM_ISR(taskWoken);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = xTimerChangePeriod(handle, ticks, OS_TIMER_WAIT_NONE);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_ERR("err %d\r\n", ret);
|
||||
return OS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
vTimerSetReloadMode(handle, type == OS_TIMER_PERIODIC ? pdTRUE : pdFALSE);
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_state os_timer_stop(os_timer_t *timer)
|
||||
{
|
||||
TimerHandle_t handle;
|
||||
int ret;
|
||||
BaseType_t taskWoken;
|
||||
|
||||
OS_ASS_HDL(os_timer_is_valid(timer), timer->handle);
|
||||
|
||||
handle = _os_timer_get_handle(timer);
|
||||
|
||||
if (os_is_isr_context())
|
||||
{
|
||||
taskWoken = pdFALSE;
|
||||
ret = xTimerStopFromISR(handle, &taskWoken);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_ERR("err %d\r\n", ret);
|
||||
return OS_FAIL;
|
||||
}
|
||||
portYIELD_FROM_ISR(taskWoken);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = xTimerStop(handle, OS_TIMER_WAIT_FOREVER);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_ERR("err %d\r\n", ret);
|
||||
return OS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
bool os_timer_is_pending(os_timer_t *timer)
|
||||
{
|
||||
TimerHandle_t handle;
|
||||
|
||||
if (!os_timer_is_valid(timer))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
handle = _os_timer_get_handle(timer);
|
||||
|
||||
return (xTimerIsTimerActive(handle) != pdFALSE);
|
||||
}
|
||||
|
||||
bool os_timer_is_valid(os_timer_t *timer)
|
||||
{
|
||||
if (timer && timer->handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
33
sal/esp32/kernel/os_util.h
Executable file
33
sal/esp32/kernel/os_util.h
Executable file
@@ -0,0 +1,33 @@
|
||||
#ifndef __OS_UTIL_H__
|
||||
#define __OS_UTIL_H__
|
||||
|
||||
#include "list/slist.h"
|
||||
#include "os/os_common.h"
|
||||
#include "os_debug.h"
|
||||
|
||||
#include "k_kit.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#define OS_TICK_RATE configTICK_RATE_HZ
|
||||
|
||||
typedef struct os_work_q_list
|
||||
{
|
||||
k_work_q_t work_q_handle;
|
||||
os_sem_t sem_handle;
|
||||
os_thread_t thread;
|
||||
} os_work_q_list_t;
|
||||
|
||||
struct os_thread_handle
|
||||
{
|
||||
slist_node_t node;
|
||||
TaskHandle_t pxCreatedTask;
|
||||
os_thread_t *thread;
|
||||
os_work_q_list_t *work_q_list;
|
||||
os_thread_entry_t entry;
|
||||
void *arg;
|
||||
uint8_t flag_free;
|
||||
};
|
||||
|
||||
#endif /* __OS_UTIL_H__ */
|
||||
72
sal/esp32/os_entry.c
Normal file
72
sal/esp32/os_entry.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "os_entry.h"
|
||||
|
||||
#undef SYS_LOG_DOMAIN
|
||||
#define SYS_LOG_DOMAIN "OS"
|
||||
#include "kernel/os_util.h"
|
||||
|
||||
#ifndef CONFIG_OS_THREAD_MAIN_STACK_SIZE
|
||||
#define CONFIG_OS_THREAD_MAIN_STACK_SIZE 0x1C00
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_OS_THREAD_MAIN_PRIORITY
|
||||
#define CONFIG_OS_THREAD_MAIN_PRIORITY OS_PRIORITY_NORMAL
|
||||
#endif
|
||||
|
||||
static unsigned s_int_nest;
|
||||
|
||||
static unsigned _port_interrupt_save(void)
|
||||
{
|
||||
if (s_int_nest == 0)
|
||||
{
|
||||
os_interrupt_disable();
|
||||
}
|
||||
return s_int_nest++;
|
||||
}
|
||||
|
||||
static void _port_interrupt_restore(unsigned nest)
|
||||
{
|
||||
s_int_nest = nest;
|
||||
if (nest == 0)
|
||||
{
|
||||
os_interrupt_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static k_work_q_t *_port_get_work_q_hdl(void)
|
||||
{
|
||||
struct os_thread_handle *thread_handle = os_thread_get_self();
|
||||
os_work_q_list_t *work_q_list = thread_handle->work_q_list;
|
||||
return &work_q_list->work_q_handle;
|
||||
}
|
||||
|
||||
static void _port_thread_sleep(k_tick_t sleep_ticks)
|
||||
{
|
||||
vTaskDelay(sleep_ticks);
|
||||
}
|
||||
|
||||
int os_entry(os_work_fn work_route)
|
||||
{
|
||||
static k_init_t const init_struct = {
|
||||
.malloc = os_malloc,
|
||||
.free = os_free,
|
||||
.get_sys_ticks = os_get_sys_ticks,
|
||||
.interrupt_save = _port_interrupt_save,
|
||||
.interrupt_restore = _port_interrupt_restore,
|
||||
.scheduler_disable = os_scheduler_suspend,
|
||||
.scheduler_enable = os_scheduler_resume,
|
||||
.get_work_q_hdl = _port_get_work_q_hdl,
|
||||
.thread_sleep = _port_thread_sleep,
|
||||
};
|
||||
k_init(&init_struct);
|
||||
|
||||
os_work_q_create(default_os_work_q_hdl,
|
||||
"app-work_q",
|
||||
CONFIG_OS_THREAD_MAIN_STACK_SIZE,
|
||||
CONFIG_OS_THREAD_MAIN_PRIORITY);
|
||||
|
||||
static os_work_t _work_hdl_init;
|
||||
os_work_create(&_work_hdl_init, "work-main", work_route, NULL, 3);
|
||||
os_work_submit(default_os_work_q_hdl, &_work_hdl_init, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
27
sal/esp32/soc_shell.c
Normal file
27
sal/esp32/soc_shell.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "shell/sh.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#define CONFIG_SYS_LOG_DUMP_ON 1
|
||||
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
|
||||
#define SYS_LOG_DOMAIN "SOC"
|
||||
#include "sys_log.h"
|
||||
|
||||
#include "soc_shell_base.c"
|
||||
#include "soc_shell_nvs.c"
|
||||
|
||||
SH_DEF_SUB_CMD(
|
||||
sub_soc,
|
||||
SH_SETUP_CMD("base", "Basic information of the system", NULL, sub_soc_base), //
|
||||
SH_SETUP_CMD("nvs", "Partition for operating nvs", NULL, sub_soc_nvs), //
|
||||
);
|
||||
|
||||
SH_DEF_CMD(
|
||||
_register_cmd_soc,
|
||||
SH_SETUP_CMD("soc", "System on chip", NULL, sub_soc), );
|
||||
|
||||
void soc_shell_register(void)
|
||||
{
|
||||
sh_register_cmd(&_register_cmd_soc);
|
||||
}
|
||||
141
sal/esp32/soc_shell_base.c
Normal file
141
sal/esp32/soc_shell_base.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @file soc_shell_base.c
|
||||
* @author LokLiang
|
||||
* @brief 仅被 soc_shell.c 所包含,完成子命令列表及功能
|
||||
* @version 0.1
|
||||
* @date 2023-09-15
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SOC_SHELL_BASE_C__
|
||||
#define __SOC_SHELL_BASE_C__
|
||||
|
||||
#include "shell/sh.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "spi_flash_mmap.h"
|
||||
#include "esp_flash.h"
|
||||
#include "esp_chip_info.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Unsigned integers. */
|
||||
#define PRIu8 "u"
|
||||
#define PRIu16 "u"
|
||||
#define PRIu32 "u"
|
||||
#define PRIu64 __PRI64_PREFIX "u"
|
||||
|
||||
SH_CMD_FN(_base_free);
|
||||
SH_CMD_FN(_base_heap);
|
||||
SH_CMD_FN(_base_version);
|
||||
SH_CMD_FN(_base_tasks);
|
||||
SH_CMD_FN(_base_restart);
|
||||
|
||||
SH_DEF_SUB_CMD(
|
||||
sub_soc_base,
|
||||
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
|
||||
SH_SETUP_CMD("tasks", "Get information about running tasks", _base_tasks, NULL), //
|
||||
#endif
|
||||
SH_SETUP_CMD("free", "Get the current size of free heap memory", _base_free, NULL), //
|
||||
SH_SETUP_CMD("heap", "Get minimum size of free heap memory that was available during program execution", _base_heap, NULL), //
|
||||
SH_SETUP_CMD("version", "Get version of chip and SDK", _base_version, NULL), //
|
||||
SH_SETUP_CMD("restart", "Software reset of the chip", _base_restart, NULL), //
|
||||
);
|
||||
|
||||
SH_CMD_FN(_base_free)
|
||||
{
|
||||
sh_echo(sh_hdl, "当前堆内存空闲大小: %d bytes\r\n", esp_get_free_heap_size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
SH_CMD_FN(_base_heap)
|
||||
{
|
||||
sh_echo(sh_hdl, "当前堆内存最少剩余: %d bytes\r\n", heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT));
|
||||
return 0;
|
||||
}
|
||||
|
||||
SH_CMD_FN(_base_version)
|
||||
{
|
||||
const char *model;
|
||||
esp_chip_info_t info;
|
||||
uint32_t flash_size;
|
||||
esp_chip_info(&info);
|
||||
|
||||
switch (info.model)
|
||||
{
|
||||
case CHIP_ESP32:
|
||||
model = "ESP32";
|
||||
break;
|
||||
case CHIP_ESP32S2:
|
||||
model = "ESP32-S2";
|
||||
break;
|
||||
case CHIP_ESP32S3:
|
||||
model = "ESP32-S3";
|
||||
break;
|
||||
case CHIP_ESP32C3:
|
||||
model = "ESP32-C3";
|
||||
break;
|
||||
case CHIP_ESP32H2:
|
||||
model = "ESP32-H2";
|
||||
break;
|
||||
case CHIP_ESP32C2:
|
||||
model = "ESP32-C2";
|
||||
break;
|
||||
default:
|
||||
model = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
if (esp_flash_get_size(NULL, &flash_size) != ESP_OK)
|
||||
{
|
||||
sh_echo(sh_hdl, "Get flash size failed");
|
||||
return 1;
|
||||
}
|
||||
sh_echo(sh_hdl, "IDF Version:%s\r\n", esp_get_idf_version());
|
||||
sh_echo(sh_hdl, "Chip info:\r\n");
|
||||
sh_echo(sh_hdl, "\tmodel:%s\r\n", model);
|
||||
sh_echo(sh_hdl, "\tcores:%d\r\n", info.cores);
|
||||
sh_echo(sh_hdl, "\tfeature:%s%s%s%s%" PRIu32 "%s\r\n",
|
||||
info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "",
|
||||
info.features & CHIP_FEATURE_BLE ? "/BLE" : "",
|
||||
info.features & CHIP_FEATURE_BT ? "/BT" : "",
|
||||
info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:",
|
||||
flash_size / (1024 * 1024), " MB");
|
||||
sh_echo(sh_hdl, "\trevision number:%d\r\n", info.revision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SH_CMD_FN(_base_tasks)
|
||||
{
|
||||
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
|
||||
const size_t bytes_per_task = 40; /* see vTaskList description */
|
||||
char *task_list_buffer = malloc(uxTaskGetNumberOfTasks() * bytes_per_task);
|
||||
if (task_list_buffer == NULL)
|
||||
{
|
||||
sh_echo(sh_hdl, "failed to allocate buffer for vTaskList output\r\n");
|
||||
return -1;
|
||||
}
|
||||
sh_echo(sh_hdl, "Task Name\tStatus\tPrio\tHWM\tTask#", stdout);
|
||||
#ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
|
||||
sh_echo(sh_hdl, "\tAffinity", stdout);
|
||||
#endif
|
||||
sh_echo(sh_hdl, "\r\n", stdout);
|
||||
vTaskList(task_list_buffer);
|
||||
sh_echo(sh_hdl, task_list_buffer, stdout);
|
||||
|
||||
sh_echo(sh_hdl, "Task_Name\tRun_Cnt\t\tUsage_Rate\r\n", stdout);
|
||||
vTaskGetRunTimeStats(task_list_buffer);
|
||||
sh_echo(sh_hdl, task_list_buffer, stdout);
|
||||
|
||||
free(task_list_buffer);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
SH_CMD_FN(_base_restart)
|
||||
{
|
||||
esp_restart();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
117
sal/esp32/soc_shell_nvs.c
Normal file
117
sal/esp32/soc_shell_nvs.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* @file soc_shell_nvs.c
|
||||
* @author LokLiang
|
||||
* @brief 仅被 soc_shell.c 所包含,完成子命令列表及功能
|
||||
* @version 0.1
|
||||
* @date 2023-09-15
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SOC_SHELL_NVS_C__
|
||||
#define __SOC_SHELL_NVS_C__
|
||||
|
||||
#include "shell/sh.h"
|
||||
#include "shell/sh_vset.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "os/os.h"
|
||||
|
||||
static char s_nvs_str_buf[0x40];
|
||||
|
||||
static int _value_set_str(const char *argv[]) { return SET_VAR(&s_nvs_str_buf, 0, 0); }
|
||||
|
||||
SH_CMD_FN(_nvs_dump);
|
||||
SH_CMD_FN(_nvs_erase);
|
||||
|
||||
SH_DEF_SUB_CMD(
|
||||
sub_soc_nvs,
|
||||
SH_SETUP_CMD("dump", "Dump blob value for given key <namespace> <key>", _nvs_dump, NULL), //
|
||||
SH_SETUP_CMD("erase", "Erase the default NVS partition", _nvs_erase, NULL), //
|
||||
);
|
||||
|
||||
SH_CMD_FN(_nvs_dump)
|
||||
{
|
||||
const char *argv_r[2] = {"", ""};
|
||||
size_t required_size;
|
||||
char namespace_buf[sizeof(s_nvs_str_buf)];
|
||||
char key_buf[sizeof(s_nvs_str_buf)];
|
||||
int err = 0;
|
||||
|
||||
argv_r[0] = argv[0];
|
||||
err = err ? err : _value_set_str(argv_r);
|
||||
if (err == 0)
|
||||
strcpy(namespace_buf, s_nvs_str_buf);
|
||||
|
||||
argv_r[0] = argv[1];
|
||||
err = err ? err : _value_set_str(argv_r);
|
||||
if (err == 0)
|
||||
strcpy(key_buf, s_nvs_str_buf);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
nvs_handle nvs_hdl;
|
||||
if (nvs_open(namespace_buf, NVS_READONLY, &nvs_hdl) == ESP_OK)
|
||||
{
|
||||
err = nvs_get_blob(nvs_hdl, key_buf, NULL, &required_size);
|
||||
if (err == 0)
|
||||
{
|
||||
if (required_size)
|
||||
{
|
||||
void *data = os_malloc(required_size);
|
||||
if (data)
|
||||
{
|
||||
err = nvs_get_blob(nvs_hdl, key_buf, data, &required_size);
|
||||
if (err == 0)
|
||||
{
|
||||
SYS_LOG_DUMP(data, required_size, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
sh_echo(sh_hdl, "Can not get blob key: '%s'\r\n", key_buf);
|
||||
}
|
||||
os_free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
sh_echo(sh_hdl, "os_malloc() fail\r\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sh_echo(sh_hdl, "Blob data empty\r\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sh_echo(sh_hdl, "Can not get blob key: '%s'\r\n", key_buf);
|
||||
}
|
||||
nvs_close(nvs_hdl);
|
||||
}
|
||||
else
|
||||
{
|
||||
sh_echo(sh_hdl, "Can not open name space: '%s'\r\n", namespace_buf);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
SH_CMD_FN(_nvs_erase)
|
||||
{
|
||||
sh_echo(sh_hdl, "正在擦除 NVS 分区 ...\r\n");
|
||||
esp_err_t err = nvs_flash_erase();
|
||||
if (err == ESP_OK)
|
||||
{
|
||||
sh_echo(sh_hdl, "操作成功,重启系统 ...\r\n");
|
||||
esp_restart();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sh_echo(sh_hdl, "操作异常: err = %d\r\n", err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user