为什么我不能将 CubeMX USB MSC 代码集成到默认的端节点 I-CUBE-LRWAN 项目中?

Why can't I integrate the CubeMX USB MSC code into the default end-node I-CUBE-LRWAN project?

我想为我的 Murata B-L072Z-LRWAN1 开发板添加 USB MSC(大容量存储 Class,也就是 USB 存储驱动器)功能。为此,我使用了最新的 I-CUBE-LRWAN 端节点项目并生成了 USB MSC 代码。我过去曾为旧版本的 I-CUBE-LRWAN(2018 年发布)做过此操作并使其正常工作。但是,如果我现在这样做,我会得到两种行为:

我无法解释这个。为什么代码在附加调试器时有效,但在未附加时完全锁定?至于 I-CUBE-LRWAN 新旧版本之间的变化:它们已经从 systick 更改为基于 RTC 的计时设置。但是我无法弄清楚这与调试器有何关系。

移除 USB 设备电缆不会生成代码 运行。

当我注释掉对 MX_USB_DEVICE_Init 的调用时,windows 看到一个无法识别的 USB 设备,但代码的 none 有效(例如,没有调试 UART 输出)。当我取消注释时 MX_USB_DEVICE_Init 没有任何反应,没有 USB 连接。

我正在使用 Keil uVision 作为我的 IDE。编译器版本:“默认编译器版本 6”

要复制这个,您需要一个 B-L072Z-LRWAN1(经过修改以启用 USB 引脚)或带有 USB 端口的 Murata 芯片。完整的最小可重现示例是从 I-CUBE-LRWAN 中获取端节点项目并在 STM32CubeMX 中生成 USB MSC 代码。 (目标 MCU 是 STM32L072CZTx)。然后将所有 USB MSC 文件添加到端节点项目,并在项目中添加以下内容:

将 USB_IRQHandler 添加到 stm32l0xx_it.c:

extern PCD_HandleTypeDef hpcd_USB_FS;
/**
* @brief This function handles USB event interrupt / USB wake-up interrupt through EXTI line 18.
*/
void USB_IRQHandler(void)
{
  HAL_PCD_IRQHandler(&hpcd_USB_FS);
}

将以下时钟配置附加到SystemClock_Config

RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
while(!LL_RCC_HSI48_IsReady());
    
/*USB clock initialization  */
PeriphClkInit.PeriphClockSelection |= RCC_PERIPHCLK_USB;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
  Error_Handler();
}

并添加包含的 #include usb_device.h 并在 main.c

中调用 MX_USB_DEVICE_Init();

关于我的旧代码,当我将它闪存到我的板上时,USB 确实可以与其他所有东西(LED、LoRaWAN、调试 UART)一起工作。


运行 USB MSC 代码在它自己的作品中。 运行 LoRaWAN 代码在它自己的作品中。问题只体现在这两个合并上。

问题是 printf 被调用是因为 usbd_conf.h 中的以下定义。

/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
  * @brief Defines for configuration of the Usb device.
  * @{
  */

/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES     1
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION     1
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ     512
/*---------- -----------*/
#define USBD_SUPPORT_USER_STRING     0
/*---------- -----------*/
#define USBD_DEBUG_LEVEL     3
/*---------- -----------*/
#define USBD_SELF_POWERED     1
/*---------- -----------*/
#define MSC_MEDIA_PACKET     512

/****************************************/
/* #define for FS and HS identification */
#define DEVICE_FS       0

/**
  * @}
  */

/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros
  * @brief Aliases.
  * @{
  */

/* Memory management macros */

/** Alias for memory allocation. */
#define USBD_malloc         (uint32_t *)USBD_static_malloc

/** Alias for memory release. */
#define USBD_free           USBD_static_free

/** Alias for memory set. */
#define USBD_memset         /* Not used */

/** Alias for memory copy. */
#define USBD_memcpy         /* Not used */

/** Alias for delay. */
#define USBD_Delay          HAL_Delay

/* DEBUG macros */

#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...)    printf(__VA_ARGS__);\
                            printf("\n");
#else
#define USBD_UsrLog(...)
#endif

#if (USBD_DEBUG_LEVEL > 1)

#define USBD_ErrLog(...)    printf("ERROR: ") ;\
                            printf(__VA_ARGS__);\
                            printf("\n");
#else
#define USBD_ErrLog(...)
#endif

#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...)    printf("DEBUG : ") ;\
                            printf(__VA_ARGS__);\
                            printf("\n");
#else
#define USBD_DbgLog(...)
#endif

所以这个版本的I-CUBE-LRWAN的解决方案是将USBD_DEBUG_LEVEL的值设置为0。另一种选择是通过将 printf 更改为 APP_PRINTF.

来解决此问题

还有一个问题就是sequencer中的sleep函数导致了问题。在 sys_conf.h 中将定义 LOW_POWER_DISABLE 设置为 1 会禁用停止模式。

如果在 USB 操作期间需要更精细的控制,那么在正确的设置和取消设置模式下调用此行将使其工作:

UTIL_LPM_SetStopMode((1 << CFG_LPM_APPLI_Id), UTIL_LPM_DISABLE);

(低功耗在 sys_app.c:96 中处理。