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.
		
		
		
		
			
				
					180 lines
				
				4.4 KiB
			
		
		
			
		
	
	
					180 lines
				
				4.4 KiB
			| 
											22 hours ago
										 | /*
 | ||
|  |  * 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);
 |