usb1

我们只需要移植MSD(UMS)功能。参看官方案例。进行迁移放入到middleware文件夹里面。

移植USB功能我们不需要考虑那么多。只需要给到单片机USB相关配置给这些文件就好了。

步骤 1:确认 DWC2 兼容 & 收集硬件参数

从新 MCU 数据手册拿到:USB 控制器寄存器基地址、USB 中断号、端点数、DM/DP 引脚、48MHz 时钟来源。

步骤 2:新建 Target/USBTarget.h

#ifndef __USB_TARGET_CONFIG_MH2457_H__
#define __USB_TARGET_CONFIG_MH2457_H__

#define USE_USBESL_CORE_ZOFFY 1

// Zoffy Features
#define FEATURE_USBCORE_ZOFFY_DYNAMIC_DMA_MODE 1

#define FEATURE_USBCORE_ZOFFY_MAX_EP_COUNT (6)

#include "mh2457.h"

// USB Core Base Address
#define USB_ZOFFY1_BASE 0x50000000
#define USB_ZOFFY1_IRQ  USB1_IRQn

#define USB_ZOFFY_BASE USB_ZOFFY1_BASE
#define USB_ZOFFY_IRQ  USB_ZOFFY1_IRQ

#ifndef USB_IO_CONFIG_DATA
#define USB_IO_CONFIG_DATA MakeIOConfig(IOModeAlternate, GPIO_AF_USB, IOPullNone, IOSpeedHigh, IODriveHigh)
#endif

#ifndef USB_IO_CONFIG_ID
#define USB_IO_CONFIG_ID MakeIOConfig(IOModeAlternate, GPIO_AF_USB, IOPullUp, IOSpeedMedium, IODriveMedium)
#endif

#ifndef USB_IO_CONFIG_VBUS
#define USB_IO_CONFIG_VBUS MakeIOConfig(IOModeInput, 0, IOPullNone, IOSpeedMedium, IODriveMedium)
#endif

#endif

新建 Target/USBTarget.c

extern void USBTargetConstractor(USBHALStruct* hal);   // 设能力位(DMA/Device/Host)
extern void USBTargetDelayUs(uint32_t us);             // → SystemDelayUs
extern void USBTargetEnablePhy(...);                   // PHY 上电 / GCFG
extern void USBTargetEnableInterrupt(...);             // NVIC Enable/Disable
extern void USBTargetEnableModule(...);                // ★引脚+48M时钟+外设使能
extern void USBTargetResetModule(...);                 // PeripheralReset
extern uint8_t USBTargetGetSN(...);                    // 序列号(可空)
#include "USBCoreZoffyDefine.h"
#include "USBESL.h"

inline void USBTargetConstractor(USBHALStruct* hal) {
    if (hal->USBBase == 0x50000000) { //USB硬件地址
        hal->IsDMAEnabled    = false; //关闭DMA
        hal->IsDeviceEnabled = true; //设备模式
        hal->IsHostEnabled   = false; //host关闭
        hal->IsSRPEnabled    = false; //SRP关闭
    }
    else {
        hal->IsDMAEnabled    = true;
        hal->IsDeviceEnabled = true;
        hal->IsHostEnabled   = false;
        hal->IsSRPEnabled    = false;
        hal->PhyType         = USBPhyTypeUTMI;
        hal->SpeedConfig     = USBSpeedConfigHigh;
    }
}

inline void USBTargetDelayUs(uint32_t us) {
    SystemDelayUs(us);
}

inline void USBTargetEnablePhy(USBHALStruct* hal, bool isEnable) {
    if (!isEnable || hal->PhyType == USBPhyTypeUTMI) {
        hal->Zoffy.USB->GREGS.GCFG = 0;
    }
    else {
        hal->Zoffy.USB->GREGS.GCFG = BIT(16); // Power ON

        if (!(hal->IsHNPEnabled || hal->IsSRPEnabled))
            hal->Zoffy.USB->GREGS.GCFG |= BIT(21); // NOVUBS
        else
            hal->Zoffy.USB->GREGS.GCFG |= BIT(19) | BIT(18); // VBUS A|B EN

        if (hal->PhyType == USBPhyTypeFSI2C) {
            hal->Zoffy.USB->GREGS.GI2CCTL = //
                BIT(26) |                   // I2C Addr 0x2D
                BIT(23);                    // I2C Enable
        }
        if (hal->USBBase == 0x50000000) {
            hal->Zoffy.MaxFifoSize = 0x140; // Fix FIFO size of USB 1 to 1280 bytes
        }
    }
}

inline void USBTargetEnableInterrupt(USBHALStruct* hal, bool isEnable) {
    IRQn_Type irq = USB1_IRQn;
    if (isEnable) {
        NVIC_EnableIRQ(irq);
    }
    else {
        NVIC_DisableIRQ(irq);
    }
}

inline void USBTargetEnableModule(USBHALStruct* hal, bool isEnable) {
    if (hal->USBBase == 0x50000000) {
        // Configure DM DP Pins
        IOSetup(PA11, USB_IO_CONFIG_DATA);
        IOSetup(PA12, USB_IO_CONFIG_DATA);

        // Configure ID Pin
        if (hal->IsDeviceEnabled && hal->IsHostEnabled) {
            IOSetup(PA10, USB_IO_CONFIG_ID);
        }

        // Configure VBUS Pin
        if (hal->IsSRPEnabled || hal->IsHNPEnabled) {
            IOSetup(PA9, USB_IO_CONFIG_VBUS);
        }
    }

    if (isEnable && (ClockGet(ClockNodeREF) / 1000000 != 48)) {
        ClockMultiply(ClockNodePLL3, ClockRatio(768 / 12.0));
        ClockDivide(ClockNodePLL3R, ClockRatio(768 / 48.0));
        ClockSelect(ClockNodeREF, ClockNodePLL3R);
        ClockEnable(ClockNodePLL3G, true);
    }

    PeripheralEnable(PeripheralUSB1, isEnable);
}

inline void USBTargetResetModule(USBHALStruct* hal) {
    PeripheralReset(PeripheralUSB1);
}
inline uint8_t USBTargetGetSN(uint8_t* sn, uint8_t length) {
    // TODO
    return 0;
}

步骤 4:改 USBESL.h 的 include(USBESL.h:17)

#include "Target/USBTargetMH2457.h"   // → 改为 #include "Target/USBTarget<新MCU>.h"

步骤 5:对齐中断向量名

匹配MCU 启动文件里的向量名:

// usb_msd.c:418
void USB1_IRQHandler(void) {           // ← 必须与新 MCU startup_xxx.s 的向量弱符号同名
    s_usbHAL.Interrupt(&s_usbHAL);
}

步骤 6:配置 NVIC 优先级

NVIC_SetPriority(USB_ZOFFY1_IRQ, BSP_NVIC_PRIO_USB);