如何在启动后强制winCE看到SD/MMC卡

本文关键字:SD 看到 MMC winCE 启动 | 更新日期: 2023-09-27 17:49:36

我正在为一种与一些科学设备相互作用的新仪器开发软件。用户界面是通过Windows CE袖珍PC (Windows CE 600 V3.01 Build 195)。仪器的一端总是插入PC上的SD卡插槽。电缆插入仪器,当SD卡存在时,另一端插入安装的SD卡。SD卡包含一个用于仪器的芯片,以及所需的软件/固件更新和与芯片相关的数据文件。我有一个c#软件应用程序,当WinCE启动时运行。这个应用程序检查SDMMC卡的存在,因为它依赖于与随附芯片相关的数据来实现某些功能。

我的问题:如果SD卡插入到柔性电缆的另一端时,WinCE启动,WinCE检测到卡的存在,并创建'SDMMC文件夹,允许软件读取数据。如果只插入了柔性电缆,但另一端没有SDMMC卡,则Windows不会创建文件夹。这是我所期待的。但我们的现场工程师会因为各种原因更换卡在软件运行时更换芯片。如果在插入卡之前启动了windows,则会出现问题。由于柔性电缆,WinCE从未检测到卡已插入。它也从来没有检测到它被删除了。

软件每5秒轮询一次SD卡。固件可以通过位的设置来判断卡是否被插入,并将此信息传递给软件。如果卡以前不存在,现在被检测到,但'SDMMC文件夹不存在,我希望软件触发WinCE再次尝试检测。我考虑过使用注册表值,但不清楚HKEY_LOCAL_MACHINE SDMMc值的存在是否可以写入。我也不太确定这些值是什么意思。这些可以重置吗?我看到存储管理器注册表将这样定义:

[HKEY_LOCAL_MACHINE'System'StorageManager'Profiles'SDMMC] 
"Name"="SD MMC device"
"Folder"="SD Card

是否有办法读/写这个注册表戳winCE看到卡已插入在电缆的另一端?我的这个想法是不是完全错了?还有别的办法吗?

我为这个冗长的问题道歉。我一般在应用级别玩。谷歌这个问题并没有给我我需要的答案,尽管也许我知道的不够多,无法提出正确的问题。谢谢你给我的任何帮助。

更新:我仍在试图找到解决这个问题的方法。我目前的想法是,当我的仪器固件检测到卡已插入时,强制Windows CE重新枚举设备。我的代码在我的c#应用程序中轮询固件以接收此通知。对于我的仪器/应用程序,SD卡总是在"Dsk2:"。当c#应用程序收到SD卡已插入的通知时,它调用一个方法,做以下事情:

代码
     hDevice = CreateFile("''Dsk2:", (0x80000000) | (0x40000000), 0,
        IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
     if (hDevice == INVALID_HANDLE_VALUE)
     {
        int hDeviceError = Marshal.GetLastWin32Error();
        // THis is an error - call GetLastERror to find
        // out what happened.
        using (StreamWriter bw = new StreamWriter(File.Open(App.chipDebugFile, FileMode.Append)))
        {
           String iua = "DevDriverInterface: error from CreateFile: " + hDeviceError.ToString();
           bw.WriteLine(iua);
        }
        return false;
     }
     bResult = DeviceIoControl(hDevice,
        IOCTL_DISK_UPDATE_PROPERTIES, 
        null,
        0,
        null,
        0,
        ref nBytesReturned,
        nOverLapped);

/代码

在上面的例子中,CreateFile()调用失败,错误55:"指定的网络资源或设备不再可用"。

我的问题:我正在尝试做的是合理的重新枚举设备?CreateFile错误是否指示我应该进行ActivateDevice()调用?我在这里看到一个例子:在启动时加载设备驱动程序的问题——有人从c#代码中调用ActivateDevice(),我想知道这是否会解决让WIndows CE识别SD卡现在插入的问题。谁能帮助我了解什么参数发送到窗口的ActivateDevice()命令?我的这种做法是不是太离谱了?

这对我来说是全新的领域,我很感激你能提供的任何帮助。谢谢。

如何在启动后强制winCE看到SD/MMC卡

对于感兴趣的人来说,这里是修复问题的代码。当固件检测到SD卡在上电后插入或删除时,调用此方法。实际上,它卸载/加载设备驱动程序:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
 public struct DEVMGR_DEVICE_INFORMATION
 {
  public uint dwSize;
  public IntPtr hDevice;
  public IntPtr hParentDevice;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
  public string szLegacyName;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  public string szDeviceKey;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  public string szDeviceName;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  public string szBusName;
}
public enum DeviceSearchType : int
{
  DeviceSearchByLegacyName = 0,
  DeviceSearchByDeviceName = 1,
  DeviceSearchByBusName = 2,
  DeviceSearchByGuid = 3,
  DeviceSearchByParent = 4
}
class DevDriverInterface
{
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  public struct SECURITY_ATTRIBUTES
  {
     public int nLength;
     public IntPtr lpSecurityDescriptor;
     public bool bInheritHandle;
  }
  [DllImport("coredll.dll", SetLastError = true)]
  public extern static int ActivateDeviceEx(string device, IntPtr regEnts,
     UInt32 cRegEnts, IntPtr devKey);
  [DllImport("coredll.dll", SetLastError = true)]
  public extern static bool DeactivateDevice(int handle);
  [DllImport("coredll.dll", SetLastError = true)]
  public static extern int FindFirstDevice(DeviceSearchType
  searchType, IntPtr searchParam, ref DEVMGR_DEVICE_INFORMATION pdi);
  // Constructor
  public DevDriverInterface() { }
  public bool MountSDCardDrive()
  {
     const int INVALID_HANDLE_VALUE = -1;
     string mRegPath1 = "";
     int handle = INVALID_HANDLE_VALUE;
     DeviceSearchType searchType = DeviceSearchType.DeviceSearchByDeviceName;
     DEVMGR_DEVICE_INFORMATION di = new DEVMGR_DEVICE_INFORMATION();
     di.dwSize = (uint)Marshal.SizeOf(typeof(DEVMGR_DEVICE_INFORMATION));
     String searchParamString = "SDH1";
     IntPtr searchParam = Marshal.StringToBSTR(searchParamString);
     handle = FindFirstDevice(searchType, searchParam, ref di);
     if (handle == INVALID_HANDLE_VALUE)
     {
        // Failure - print error
        int hFindFirstDeviceError = Marshal.GetLastWin32Error();
        using (StreamWriter bw = new StreamWriter(File.Open(App.chipDebugFile, 
            FileMode.Append)))
        {
           String iua = "DevDriverInterface: error from FindFirstDevice: " + 
                  hFindFirstDeviceError.ToString();
           bw.WriteLine(iua);
        }
        return false;
     }
     else
     {
        mRegPath1 = di.szDeviceKey;
        bool deactBool = DeactivateDevice((int) di.hDevice);
        if (deactBool == false)
        {
           using (StreamWriter bw = new StreamWriter(File.Open(App.chipDebugFile,
              FileMode.Append)))
           {
              String iua = "DevDriverInterface: DeactivateDevice: returned false -
                          FAILED";
              bw.WriteLine(iua);
           }
           return false;
        }
        Thread.Sleep(50);
        // Call ActiveDevice to setup the device driver
        handle = ActivateDeviceEx(mRegPath1, IntPtr.Zero, 0, IntPtr.Zero);
        if (handle == INVALID_HANDLE_VALUE)
        {
           // Failure - print error
           int hActivateDeviceError = Marshal.GetLastWin32Error();
           using (StreamWriter bw = new StreamWriter(File.Open(App.chipDebugFile, 
              FileMode.Append)))
           {
              String iua = "DevDriverInterface: error from ActivateDevice: " + 
                     hActivateDeviceError.ToString();
              bw.WriteLine(iua);
           }
           return false;
        }
     }
     return true;
  }
}; // end class

这个问题在研华同事的帮助下解决了。他们为我提供了一个小的c++可执行文件,可以验证加载/卸载设备驱动程序是否会触发wince来识别已插入的SD卡。然后,我的问题变成了如何在我的c#应用程序中工作。在这个帖子(我自己的帖子)的帮助下:

c# FindFirstDevice封送处理

我能够通过使用"SDH1"作为标识设备的字符串调用FindFirstDevice()来实现这一点,然后调用DeactivateDevice()/ActivateDeviceEX()。如果有人对具体的代码感兴趣,我可以稍后发布(我现在在家,代码在我的工作笔记本电脑上)。

让我们看看一个正常运行的系统中事件的顺序。

  1. 设备启动并加载SD/MMC驱动程序
  2. 卡槽插入卡
  3. 硬件中断发生(可能是电源检测,可能是数据-这取决于OEM)
  4. 中断处理程序通知SDMMC驱动程序有卡存在
  5. 驱动程序查询卡类型
  6. 正确的功能驱动程序(存储等)被加载(或者在存储的情况下被通知)
  7. 函数驱动程序的工作是将硬件暴露给操作系统和应用程序

您的问题是,如果卡已经在插槽中,则#3在启动时不会正确发生。这在SD或USB的平台开发中并不少见-中断处理程序必须在插槽供电之前正常工作并揭开掩码。

为此创建一个软件解决方案是非常困难的,特别是如果OAL(由硬件制造商开发的操作系统的一部分,而不是微软)是一个黑盒子。我认为是这种情况。

要清楚,这绝对是一个平台错误。第一步应该是与设备OEM的支持小组交谈,告诉他们他们有一个错误,看看你是否可以让他们修复它。

如果这失败了(如果你没有买很多设备,或者设备很旧,获得支持是....挑战),那么我建议深入研究平台SDMMC驱动程序,看看是否有任何方法可以进入过程的中间。我从来没有尝试过(我一直在OEM这边,只是修复驱动程序或平台代码),所以我不确定是否有解决方案,但值得一看。

如果您下载并安装Platform Builder的评估版本,则可以免费获得源代码(请确保选择"install source"选项)。都是C语言,浏览起来也没什么意思,但俗话说,"卢克,使用源代码。"