Ring0中的Sleep延时函数

本文介绍了一个Windows内核模式下的延时函数mySleepTimer,该函数通过使用KeDelayExecutionThread来实现精确的5秒延时。文中还详细解释了时间单位的定义及转换宏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个函数实现的功能是延迟5秒钟。

 

 

等相对的5秒钟就是 RELATIVE(SECONDS(5)),很强大~

 

原文地址:http://yexin218.javaeye.com/blog/640165

#include <zephyr/kernel.h> #include <zephyr/device.h> #include <zephyr/devicetree.h> #include <zephyr/drivers/gpio.h> #include <zephyr/logging/log.h> #include <zephyr/drivers/uart.h> #include "GVL.h" #define LOG_MODULE_NAME rs485_thread LOG_MODULE_REGISTER(LOG_MODULE_NAME); // 获取设备树节点 #define ZEPHYR_USER_NODE DT_PATH(zephyr_user) // 声明设备 static const struct device *const rs485_uart = DEVICE_DT_GET(DT_ALIAS(myuart)); static const struct gpio_dt_spec direct_pin = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, rs485_gpios); // 延时工作 static struct k_work_delayable uart_work; // RS485接收状态机 enum rx_state { STATE_IDLE, STATE_GOT_AA, STATE_RECEIVING }; static struct { enum rx_state state; uint8_t buffer[sizeof(rs485_raw_data_t) + 3]; // AA + BB + payload + CRC size_t index; } rx_state_machine; static struct k_spinlock data_spinlock; // CRC校验函数 static uint8_t calculate_crc(const uint8_t *data, size_t len) { uint8_t crc = 0; for (size_t i = 0; i < len; i++) { crc ^= data[i]; } return crc; } // 统一数据结构处理 static void process_rs485_packet(uint8_t *packet, size_t len) { // CRC校验 (最后1字节是CRC) if (calculate_crc(packet, len - 1) != packet[len - 1]) { LOG_WRN("Invalid RS485 packet CRC"); return; } // 解析原始RS485数据 rs485_raw_data_t raw_data; memcpy(&raw_data, packet + 2, sizeof(raw_data)); // 跳过包头 // 转换为统一数据结构 unified_data_point_t data_point = { .timestamp = k_uptime_get_32(), .acc_x = raw_data.acc_x, .acc_y = raw_data.acc_y, .acc_z = raw_data.acc_z, .gyro_x = raw_data.gyro_x, .gyro_y = raw_data.gyro_y, .gyro_z = raw_data.gyro_z, .data_source = 2 // 标记为RS485设备数据 }; // 添加到批处理 k_spinlock_key_t key = k_spin_lock(&batch_lock); batch_container_t *batch = &data_batches[active_batch_index]; if (batch->count < BATCH_SIZE) { batch->data[batch->count++] = data_point; // 批次满或超时处理 if (batch->count >= BATCH_SIZE || (batch->count > 0 && (k_uptime_get() - batch->start_timestamp) > MAX_BATCH_TIMEOUT_MS)) { batch->ready = true; batch->start_timestamp = k_uptime_get(); // 切换到备用缓冲区 active_batch_index = (active_batch_index + 1) % 2; data_batches[active_batch_index].count = 0; data_batches[active_batch_index].ready = false; // 通知BLE线程 k_sem_give(&ble_data_ready_sem); } } else { LOG_WRN("Batch buffer overflow"); } k_spin_unlock(&batch_lock, key); } static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data) { static size_t aborted_len; struct uart_data_t *buf; static uint8_t *aborted_buf; static bool disable_req; k_spinlock_key_t key; switch (evt->type) { case UART_TX_DONE: LOG_DBG("UART_TX_DONE"); // 设置方向为接收模式 gpio_pin_set_dt(&direct_pin, 0); if ((evt->data.tx.len == 0) || (!evt->data.tx.buf)) { return; } if (aborted_buf) { buf = CONTAINER_OF(aborted_buf, struct uart_data_t, data[0]); aborted_buf = NULL; aborted_len = 0; k_free(buf); } else { buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t, data[0]); k_free(buf); } // 发送下一个数据包 buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT); if (buf) { // 设置方向为发送模式 gpio_pin_set_dt(&direct_pin, 1); k_busy_wait(RS485_DIR_PIN_DELAY_US); if (uart_tx(rs485_uart, buf->data, buf->len, SYS_FOREVER_MS)) { LOG_WRN("Failed to send data over UART"); gpio_pin_set_dt(&direct_pin, 0); // 确保切换回接收模式 k_free(buf); } } break; case UART_RX_RDY: const uint8_t *data = evt->data.rx.buf; size_t len = evt->data.rx.len; for (size_t i = 0; i < len; i++) { uint8_t byte = data[i]; switch (rx_state_machine.state) { case STATE_IDLE: if (byte == 0xAA) { rx_state_machine.state = STATE_GOT_AA; } break; case STATE_GOT_AA: if (byte == 0xBB) { rx_state_machine.state = STATE_RECEIVING; rx_state_machine.index = 0; rx_state_machine.buffer[rx_state_machine.index++] = 0xAA; rx_state_machine.buffer[rx_state_machine.index++] = 0xBB; } else { rx_state_machine.state = (byte == 0xAA) ? STATE_GOT_AA : STATE_IDLE; } break; case STATE_RECEIVING: rx_state_machine.buffer[rx_state_machine.index++] = byte; // 检查完整数据包 (AA + BB + payload + CRC) if (rx_state_machine.index >= sizeof(rx_state_machine.buffer)) { process_rs485_packet(rx_state_machine.buffer, rx_state_machine.index); rx_state_machine.state = STATE_IDLE; } break; } } break; case UART_RX_DISABLED: LOG_DBG("UART_RX_DISABLED"); disable_req = false; buf = k_malloc(sizeof(*buf)); if (buf) { buf->len = 0; uart_rx_enable(rs485_uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT_MS); } else { LOG_WRN("Not able to allocate UART receive buffer"); k_work_reschedule(&uart_work, K_MSEC(UART_WAIT_FOR_RX)); } break; case UART_RX_BUF_REQUEST: LOG_DBG("UART_RX_BUF_REQUEST"); buf = k_malloc(sizeof(*buf)); if (buf) { buf->len = 0; uart_rx_buf_rsp(rs485_uart, buf->data, sizeof(buf->data)); } else { LOG_WRN("Not able to allocate UART receive buffer"); } break; case UART_RX_BUF_RELEASED: LOG_DBG("UART_RX_BUF_RELEASED"); buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t, data[0]); k_free(buf); break; case UART_TX_ABORTED: LOG_DBG("UART_TX_ABORTED"); gpio_pin_set_dt(&direct_pin, 0); // 确保切换回接收模式 if (!aborted_buf) { aborted_buf = (uint8_t *)evt->data.tx.buf; aborted_len = evt->data.tx.len; } struct uart_data_t *tx_buf = CONTAINER_OF(aborted_buf, struct uart_data_t, data); size_t remaining = tx_buf->len - aborted_len; if (remaining > 0) { gpio_pin_set_dt(&direct_pin, 1); k_busy_wait(RS485_DIR_PIN_DELAY_US); uart_tx(rs485_uart, &tx_buf->data[aborted_len], remaining, SYS_FOREVER_MS); } break; default: break; } } static void uart_work_handler(struct k_work *item) { struct uart_data_t *buf = k_malloc(sizeof(*buf)); if (buf) { buf->len = 0; uart_rx_enable(rs485_uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT_MS); } else { LOG_WRN("Not able to allocate UART receive buffer"); k_work_reschedule(&uart_work, K_MSEC(UART_WAIT_FOR_RX)); } } static int rs485_init(void) { int err; if (!device_is_ready(rs485_uart)) { LOG_ERR("UART device not ready"); return -ENODEV; } // 初始化方向控制引脚 if (!device_is_ready(direct_pin.port)) { LOG_ERR("GPIO device not ready"); return -ENODEV; } err = gpio_pin_configure_dt(&direct_pin, GPIO_OUTPUT_INACTIVE); if (err) { LOG_ERR("GPIO config error: %d", err); return err; } // 初始化引脚为接收 gpio_pin_set_dt(&direct_pin, 0); // 初始化接收状态机 rx_state_machine.state = STATE_IDLE; rx_state_machine.index = 0; // 初始化UART k_work_init_delayable(&uart_work, uart_work_handler); err = uart_callback_set(rs485_uart, uart_cb, NULL); if (err) { LOG_ERR("Cannot set UART callback: %d", err); return err; } // 启动接收 k_work_schedule(&uart_work, K_NO_WAIT); return 0; } void rs485_send(const uint8_t *data, size_t len) { struct uart_data_t *tx = k_malloc(sizeof(*tx) + len); if (!tx) { LOG_ERR("Not enough memory for UART send"); return; } memcpy(tx->data, data, len); tx->len = len; // 如果发送队列为空,直接发送,否则加入队列 if (k_fifo_is_empty(&fifo_uart_tx_data)) { // 设置方向为发送模式 gpio_pin_set_dt(&direct_pin, 1); k_busy_wait(RS485_DIR_PIN_DELAY_US); if (uart_tx(rs485_uart, tx->data, tx->len, SYS_FOREVER_MS)) { LOG_WRN("Failed to start UART send"); gpio_pin_set_dt(&direct_pin, 0); // 切换回接收模式 k_free(tx); } } else { k_fifo_put(&fifo_uart_tx_data, tx); } } void rs485_thread(void) { if (rs485_init() != 0) { LOG_ERR("RS485 initialization failed"); return; } LOG_INF("RS485 thread started"); // 初始化自旋锁 k_spinlock_init(&data_spinlock); // 线程主循环 while (1) { k_sleep(K_FOREVER); } } K_THREAD_DEFINE(rs485_thread_id, 2048, rs485_thread, NULL, NULL, NULL, 5, 0, 0);
最新发布
06-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值