You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.4 KiB
179 lines
4.4 KiB
/*
|
|
* 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);
|
|
|