first commit
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
#include "OsSample.h"
|
||||
|
||||
// --- 1. vTaskDelay ---
|
||||
void vTaskDelay(const TickType_t xTicksToDelay) {
|
||||
#ifdef _WIN32
|
||||
Sleep(xTicksToDelay);
|
||||
#elif defined(__linux__)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = xTicksToDelay / 1000;
|
||||
ts.tv_nsec = (xTicksToDelay % 1000) * 1000000L;
|
||||
nanosleep(&ts, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
// --- 2. xTaskCreate ---
|
||||
// 内部包装函数:为了适配系统线程接口并防止任务返回导致进程奔溃
|
||||
#ifdef _WIN32
|
||||
DWORD WINAPI prvTaskWrapper(LPVOID lpParam) {
|
||||
TaskFunction_t pxTask = (TaskFunction_t)(((void**)lpParam)[0]);
|
||||
void* pvParams = ((void**)lpParam)[1];
|
||||
free(lpParam);
|
||||
pxTask(pvParams);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
void* prvTaskWrapper(void* lpParam) {
|
||||
TaskFunction_t pxTask = (TaskFunction_t)(((void**)lpParam)[0]);
|
||||
void* pvParams = ((void**)lpParam)[1];
|
||||
free(lpParam);
|
||||
pxTask(pvParams);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask) {
|
||||
// 准备参数包
|
||||
void** args = malloc(sizeof(void*) * 2);
|
||||
args[0] = (void*)pvTaskCode;
|
||||
args[1] = pvParameters;
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE hThread = CreateThread(NULL, usStackDepth, prvTaskWrapper, args, 0, NULL);
|
||||
if (pxCreatedTask) *pxCreatedTask = (TaskHandle_t)hThread;
|
||||
return (hThread != NULL) ? pdPASS : pdFAIL;
|
||||
#elif defined(__linux__)
|
||||
pthread_t threadId;
|
||||
int res = pthread_create(&threadId, NULL, prvTaskWrapper, args);
|
||||
if (pxCreatedTask) *pxCreatedTask = (TaskHandle_t)threadId;
|
||||
return (res == 0) ? pdPASS : pdFAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// --- 3. xQueueCreate (简易内存模拟) ---
|
||||
// 注意:实际生产环境建议使用互斥锁保护。这里仅展示逻辑框架。
|
||||
typedef struct {
|
||||
uint8_t* storage;
|
||||
uint32_t length;
|
||||
uint32_t item_size;
|
||||
uint32_t write_idx; // 写指针
|
||||
uint32_t read_idx; // 读指针
|
||||
uint32_t count; // 当前元素数量
|
||||
#ifdef _WIN32
|
||||
HANDLE mutex; // 保护结构体内部数据
|
||||
HANDLE sem_fill; // 计数信号量:当前有多少数据可读
|
||||
#else
|
||||
pthread_mutex_t mutex;
|
||||
sem_t sem_fill;
|
||||
#endif
|
||||
} SimulatedQueue;
|
||||
|
||||
// --- xQueueCreate ---
|
||||
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize) {
|
||||
SimulatedQueue* q = (SimulatedQueue*)malloc(sizeof(SimulatedQueue));
|
||||
if (!q) return NULL;
|
||||
|
||||
q->storage = (uint8_t*)malloc(uxQueueLength * uxItemSize);
|
||||
q->length = uxQueueLength;
|
||||
q->item_size = uxItemSize;
|
||||
q->write_idx = 0;
|
||||
q->read_idx = 0;
|
||||
q->count = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
q->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
q->sem_fill = CreateSemaphore(NULL, 0, uxQueueLength, NULL);
|
||||
#else
|
||||
pthread_mutex_init(&q->mutex, NULL);
|
||||
sem_init(&q->sem_fill, 0, 0);
|
||||
#endif
|
||||
return (QueueHandle_t)q;
|
||||
}
|
||||
|
||||
// --- xQueueSend ---
|
||||
BaseType_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait) {
|
||||
SimulatedQueue* q = (SimulatedQueue*)xQueue;
|
||||
if (!q) return pdFAIL;
|
||||
|
||||
// 1. 进入临界区保护数据
|
||||
#ifdef _WIN32
|
||||
WaitForSingleObject(q->mutex, INFINITE);
|
||||
#else
|
||||
pthread_mutex_lock(&q->mutex);
|
||||
#endif
|
||||
|
||||
// 检查队列是否已满
|
||||
if (q->count >= q->length) {
|
||||
#ifdef _WIN32
|
||||
ReleaseMutex(q->mutex);
|
||||
#else
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
#endif
|
||||
return errQUEUE_FULL;
|
||||
}
|
||||
|
||||
// 2. 拷贝数据到环形缓冲区
|
||||
memcpy(q->storage + (q->write_idx * q->item_size), pvItemToQueue, q->item_size);
|
||||
q->write_idx = (q->write_idx + 1) % q->length;
|
||||
q->count++;
|
||||
|
||||
// 3. 释放信号量通知接收方,退出临界区
|
||||
#ifdef _WIN32
|
||||
ReleaseSemaphore(q->sem_fill, 1, NULL);
|
||||
ReleaseMutex(q->mutex);
|
||||
#else
|
||||
sem_post(&q->sem_fill);
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
#endif
|
||||
|
||||
return pdPASS;
|
||||
}
|
||||
|
||||
// --- xQueueReceive ---
|
||||
BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait) {
|
||||
SimulatedQueue* q = (SimulatedQueue*)xQueue;
|
||||
if (!q) return pdFAIL;
|
||||
|
||||
// 1. 等待信号量(是否有数据可读)
|
||||
#ifdef _WIN32
|
||||
DWORD res = WaitForSingleObject(q->sem_fill, (xTicksToWait == portMAX_DELAY) ? INFINITE : xTicksToWait);
|
||||
if (res != WAIT_OBJECT_0) return pdFAIL;
|
||||
WaitForSingleObject(q->mutex, INFINITE); // 进入临界区
|
||||
#else
|
||||
// Linux 简化处理,直接阻塞等
|
||||
sem_wait(&q->sem_fill);
|
||||
pthread_mutex_lock(&q->mutex);
|
||||
#endif
|
||||
|
||||
// 2. 拷贝数据
|
||||
memcpy(pvBuffer, q->storage + (q->read_idx * q->item_size), q->item_size);
|
||||
q->read_idx = (q->read_idx + 1) % q->length;
|
||||
q->count--;
|
||||
|
||||
// 3. 退出临界区
|
||||
#ifdef _WIN32
|
||||
ReleaseMutex(q->mutex);
|
||||
#else
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
#endif
|
||||
|
||||
return pdPASS;
|
||||
}
|
||||
|
||||
// 在 OsSample.c 中实现
|
||||
void vTaskStartScheduler(void) {
|
||||
#ifdef _WIN32
|
||||
// Windows: 挂起主线程,直到进程结束
|
||||
Sleep(INFINITE);
|
||||
#elif defined(__linux__)
|
||||
// Linux: 使用 pause() 挂起,等待信号,或者用死循环
|
||||
while(1) {
|
||||
pause();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user