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
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef OS_SAMPLE_H
|
||||
#define OS_SAMPLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN // 阻止 windows.h 包含旧版 winsock.h
|
||||
#endif
|
||||
#include <semaphore.h>
|
||||
#include <windows.h>
|
||||
#elif defined(__linux__)
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 状态返回码枚举
|
||||
*/
|
||||
typedef enum {
|
||||
#ifndef ERROR
|
||||
ERROR = 0,
|
||||
#endif
|
||||
#ifndef SUCCESS
|
||||
SUCCESS = 1
|
||||
#endif
|
||||
} Status;
|
||||
|
||||
// 常用公共宏定义
|
||||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
|
||||
/* 时间常数定义 */
|
||||
#define portMAX_DELAY (TickType_t)0xFFFFFFFFUL
|
||||
|
||||
/* FreeRTOS 基础类型模拟 */
|
||||
typedef int32_t BaseType_t;
|
||||
typedef uint32_t TickType_t;
|
||||
typedef uint32_t UBaseType_t;
|
||||
typedef void* TaskHandle_t;
|
||||
typedef void* QueueHandle_t;
|
||||
|
||||
#define pdTRUE 1
|
||||
#define pdFALSE 0
|
||||
#define pdPASS 1
|
||||
#define pdFAIL 0
|
||||
#define errQUEUE_FULL 0 // 或者根据你现有的定义调整
|
||||
|
||||
/* 任务函数指针定义 */
|
||||
typedef void (*TaskFunction_t)(void *);
|
||||
|
||||
/* --- 严格一致的接口声明 --- */
|
||||
|
||||
// 延时 (ms)
|
||||
void vTaskDelay(const TickType_t xTicksToDelay);
|
||||
|
||||
// 创建任务
|
||||
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 vTaskStartScheduler(void);
|
||||
|
||||
// 队列操作
|
||||
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
|
||||
BaseType_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
|
||||
BaseType_t xQueueReceive(QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "SocketSample.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// --- 1. xSocketInitEnvironment ---
|
||||
int xSocketInitEnvironment(void) {
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
return SOCKET_FAIL;
|
||||
}
|
||||
#endif
|
||||
return SOCKET_SUCCESS;
|
||||
}
|
||||
|
||||
// --- 2. xSocketCreateUDP ---
|
||||
Socket_t xSocketCreateUDP(void) {
|
||||
Socket_t xSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
return xSocket;
|
||||
}
|
||||
|
||||
// --- 3. xSocketBind ---
|
||||
int xSocketBind(Socket_t xSocket, uint16_t usPort) {
|
||||
struct sockaddr_in xLocalAddr;
|
||||
memset(&xLocalAddr, 0, sizeof(xLocalAddr));
|
||||
xLocalAddr.sin_family = AF_INET;
|
||||
xLocalAddr.sin_port = htons(usPort);
|
||||
xLocalAddr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡
|
||||
|
||||
if (bind(xSocket, (struct sockaddr*)&xLocalAddr, sizeof(xLocalAddr)) == SOCKET_ERROR_HANDLE) {
|
||||
return SOCKET_FAIL;
|
||||
}
|
||||
return SOCKET_SUCCESS;
|
||||
}
|
||||
|
||||
// --- 4. vSocketClose ---
|
||||
void vSocketClose(Socket_t xSocket) {
|
||||
if (xSocket == INVALID_SOCKET_HANDLE) return;
|
||||
#ifdef _WIN32
|
||||
closesocket(xSocket);
|
||||
#else
|
||||
close(xSocket);
|
||||
#endif
|
||||
}
|
||||
|
||||
// --- 5. xSocketSendTo ---
|
||||
int32_t xSocketSendTo(Socket_t xSocket, const void* pvBuffer, uint32_t ulLength,
|
||||
const char* pcIPAddress, uint16_t usPort) {
|
||||
struct sockaddr_in xDestAddr;
|
||||
memset(&xDestAddr, 0, sizeof(xDestAddr));
|
||||
xDestAddr.sin_family = AF_INET;
|
||||
xDestAddr.sin_port = htons(usPort);
|
||||
xDestAddr.sin_addr.s_addr = inet_addr(pcIPAddress);
|
||||
|
||||
int res = sendto(xSocket, (const char*)pvBuffer, (int)ulLength, 0,
|
||||
(struct sockaddr*)&xDestAddr, sizeof(xDestAddr));
|
||||
|
||||
if (res == SOCKET_ERROR_HANDLE) return SOCKET_FAIL;
|
||||
return (int32_t)res;
|
||||
}
|
||||
|
||||
// --- 6. xSocketReceiveFrom ---
|
||||
int32_t xSocketReceiveFrom(Socket_t xSocket, void* pvBuffer, uint32_t ulLength,
|
||||
char* pcIPAddress, uint16_t* pusPort) {
|
||||
struct sockaddr_in xSourceAddr;
|
||||
#ifdef _WIN32
|
||||
int xAddrLen = sizeof(xSourceAddr);
|
||||
#else
|
||||
socklen_t xAddrLen = sizeof(xSourceAddr);
|
||||
#endif
|
||||
|
||||
int res = recvfrom(xSocket, (char*)pvBuffer, (int)ulLength, 0,
|
||||
(struct sockaddr*)&xSourceAddr, &xAddrLen);
|
||||
|
||||
if (res != SOCKET_ERROR_HANDLE) {
|
||||
if (pcIPAddress) {
|
||||
char* ip = inet_ntoa(xSourceAddr.sin_addr);
|
||||
if (ip) strcpy(pcIPAddress, ip);
|
||||
}
|
||||
if (pusPort) *pusPort = ntohs(xSourceAddr.sin_port);
|
||||
} else {
|
||||
return SOCKET_FAIL;
|
||||
}
|
||||
return (int32_t)res;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef SOCKET_SAMPLE_H
|
||||
#define SOCKET_SAMPLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
typedef SOCKET Socket_t;
|
||||
#define INVALID_SOCKET_HANDLE INVALID_SOCKET
|
||||
#define SOCKET_ERROR_HANDLE SOCKET_ERROR
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
typedef int Socket_t;
|
||||
#define INVALID_SOCKET_HANDLE -1
|
||||
#define SOCKET_ERROR_HANDLE -1
|
||||
#endif
|
||||
|
||||
#define SOCKET_SUCCESS 0
|
||||
#define SOCKET_FAIL -1
|
||||
|
||||
// 环境初始化(Win必须,Linux为空操作)
|
||||
int xSocketInitEnvironment(void);
|
||||
|
||||
// 创建 UDP Socket
|
||||
Socket_t xSocketCreateUDP(void);
|
||||
|
||||
// 绑定端口(接收端必备)
|
||||
int xSocketBind(Socket_t xSocket, uint16_t usPort);
|
||||
|
||||
// 关闭 Socket
|
||||
void vSocketClose(Socket_t xSocket);
|
||||
|
||||
// UDP 发送数据
|
||||
int32_t xSocketSendTo(Socket_t xSocket, const void* pvBuffer, uint32_t ulLength,
|
||||
const char* pcIPAddress, uint16_t usPort);
|
||||
|
||||
// UDP 接收数据
|
||||
int32_t xSocketReceiveFrom(Socket_t xSocket, void* pvBuffer, uint32_t ulLength,
|
||||
char* pcIPAddress, uint16_t* pusPort);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user