17 changed files with 1267 additions and 646 deletions
File diff suppressed because it is too large
Binary file not shown.
@ -0,0 +1,152 @@ |
|||||
|
/*
|
||||
|
* Copyright (c) 2006-2021, RT-Thread Development Team |
||||
|
* |
||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||
|
* |
||||
|
* Change Logs: |
||||
|
* Date Author Notes |
||||
|
* 2025-10-25 Administrator the first version |
||||
|
*/ |
||||
|
# include <rtthread.h> |
||||
|
# include <rtdevice.h> |
||||
|
# include <board.h> |
||||
|
# include <stdio.h> |
||||
|
#include "uart_framework.h" |
||||
|
#include "data_comm.h" |
||||
|
|
||||
|
#define LOG_TAG "uart.rx" |
||||
|
#define LOG_LVL LOG_LVL_DBG |
||||
|
//#include <ulog.h>
|
||||
|
|
||||
|
#define UART_NAME "uart2" |
||||
|
#define UART_BAUD_RATE BAUD_RATE_115200 |
||||
|
|
||||
|
#define RS485RD GET_PIN(A,10) |
||||
|
#define RS485_RX() rt_pin_write(RS485RD, 0) |
||||
|
#define RS485_TX() rt_pin_write(RS485RD, 1) |
||||
|
|
||||
|
#define RECV_BUF_SIZE (512) |
||||
|
#define FRAME_TIMEOUT_MS 20 |
||||
|
#define SEND_INTERVAL_MS 0 |
||||
|
#define REQUEST_TIMEOUT_MS 250 |
||||
|
|
||||
|
static uart_framework_t uf = RT_NULL; |
||||
|
|
||||
|
static void rs485_set_tx(void) |
||||
|
{ |
||||
|
RS485_TX(); |
||||
|
rt_thread_mdelay(1); |
||||
|
} |
||||
|
|
||||
|
static void rs485_set_rx(void) |
||||
|
{ |
||||
|
rt_thread_mdelay(1); |
||||
|
RS485_RX(); |
||||
|
} |
||||
|
|
||||
|
static void rs485_gpio_init(void) |
||||
|
{ |
||||
|
rt_pin_mode(RS485RD, PIN_MODE_OUTPUT); |
||||
|
rs485_set_rx(); |
||||
|
} |
||||
|
|
||||
|
static rt_err_t uart_rs485_init(void) |
||||
|
{ |
||||
|
rt_device_t serial_device = rt_device_find(UART_NAME); |
||||
|
if (serial_device == RT_NULL) |
||||
|
{ |
||||
|
rt_kprintf("not find the serial device:%s!", UART_NAME); |
||||
|
return -RT_ERROR; |
||||
|
} |
||||
|
|
||||
|
/* 修改串口配置 */ |
||||
|
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; |
||||
|
config.baud_rate = UART_BAUD_RATE; |
||||
|
config.bufsz = RECV_BUF_SIZE; // 接收缓冲区大小
|
||||
|
rt_device_control(serial_device, RT_DEVICE_CTRL_CONFIG, &config); |
||||
|
|
||||
|
rs485_gpio_init(); |
||||
|
struct uart_framework_cfg cfg = { .uart_name = UART_NAME, .max_frame_size = RECV_BUF_SIZE, .frame_interval_ms = |
||||
|
FRAME_TIMEOUT_MS, .send_interval_ms = SEND_INTERVAL_MS, .rs485_txd = rs485_set_tx, .rs485_rxd = rs485_set_rx }; |
||||
|
//如果不是485,则配置rs485_txd和rs485_rxd为RT_NULL
|
||||
|
|
||||
|
uf = uart_framework_create(&cfg); |
||||
|
if (uf == RT_NULL) |
||||
|
{ |
||||
|
rt_kprintf("SCCM link create failed on %s\n", UART_NAME); |
||||
|
return -RT_ERROR; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
rt_kprintf("SCCM link create success on %s!\n", UART_NAME); |
||||
|
return RT_EOK; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static rt_err_t frame_handler(rt_uint8_t *data, rt_size_t size) |
||||
|
{ |
||||
|
//解析数据
|
||||
|
rt_err_t res; |
||||
|
struct proc_request *req = rt_malloc(sizeof(struct proc_request)); |
||||
|
if (!req){ return RT_ERROR;} |
||||
|
rt_strncpy(req->input, (const char *)data, sizeof(req->input)); |
||||
|
req->input_len = size; |
||||
|
req->sem = rt_malloc(sizeof(struct rt_semaphore)); |
||||
|
|
||||
|
if (!req->sem) { |
||||
|
rt_free(req); |
||||
|
return RT_ERROR; |
||||
|
} |
||||
|
|
||||
|
rt_sem_init(req->sem, "uart_resp", 0, RT_IPC_FLAG_FIFO); |
||||
|
|
||||
|
// 发送到处理线程
|
||||
|
if (rt_mq_send(proc_mq, &req, sizeof(req)) == RT_EOK) |
||||
|
{ |
||||
|
// 等待处理完成
|
||||
|
if (rt_sem_take(req->sem, RT_WAITING_FOREVER) == RT_EOK) |
||||
|
{ |
||||
|
res= uart_framework_send(uf, (rt_uint8_t *)req->output, req->output_len); |
||||
|
} |
||||
|
} |
||||
|
// 清理
|
||||
|
rt_sem_detach(req->sem); // 或 rt_sem_delete
|
||||
|
rt_free(req->sem); |
||||
|
rt_free(req); |
||||
|
|
||||
|
//这里直接返回接收到的数据
|
||||
|
// rt_uint8_t *frame_data = data;
|
||||
|
// rt_uint16_t frame_len = size;
|
||||
|
// rt_kprintf("rx_buf", 16, frame_data, frame_len);
|
||||
|
// rt_err_t res = uart_framework_send(uf, frame_data, frame_len);
|
||||
|
|
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
static void rs485_rx_handler(void *params) |
||||
|
{ |
||||
|
while (1) |
||||
|
{ |
||||
|
if(uart_framework_receive(uf, RT_WAITING_FOREVER, RT_NULL, RT_NULL, 0) == RT_EOK) |
||||
|
{ |
||||
|
frame_handler(uf->rx_buf, uf->rx_size); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int app_uart_rs485_startup(void) |
||||
|
{ |
||||
|
rt_err_t rst; |
||||
|
rst = uart_rs485_init(); |
||||
|
if (rst != RT_EOK) |
||||
|
return rst; |
||||
|
|
||||
|
rt_thread_t t = rt_thread_create("rs485rx", rs485_rx_handler, RT_NULL, 1024 * 4, 12, 20); |
||||
|
if (t == RT_NULL) |
||||
|
return -RT_ENOMEM; |
||||
|
|
||||
|
rst = rt_thread_startup(t); |
||||
|
|
||||
|
return rst; |
||||
|
} |
||||
|
//INIT_APP_EXPORT(app_uart_rs485_startup);
|
||||
@ -0,0 +1,15 @@ |
|||||
|
/*
|
||||
|
* Copyright (c) 2006-2021, RT-Thread Development Team |
||||
|
* |
||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||
|
* |
||||
|
* Change Logs: |
||||
|
* Date Author Notes |
||||
|
* 2025-10-25 Administrator the first version |
||||
|
*/ |
||||
|
#ifndef APPLICATIONS_DATA_UART_RS485_H_ |
||||
|
#define APPLICATIONS_DATA_UART_RS485_H_ |
||||
|
|
||||
|
int app_uart_rs485_startup(void); |
||||
|
|
||||
|
#endif /* APPLICATIONS_DATA_UART_RS485_H_ */ |
||||
@ -0,0 +1,179 @@ |
|||||
|
/*
|
||||
|
* Copyright (c) 2006-2021, RT-Thread Development Team |
||||
|
* |
||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||
|
* |
||||
|
* Change Logs: |
||||
|
* Date Author Notes |
||||
|
* 2025-10-22 Administrator the first version |
||||
|
*/ |
||||
|
#include "dfs_fs.h" |
||||
|
#include <rtdbg.h> |
||||
|
#include <board.h> |
||||
|
#include"drv_common.h" |
||||
|
|
||||
|
#define DBG_TAG "sd_cd" |
||||
|
#define DBG_LVL DBG_LOG |
||||
|
#include <rtdbg.h> |
||||
|
|
||||
|
// ==================== 配置参数 ====================
|
||||
|
#define SD_DEVICE_NAME "sd0" |
||||
|
#define MOUNT_POINT "/" |
||||
|
|
||||
|
// CD 引脚配置(根据你的 BSP 修改)
|
||||
|
#define CD_PIN GET_PIN(A, 0) // 示例:PA0,根据实际修改!
|
||||
|
|
||||
|
// 消息类型
|
||||
|
#define SD_EVENT_INSERTED 1 |
||||
|
#define SD_EVENT_REMOVED 2 |
||||
|
|
||||
|
// ===============================================
|
||||
|
static rt_mq_t sd_event_mq = RT_NULL; |
||||
|
static rt_sem_t mount_sync_sem = RT_NULL; |
||||
|
|
||||
|
/**
|
||||
|
* @brief CD 引脚中断回调 |
||||
|
*/ |
||||
|
void cd_pin_irq(void *param) |
||||
|
{ |
||||
|
rt_uint8_t event; |
||||
|
rt_base_t level = rt_hw_interrupt_disable(); |
||||
|
|
||||
|
// 读取当前电平
|
||||
|
int pin_level = rt_pin_read(CD_PIN); |
||||
|
|
||||
|
if (pin_level == PIN_HIGH) |
||||
|
{ |
||||
|
rt_kprintf("SD Card removed (CD high)\n"); |
||||
|
event = SD_EVENT_REMOVED; |
||||
|
} |
||||
|
else // PIN_LOW
|
||||
|
{ |
||||
|
rt_kprintf("SD Card inserted (CD low)\n"); |
||||
|
event = SD_EVENT_INSERTED; |
||||
|
} |
||||
|
|
||||
|
// 发送事件到消息队列
|
||||
|
if (sd_event_mq != RT_NULL) |
||||
|
{ |
||||
|
rt_mq_send(sd_event_mq, &event, 1); |
||||
|
} |
||||
|
|
||||
|
rt_hw_interrupt_enable(level); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief 初始化 CD 引脚为外部中断模式 |
||||
|
*/ |
||||
|
int cd_pin_init(void) |
||||
|
{ |
||||
|
rt_pin_mode(CD_PIN, PIN_MODE_INPUT_PULLUP); // 内部上拉
|
||||
|
rt_pin_attach_irq(CD_PIN, PIN_IRQ_MODE_FALLING | PIN_IRQ_MODE_RISING, cd_pin_irq, RT_NULL); |
||||
|
rt_pin_irq_enable(CD_PIN, ENABLE); // 使能中断
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief 处理 SD 卡插拔事件的主线程 |
||||
|
*/ |
||||
|
void sd_card_event_thread(void *parameter) |
||||
|
{ |
||||
|
uint8_t event; |
||||
|
rt_bool_t mounted = RT_FALSE; |
||||
|
|
||||
|
rt_kprintf("SD card event thread started...\n"); |
||||
|
|
||||
|
while (1) |
||||
|
{ |
||||
|
// 等待事件
|
||||
|
if (rt_mq_recv(sd_event_mq, &event, 1, RT_WAITING_FOREVER) != RT_EOK) |
||||
|
continue; |
||||
|
|
||||
|
switch (event) |
||||
|
{ |
||||
|
case SD_EVENT_INSERTED: |
||||
|
if (!mounted) |
||||
|
{ |
||||
|
rt_kprintf("Initializing and mounting SD card...\n"); |
||||
|
|
||||
|
// 等待设备 ready(可选)
|
||||
|
rt_thread_mdelay(100); |
||||
|
|
||||
|
// 尝试挂载
|
||||
|
if (dfs_mount(SD_DEVICE_NAME, MOUNT_POINT, "elm", 0, 0) == RT_EOK) |
||||
|
{ |
||||
|
rt_kprintf("SD card mounted to %s\n", MOUNT_POINT); |
||||
|
mounted = RT_TRUE; |
||||
|
|
||||
|
// 通知其他模块可以使用 SD 卡
|
||||
|
if (mount_sync_sem) |
||||
|
rt_sem_release(mount_sync_sem); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
rt_kprintf("Failed to mount SD card\n"); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case SD_EVENT_REMOVED: |
||||
|
if (mounted) |
||||
|
{ |
||||
|
if (dfs_unmount(MOUNT_POINT) == 0) |
||||
|
{ |
||||
|
rt_kprintf("SD card unmounted\n"); |
||||
|
mounted = RT_FALSE; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
rt_kprintf("Unmount failed or not mounted\n"); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief 启动 SD 卡热插拔检测 |
||||
|
*/ |
||||
|
int stm32_sdcard_hotplug_init(void) |
||||
|
{ |
||||
|
rt_thread_t tid; |
||||
|
|
||||
|
// 创建事件消息队列
|
||||
|
sd_event_mq = rt_mq_create("sd_event", 1, 10, RT_IPC_FLAG_FIFO); |
||||
|
if (sd_event_mq == RT_NULL) |
||||
|
{ |
||||
|
rt_kprintf("Failed to create message queue for SD event!\n"); |
||||
|
return -RT_ENOMEM; |
||||
|
} |
||||
|
|
||||
|
// 创建同步信号量(可选,用于通知挂载完成)
|
||||
|
mount_sync_sem = rt_sem_create("sd_mount", 0, RT_IPC_FLAG_FIFO); |
||||
|
|
||||
|
// 创建事件处理线程
|
||||
|
tid = rt_thread_create("sd_event", |
||||
|
sd_card_event_thread, |
||||
|
RT_NULL, |
||||
|
2048, |
||||
|
RT_THREAD_PRIORITY_MAX - 2, |
||||
|
10); |
||||
|
if (tid != RT_NULL) |
||||
|
{ |
||||
|
rt_thread_startup(tid); |
||||
|
LOG_I("SD event thread created\n"); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
rt_kprintf("Failed to create SD event thread!\n"); |
||||
|
return -RT_ERROR; |
||||
|
} |
||||
|
|
||||
|
return RT_EOK; |
||||
|
} |
||||
|
//INIT_COMPONENT_EXPORT(cd_pin_init);
|
||||
|
//INIT_APP_EXPORT(stm32_sdcard_hotplug_init);
|
||||
@ -0,0 +1 @@ |
|||||
|
Subproject commit 679392a4b6beb09dd3e2febe03c2aabc3f298412 |
||||
Loading…
Reference in new issue