打印
[应用方案]

M480BSP_ISP-1:ISP_DFU

[复制链接]
511|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
goodluck09876|  楼主 | 2021-1-8 19:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
M480BSP_ISP-1:ISP_DFU

使用特权

评论回复
沙发
goodluck09876|  楼主 | 2021-1-8 19:22 | 只看该作者
M480BSP_ISP-1:ISP_DFU

ISP_DFU.rar

3.94 MB

使用特权

评论回复
板凳
goodluck09876|  楼主 | 2021-1-8 19:24 | 只看该作者
/***************************************************************************//**
* @file     main.c
* @brief
*           Demonstrate how to upgrade firmware between USB device and PC through USB DFU( Device Firmware Upgrade) class.
*           A Windows tool is also included in this sample code to connect with USB device.
*
* @CopyRight (C) 2019 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "fmc_user.h"
#include "dfu_transfer.h"

#define PLLCON_SETTING          CLK_PLLCTL_192MHz_HXT
#define PLL_CLOCK               192000000
#define HCLK_DIV                        2
#define USBD_DIV                        4

#define V6M_AIRCR_VECTKEY_DATA    0x05FA0000UL
#define V6M_AIRCR_SYSRESETREQ     0x00000004UL

#define DetectPin   PB12

uint32_t g_apromSize;

uint32_t GetApromSize()
{
    //the smallest of APROM size is 2K
    uint32_t size = 0x800, data;
    int result;

    do
    {
        result = FMC_Read_User(size, &data);

        if (result < 0)
        {
            return size;
        }
        else
        {
            size *= 2;
        }
    } while (1);
}

/*--------------------------------------------------------------------------*/
uint32_t CLK_GetPLLClockFreq(void)
{
    return PLL_CLOCK;
}

void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
    PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
    /* Enable Internal RC clock and external XTAL clock */
    CLK->PWRCTL |= (CLK_PWRCTL_HXTEN_Msk | CLK_PWRCTL_HIRCEN_Msk);

    /* Waiting for external XTAL clock ready */
    while (!(CLK->STATUS & CLK_STATUS_HXTSTB_Msk));

    /* Set core clock as PLL_CLOCK from PLL */
    CLK->PLLCTL = PLLCON_SETTING;

    while (!(CLK->STATUS & CLK_STATUS_PLLSTB_Msk));

    CLK->CLKDIV0 &= ~CLK_CLKDIV0_HCLKDIV_Msk;
    CLK->CLKDIV0 |= CLK_CLKDIV0_HCLK(HCLK_DIV);
    CLK->CLKDIV0 &= ~CLK_CLKDIV0_USBDIV_Msk;
    CLK->CLKDIV0 |= CLK_CLKDIV0_USB(USBD_DIV);
    CLK->CLKSEL0 &= (~CLK_CLKSEL0_HCLKSEL_Msk) | CLK_CLKSEL0_HCLKSEL_PLL;
    CLK->CLKSEL0 |= CLK_CLKSEL0_USBSEL_Msk;

    /* Update System Core Clock */
    PllClock        = PLL_CLOCK;                        // PLL
    SystemCoreClock = PLL_CLOCK / HCLK_DIV;             // HCLK
    CyclesPerUs     = SystemCoreClock / 1000000;// For SYS_SysTickDelay()
    /* Set both PCLK0 and PCLK1 as HCLK/2 */
    CLK->PCLKDIV = CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2;

    /* Select USBD */
    SYS->USBPHY = (SYS->USBPHY & ~SYS_USBPHY_USBROLE_Msk) | SYS_USBPHY_USBEN_Msk | SYS_USBPHY_SBO_Msk;

    /* Enable module clock */
    CLK->APBCLK0 |= CLK_APBCLK0_USBDCKEN_Msk;
    CLK->AHBCLK |= CLK_AHBCLK_ISPCKEN_Msk;
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Set PA.12 ~ PA.14 to input mode */
    PA->MODE &= ~(GPIO_MODE_MODE12_Msk | GPIO_MODE_MODE13_Msk | GPIO_MODE_MODE14_Msk);
    SYS->GPA_MFPH &= ~(SYS_GPA_MFPH_PA12MFP_Msk | SYS_GPA_MFPH_PA13MFP_Msk | SYS_GPA_MFPH_PA14MFP_Msk | SYS_GPA_MFPH_PA15MFP_Msk);
    SYS->GPA_MFPH |= (SYS_GPA_MFPH_PA12MFP_USB_VBUS | SYS_GPA_MFPH_PA13MFP_USB_D_N | SYS_GPA_MFPH_PA14MFP_USB_D_P | SYS_GPA_MFPH_PA15MFP_USB_OTG_ID);
}

void USBD_IRQHandler(void);
/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
    /* Unlock write-protected registers */
    SYS_UnlockReg();

    /* Init system and multi-function I/O */
    SYS_Init();
    FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk | FMC_ISPCTL_APUEN_Msk | FMC_ISPCTL_ISPFF_Msk;
    g_apromSize = GetApromSize();

    /* Open USB controller */
    USBD_Open(&gsInfo, DFU_ClassRequest, NULL);

    /*Init Endpoint configuration for DFU */
    DFU_Init();

    /* Start USB device */
    USBD_Start();

    /* polling USBD interrupt flag */
    while (DetectPin == 0)
    {
        USBD_IRQHandler();
    }

    outpw(&SYS->RSTSTS, 3);//clear bit
    outpw(&FMC->ISPCTL, inpw(&FMC->ISPCTL) & 0xFFFFFFFC);
    outpw(&SCB->AIRCR, (V6M_AIRCR_VECTKEY_DATA | V6M_AIRCR_SYSRESETREQ));

    /* Trap the CPU */
    while (1);
}

使用特权

评论回复
地板
goodluck09876|  楼主 | 2021-1-8 19:25 | 只看该作者
/***************************************************************************//**
* @file     descriptors.c
* @brief    M480 series USBD driver source file
* @version  2.0.0
*
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
/*!<Includes */
#include "M480.h"
#include "dfu_transfer.h"

/*----------------------------------------------------------------------------*/
/*!<USB Device Descriptor */
uint8_t gu8DeviceDescriptor[] =
{
    18,   /* bLength */
    0x01,   /* bDescriptorType */
    0x10,   /* bcdUSB, version 1.10 */
    0x01,
    0x00,   /* bDeviceClass : See interface */
    0x00,   /* bDeviceSubClass : See interface*/
    0x00,   /* bDeviceProtocol : See interface */
    EP0_MAX_PKT_SIZE, /* bMaxPacketSize0 0x40 = 64 */
    /* idVendor */
    USBD_VID & 0x00FF,
    (USBD_VID & 0xFF00) >> 8,
    /* idProduct */
    USBD_PID & 0x00FF,
    (USBD_PID & 0xFF00) >> 8,
    0x00,   /* bcdDevice*/
    0x01,
    0x01,   /* iManufacturer : index of string Manufacturer  */
    0x02,   /* iProduct      : index of string descriptor of product*/
    0x03,   /* iSerialNumber : index of string serial number*/
    0x01    /*bNumConfigurations */
};

#define u8_usbConfigDescriptorDFU_LENGTH      (18 + (9 * 1))
/*!<USB Configure Descriptor */
uint8_t gu8ConfigDescriptor[] =
{
    0x09,   /* bLength: Configuation Descriptor size */
    0x02,   /* bDescriptorType: Configuration */
    u8_usbConfigDescriptorDFU_LENGTH,   /* wTotalLength: Bytes returned */
    0x00,
    0x01,   /* bNumInterfaces: 1 interface */
    0x01,   /* bConfigurationValue: */
    0x00,   /* iConfiguration: */
    0x80,   /* bmAttributes: */
    0x32,   /* MaxPower 100 mA */
    /* 09 */

    /************ Descriptor of DFU interface 0 Alternate setting 0 *********/
    0x09,   /* bLength: Interface Descriptor size */
    0x04,   /* bDescriptorType: */
    0x00,   /* bInterfaceNumber: Number of Interface */
    0x00,   /* bAlternateSetting: Alternate setting */
    0x00,   /* bNumEndpoints*/
    0xFE,   /* bInterfaceClass: DFU */
    0x01,   /* bInterfaceSubClass */
    0x02,   /* nInterfaceProtocol, switched to 0x02 while in dfu_mode */
    0x00,   /* iInterface: */

    /******************** DFU Functional Descriptor********************/
    0x09,   /*blength = 7 Bytes*/
    0x21,   /* DFU Functional Descriptor*/
    0x0B,   /*bmAttributes, bitCanDnload | bitCanUpload */
    0xFF,   /*DetachTimeOut= 255 ms*/
    0x00,
    (TRANSFER_SIZE & 0x00FF),
    (TRANSFER_SIZE & 0xFF00) >> 8, /* TransferSize = 1024 Byte*/
    0x10,                          /* bcdDFUVersion = 1.1 */
    0x01
};

/*!<USB Language String Descriptor */
uint8_t gu8StringLang[4] =
{
    4,              /* bLength */
    DESC_STRING,    /* bDescriptorType */
    0x09, 0x04
};

/*!<USB Vendor String Descriptor */
uint8_t gu8VendorStringDesc[] =
{
    16,
    DESC_STRING,
    'N', 0, 'u', 0, 'v', 0, 'o', 0, 't', 0, 'o', 0, 'n', 0
};

/*!<USB Product String Descriptor */
uint8_t gu8ProductStringDesc[] =
{
    14,
    DESC_STRING,
    'N', 0, 'u', 0, '_', 0, 'D', 0, 'F', 0, 'U', 0
};

uint8_t gu8StringSerial[] =
{
    4,             // bLength
    DESC_STRING,   // bDescriptorType
    '1', 0
};

uint8_t *gpu8UsbString[4] =
{
    gu8StringLang,
    gu8VendorStringDesc,
    gu8ProductStringDesc,
    gu8StringSerial
};

const S_USBD_INFO_T gsInfo =
{
    (uint8_t *)gu8DeviceDescriptor,
    (uint8_t *)gu8ConfigDescriptor,
    (uint8_t **)gpu8UsbString,
    NULL,
    NULL,
    NULL,
    NULL
};

使用特权

评论回复
5
goodluck09876|  楼主 | 2021-1-8 19:25 | 只看该作者
/***************************************************************************//**
* @file     fmc_user.c
* @brief    M480 series FMC driver source file
* @version  2.0.0
*
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "fmc_user.h"


int FMC_Proc(unsigned int u32Cmd, unsigned int addr_start, unsigned int addr_end, unsigned int *data)
{
    unsigned int u32Addr, Reg;

    for (u32Addr = addr_start; u32Addr < addr_end; data++, u32Addr += 4)
    {
        FMC->ISPADDR = u32Addr;

        if ((u32Addr & (FMC_FLASH_PAGE_SIZE - 1)) == 0 && u32Cmd == FMC_ISPCMD_PROGRAM)
        {
            FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE;
            FMC->ISPTRG = 0x1;

            while (FMC->ISPTRG & 0x1) ;
        }

        FMC->ISPCMD = u32Cmd;

        if (u32Cmd == FMC_ISPCMD_PROGRAM)
        {
            FMC->ISPDAT = *data;
        }

        FMC->ISPTRG = 0x1;
        //        __ISB();

        while (FMC->ISPTRG & 0x1) ;  /* Wait for ISP command done. */

        Reg = FMC->ISPCTL;

        if (Reg & FMC_ISPCTL_ISPFF_Msk)
        {
            FMC->ISPCTL = Reg;
            return -1;
        }

        if (u32Cmd == FMC_ISPCMD_READ)
        {
            *data = FMC->ISPDAT;
        }

    }

    return 0;
}

/**
* @brief       Read 32-bit Data from specified address of flash
*
* @param[in]   u32addr  Flash address include APROM, LDROM, Data Flash, and CONFIG
*
* @return      The data of specified address
*
* @Details     To read word data from Flash include APROM, LDROM, Data Flash, and CONFIG.
*
* @note
*              Please make sure that Register Write-Protection Function has been disabled
*              before using this function. User can check the status of
*              Register Write-Protection Function with DrvSYS_IsProtectedRegLocked().
*/
int FMC_Read_User(unsigned int u32Addr, unsigned int *data)
{
    return FMC_Proc(FMC_ISPCMD_READ, u32Addr, u32Addr + 4, data);
}

void ReadData(unsigned int addr_start, unsigned int addr_end, unsigned int *data)    // Read data from flash
{
    FMC_Proc(FMC_ISPCMD_READ, addr_start, addr_end, data);
    return;
}

void WriteData(unsigned int addr_start, unsigned int addr_end, unsigned int *data)  // Write data into flash
{
    FMC_Proc(FMC_ISPCMD_PROGRAM, addr_start, addr_end, data);
    return;
}

使用特权

评论回复
6
goodluck09876|  楼主 | 2021-1-8 19:26 | 只看该作者
/**************************************************************************//**
* @file     usbd_user.c
* @version  V1.00
* @brief    M480 USBD driver source file
*
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/

#include <string.h>
#include "NuMicro.h"
#include "M480.h"

#ifdef __cplusplus
extern "C"
{
#endif

/** @addtogroup Standard_Driver Standard Driver
  @{
*/

/** @addtogroup USBD_Driver USBD Driver
  @{
*/


/** @addtogroup USBD_EXPORTED_FUNCTIONS USBD Exported Functions
  @{
*/

/* Global variables for Control Pipe */
uint8_t g_usbd_SetupPacket[8] = {0ul};        /*!< Setup packet buffer */
volatile uint8_t g_usbd_RemoteWakeupEn = 0ul; /*!< Remote wake up function enable flag */

/**
* @cond HIDDEN_SYMBOLS
*/
static uint8_t *g_usbd_CtrlInPointer = 0;
static uint8_t *g_usbd_CtrlOutPointer = 0;
static volatile uint32_t g_usbd_CtrlInSize = 0ul;
static volatile uint32_t g_usbd_CtrlOutSize = 0ul;
static volatile uint32_t g_usbd_CtrlOutSizeLimit = 0ul;
static volatile uint32_t g_usbd_UsbAddr = 0ul;
static volatile uint32_t g_usbd_UsbConfig = 0ul;
static volatile uint32_t g_usbd_CtrlMaxPktSize = 8ul;
static volatile uint32_t g_usbd_UsbAltInterface = 0ul;
static volatile uint8_t g_usbd_CtrlInZeroFlag = 0ul;
/**
* @endcond
*/

const S_USBD_INFO_T *g_usbd_sInfo;                  /*!< A pointer for USB information structure */

//VENDOR_REQ g_usbd_pfnVendorRequest       = NULL;    /*!< USB Vendor Request Functional Pointer */
CLASS_REQ g_usbd_pfnClassRequest         = NULL;    /*!< USB Class Request Functional Pointer */
SET_INTERFACE_REQ g_usbd_pfnSetInterface = NULL;    /*!< USB Set Interface Functional Pointer */
SET_CONFIG_CB g_usbd_pfnSetConfigCallback = NULL;   /*!< USB Set configuration callback function pointer */
uint32_t g_u32EpStallLock                = 0ul;     /*!< Bit map flag to lock specified EP when SET_FEATURE */

/**
  * @brief      This function makes USBD module to be ready to use
  *
  * @param[in]  param           The structure of USBD information.
  * @param[in]  pfnClassReq     USB Class request callback function.
  * @param[in]  pfnSetInterface USB Set Interface request callback function.
  *
  * @return     None
  *
  * @details    This function will enable USB controller, USB PHY transceiver and pull-up resistor of USB_D+ pin. USB PHY will drive SE0 to bus.
  */
void USBD_Open(const S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
{
    g_usbd_sInfo = param;
    g_usbd_pfnClassRequest = pfnClassReq;
    g_usbd_pfnSetInterface = pfnSetInterface;
    /* get EP0 maximum packet size */
    g_usbd_CtrlMaxPktSize = g_usbd_sInfo->gu8DevDesc[7];
    /* Initial USB engine */
    USBD->ATTR = 0x6D0ul;
    /* Force SE0 */
    USBD_SET_SE0();
}

/**
  * @brief    This function makes USB host to recognize the device
  *
  * @param    None
  *
  * @return   None
  *
  * @details  Enable WAKEUP, FLDET, USB and BUS interrupts. Disable software-disconnect function after 100ms delay with SysTick timer.
  */
void USBD_Start(void)
{
    /* Disable software-disconnect function */
    USBD_CLR_SE0();
    USBD->ATTR = 0x7D0ul;
    /* Clear USB-related interrupts before enable interrupt */
    USBD_CLR_INT_FLAG(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
    /* Enable USB-related interrupts. */
    USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
}

/**
  * @brief      Get the received SETUP packet
  *
  * @param[in]  buf A buffer pointer used to store 8-byte SETUP packet.
  *
  * @return     None
  *
  * @details    Store SETUP packet to a user-specified buffer.
  *
  */
void USBD_GetSetupPacket(uint8_t *buf)
{
    USBD_MemCopy(buf, g_usbd_SetupPacket, 8ul);
}

/**
  * @brief    Process SETUP packet
  *
  * @param    None
  *
  * @return   None
  *
  * @details  Parse SETUP packet and perform the corresponding action.
  *
  */
void USBD_ProcessSetupPacket(void)
{
    /* Get SETUP packet from USB buffer */
    USBD_MemCopy(g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE + USBD->STBUFSEG, 8);

    /* Check the request type */
    switch (g_usbd_SetupPacket[0] & 0x60ul)
    {
        case REQ_STANDARD:
        {
            USBD_StandardRequest();
            break;
        }

        case REQ_CLASS:
        {
            if (g_usbd_pfnClassRequest != NULL)
            {
                g_usbd_pfnClassRequest();
            }

            break;
        }

        default:   // reserved
        {
            /* Setup error, stall the device */
            USBD_SET_EP_STALL(EP0);
            USBD_SET_EP_STALL(EP1);
            break;
        }
    }
}

/**
  * @brief    Process GetDescriptor request
  *
  * @param    None
  *
  * @return   None
  *
  * @details  Parse GetDescriptor request and perform the corresponding action.
  *
  */
void USBD_GetDescriptor(void)
{
    uint32_t u32Len;
    g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
    u32Len = 0ul;
    u32Len = g_usbd_SetupPacket[7];
    u32Len <<= 8ul;
    u32Len += g_usbd_SetupPacket[6];

    switch (g_usbd_SetupPacket[3])
    {
        /* Get Device Descriptor */
        case DESC_DEVICE:
        {
            u32Len = USBD_Minimum(u32Len, (uint32_t)LEN_DEVICE);
            USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len);
            break;
        }

        /* Get Configuration Descriptor */
        case DESC_CONFIG:
        {
            uint32_t u32TotalLen;
            u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3];
            u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8);

            if (u32Len > u32TotalLen)
            {
                u32Len = u32TotalLen;

                if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
                {
                    g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
                }
            }

            USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len);

            break;
        }

        /* Get String Descriptor */
        case DESC_STRING:
        {
            /* Get String Descriptor */
            if (g_usbd_SetupPacket[2] < 4ul)
            {
                if (u32Len > g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0])
                {
                    u32Len = g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0];

                    if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
                    {
                        g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
                    }
                }

                USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]], u32Len);
                break;
            }
            else
            {
                /* Not support. Reply STALL. */
                USBD_SET_EP_STALL(EP0);
                USBD_SET_EP_STALL(EP1);
                break;
            }
        }

        default:
            /* Not support. Reply STALL.*/
            USBD_SET_EP_STALL(EP0);
            USBD_SET_EP_STALL(EP1);
            break;
    }
}

/**
  * @brief    Process standard request
  *
  * @param    None
  *
  * @return   None
  *
  * @details  Parse standard request and perform the corresponding action.
  *
  */
void USBD_StandardRequest(void)
{

    /* clear global variables for new request */
    g_usbd_CtrlInPointer = 0;
    g_usbd_CtrlInSize = 0ul;

    if ((g_usbd_SetupPacket[0] & 0x80ul) == 0x80ul)   /* request data transfer direction */
    {
        /* Device to host */
        switch (g_usbd_SetupPacket[1])
        {
#if 0

            case GET_CONFIGURATION:
            {
                /* Return current configuration setting */
                /* Data stage */
                addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
                M8(addr) = (uint8_t)g_usbd_UsbConfig;
                USBD_SET_DATA1(EP0);
                USBD_SET_PAYLOAD_LEN(EP0, 1ul);
                /* Status stage */
                USBD_PrepareCtrlOut(0, 0ul);
                break;
            }

#endif

            case GET_DESCRIPTOR:
            {
                USBD_GetDescriptor();
                USBD_PrepareCtrlOut(0, 0ul); /* For status stage */
                break;
            }

#if 0

            case GET_INTERFACE:
            {
                /* Return current interface setting */
                /* Data stage */
                addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
                M8(addr) = (uint8_t)g_usbd_UsbAltInterface;
                USBD_SET_DATA1(EP0);
                USBD_SET_PAYLOAD_LEN(EP0, 1ul);
                /* Status stage */
                USBD_PrepareCtrlOut(0, 0ul);
                break;
            }

            case GET_STATUS:
            {
                /* Device */
                if (g_usbd_SetupPacket[0] == 0x80ul)
                {
                    uint8_t u8Tmp;
                    u8Tmp = (uint8_t)0ul;

                    if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x40ul) == 0x40ul)
                    {
                        u8Tmp |= (uint8_t)1ul; /* Self-Powered/Bus-Powered.*/
                    }

                    if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x20ul) == 0x20ul)
                    {
                        u8Tmp |= (uint8_t)(g_usbd_RemoteWakeupEn << 1ul); /* Remote wake up */
                    }

                    addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
                    M8(addr) = u8Tmp;
                }
                /* Interface */
                else if (g_usbd_SetupPacket[0] == 0x81ul)
                {
                    addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
                    M8(addr) = (uint8_t)0ul;
                }
                /* Endpoint */
                else if (g_usbd_SetupPacket[0] == 0x82ul)
                {
                    uint8_t ep = (uint8_t)(g_usbd_SetupPacket[4] & 0xFul);
                    addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
                    M8(addr) = (uint8_t)(USBD_GetStall(ep) ? 1ul : 0ul);
                }

                addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0) + 1ul;
                M8(addr) = (uint8_t)0ul;
                /* Data stage */
                USBD_SET_DATA1(EP0);
                USBD_SET_PAYLOAD_LEN(EP0, 2ul);
                /* Status stage */
                USBD_PrepareCtrlOut(0, 0ul);
                break;
            }

#endif

            default:
            {
                /* Setup error, stall the device */
                USBD_SET_EP_STALL(EP0);
                USBD_SET_EP_STALL(EP1);
                break;
            }
        }
    }
    else
    {
        /* Host to device */
        switch (g_usbd_SetupPacket[1])
        {
            case CLEAR_FEATURE:
            {
                if (g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
                {
                    uint32_t epNum, i;
                    /* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
                       a flag: g_u32EpStallLock is added to support it */
                    epNum = (uint8_t)(g_usbd_SetupPacket[4] & 0xFul);

                    for (i = 0ul; i < USBD_MAX_EP; i++)
                    {
                        if (((USBD->EP.CFG & 0xFul) == epNum) && ((g_u32EpStallLock & (1ul << i)) == 0ul))
                        {
                            USBD->EP.CFGP &= ~USBD_CFGP_SSTALL_Msk;
                            USBD->EP.CFG &= ~USBD_CFG_DSQSYNC_Msk;
                        }
                    }
                }
                else if (g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
                {
                    g_usbd_RemoteWakeupEn = (uint8_t)0;
                }

                /* Status stage */
                USBD_SET_DATA1(EP0);
                USBD_SET_PAYLOAD_LEN(EP0, 0ul);
                break;
            }

            case SET_ADDRESS:
            {
                g_usbd_UsbAddr = g_usbd_SetupPacket[2];
                /* Status Stage */
                USBD_SET_DATA1(EP0);
                USBD_SET_PAYLOAD_LEN(EP0, 0ul);
                break;
            }

            case SET_CONFIGURATION:
            {
                g_usbd_UsbConfig = g_usbd_SetupPacket[2];

                if (g_usbd_pfnSetConfigCallback)
                {
                    g_usbd_pfnSetConfigCallback();
                }

                /* Status stage */
                USBD_SET_DATA1(EP0);
                USBD_SET_PAYLOAD_LEN(EP0, 0ul);
                break;
            }

            case SET_FEATURE:
            {
#if 0

                if ((g_usbd_SetupPacket[0] & 0xFul) == 0ul)    /* 0: device */
                {
                    if ((g_usbd_SetupPacket[2] == 3ul) && (g_usbd_SetupPacket[3] == 0ul))   /* 3: HNP enable */
                    {
                        OTG->CTL |= (OTG_CTL_HNPREQEN_Msk | OTG_CTL_BUSREQ_Msk);
                    }
                }

#endif

                if (g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
                {
                    USBD_SetStall((uint8_t)(g_usbd_SetupPacket[4] & 0xFul));
                }
                else if (g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
                {
                    g_usbd_RemoteWakeupEn = (uint8_t)1ul;
                }

                /* Status stage */
                USBD_SET_DATA1(EP0);
                USBD_SET_PAYLOAD_LEN(EP0, 0ul);
                break;
            }

#if 0

            case SET_INTERFACE:
            {
                g_usbd_UsbAltInterface = g_usbd_SetupPacket[2];

                if (g_usbd_pfnSetInterface != NULL)
                {
                    g_usbd_pfnSetInterface(g_usbd_UsbAltInterface);
                }

                /* Status stage */
                USBD_SET_DATA1(EP0);
                USBD_SET_PAYLOAD_LEN(EP0, 0ul);
                break;
            }

#endif

            default:
            {
                /* Setup error, stall the device */
                USBD_SET_EP_STALL(EP0);
                USBD_SET_EP_STALL(EP1);
                break;
            }
        }
    }
}

/**
  * @brief      Prepare the first Control IN pipe
  *
  * @param[in]  pu8Buf  The pointer of data sent to USB host.
  * @param[in]  u32Size The IN transfer size.
  *
  * @return     None
  *
  * @details    Prepare data for Control IN transfer.
  *
  */
void USBD_PrepareCtrlIn(uint8_t pu8Buf[], uint32_t u32Size)
{
    uint32_t addr;

    if (u32Size > g_usbd_CtrlMaxPktSize)
    {
        /* Data size > MXPLD */
        g_usbd_CtrlInPointer = pu8Buf + g_usbd_CtrlMaxPktSize;
        g_usbd_CtrlInSize = u32Size - g_usbd_CtrlMaxPktSize;
        USBD_SET_DATA1(EP0);
        addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
        USBD_MemCopy((uint8_t *)addr, pu8Buf, g_usbd_CtrlMaxPktSize);
        USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
    }
    else
    {
        /* Data size <= MXPLD */
        g_usbd_CtrlInPointer = 0;
        g_usbd_CtrlInSize = 0ul;
        USBD_SET_DATA1(EP0);
        addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
        USBD_MemCopy((uint8_t *)addr, pu8Buf, u32Size);
        USBD_SET_PAYLOAD_LEN(EP0, u32Size);
    }
}

/**
  * @brief    Repeat Control IN pipe
  *
  * @param    None
  *
  * @return   None
  *
  * @details  This function processes the remained data of Control IN transfer.
  *
  */
void USBD_CtrlIn(void)
{
    uint32_t addr;

    if (g_usbd_CtrlInSize)
    {
        /* Process remained data */
        if (g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize)
        {
            /* Data size > MXPLD */
            addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
            USBD_MemCopy((uint8_t *)addr, (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize);
            USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
            g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize;
            g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize;
        }
        else
        {
            /* Data size <= MXPLD */
            addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
            USBD_MemCopy((uint8_t *)addr, (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize);
            USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize);
            g_usbd_CtrlInPointer = 0;
            g_usbd_CtrlInSize = 0ul;
        }
    }
    else
    {
        /* In ACK for Set address */
        if ((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == SET_ADDRESS))
        {
            addr = USBD_GET_ADDR();

            if ((addr != g_usbd_UsbAddr) && (addr == 0ul))
            {
                USBD_SET_ADDR(g_usbd_UsbAddr);
            }
        }

        /* For the case of data size is integral times maximum packet size */
        if (g_usbd_CtrlInZeroFlag)
        {
            USBD_SET_PAYLOAD_LEN(EP0, 0ul);
            g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
        }
    }
}

/**
  * @brief      Prepare the first Control OUT pipe
  *
  * @param[in]  pu8Buf  The pointer of data received from USB host.
  * @param[in]  u32Size The OUT transfer size.
  *
  * @return     None
  *
  * @details    This function is used to prepare the first Control OUT transfer.
  *
  */
void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
{
    g_usbd_CtrlOutPointer = pu8Buf;
    g_usbd_CtrlOutSize = 0ul;
    g_usbd_CtrlOutSizeLimit = u32Size;
    USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
}

/**
  * @brief    Repeat Control OUT pipe
  *
  * @param    None
  *
  * @return   None
  *
  * @details  This function processes the successive Control OUT transfer.
  *
  */
void USBD_CtrlOut(void)
{
    uint32_t u32Size;
    uint32_t addr;

    if (g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
    {
        u32Size = USBD_GET_PAYLOAD_LEN(EP1);
        addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1);
        USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer, (uint8_t *)addr, u32Size);
        g_usbd_CtrlOutPointer += u32Size;
        g_usbd_CtrlOutSize += u32Size;

        if (g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
        {
            USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
        }
    }
}

/**
  * @brief    Reset software flags
  *
  * @param    None
  *
  * @return   None
  *
  * @details  This function resets all variables for protocol and resets USB device address to 0.
  *
  */
void USBD_SwReset(void)
{
    uint32_t i;
    /* Reset all variables for protocol */
    g_usbd_CtrlInPointer = 0;
    g_usbd_CtrlInSize = 0ul;
    g_usbd_CtrlOutPointer = 0;
    g_usbd_CtrlOutSize = 0ul;
    g_usbd_CtrlOutSizeLimit = 0ul;
    g_u32EpStallLock = 0ul;
    memset(g_usbd_SetupPacket, 0, 8ul);

    /* Reset PID DATA0 */
    for (i = 0ul; i < USBD_MAX_EP; i++)
    {
        USBD->EP.CFG &= ~USBD_CFG_DSQSYNC_Msk;
    }

    /* Reset USB device address */
    USBD_SET_ADDR(0ul);
}

/**
* @brief       USBD Set Vendor Request
*
* @param[in]   pfnVendorReq    Vendor Request Callback Function
*
* @return      None
*
* @details     This function is used to set USBD vendor request callback function
*/
//void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq)
//{
//    g_usbd_pfnVendorRequest = pfnVendorReq;
//}

/**
* @brief       The callback function which called when get SET CONFIGURATION request
*
* @param[in]   pfnSetConfigCallback    Callback function pointer for SET CONFIGURATION request
*
* @return      None
*
* @details     This function is used to set the callback function which will be called at SET CONFIGURATION request.
*/
void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)
{
    g_usbd_pfnSetConfigCallback = pfnSetConfigCallback;
}


/**
* @brief       EP stall lock function to avoid stall clear by USB SET FEATURE request.
*
* @param[in]   u32EpBitmap    Use bitmap to select which endpoints will be locked
*
* @return      None
*
* @details     This function is used to lock relative endpoint to avoid stall clear by SET FEATURE request.
*              If ep stall locked, user needs to reset USB device or re-configure device to clear it.
*/
void USBD_LockEpStall(uint32_t u32EpBitmap)
{
    g_u32EpStallLock = u32EpBitmap;
}


/*@}*/ /* end of group USBD_EXPORTED_FUNCTIONS */

/*@}*/ /* end of group USBD_Driver */

/*@}*/ /* end of group Standard_Driver */

#ifdef __cplusplus
}
#endif

/*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/

使用特权

评论回复
7
goodluck09876|  楼主 | 2021-1-8 19:27 | 只看该作者
/******************************************************************************//**
* @file     dfu_transfer.c
* @version  V1.00
* @brief    M480 series USBD DFU transfer sample file
*
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/

/*!<Includes */
#include <stdio.h>
#include <string.h>
#include "M480.h"
#include "dfu_transfer.h"
#include "fmc_user.h"

extern uint32_t g_apromSize;
#define APROM_BLOCK_NUM         ((g_apromSize/TRANSFER_SIZE)-1)

uint32_t command_Count = 0;
uint8_t manifest_state = MANIFEST_COMPLETE;
dfu_status_struct dfu_status;
s_prog_struct prog_struct __attribute__((aligned(4))) = {{0}, 0, 0, APP_LOADED_ADDR};

void USBD_IRQHandler(void)
{
    uint32_t u32IntSts = USBD_GET_INT_FLAG();
    uint32_t u32State = USBD_GET_BUS_STATE();

    //------------------------------------------------------------------
    if (u32IntSts & USBD_INTSTS_FLDET)
    {
        // Floating detect
        USBD_CLR_INT_FLAG(USBD_INTSTS_FLDET);

        if (USBD_IS_ATTACHED())
        {
            /* USB Plug In */
            USBD_ENABLE_USB();
        }
        else
        {
            /* USB Un-plug */
            USBD_DISABLE_USB();
        }
    }

    //------------------------------------------------------------------
    if (u32IntSts & USBD_INTSTS_BUS)
    {
        /* Clear event flag */
        USBD_CLR_INT_FLAG(USBD_INTSTS_BUS);

        if (u32State & USBD_STATE_USBRST)
        {
            /* Bus reset */
            USBD_ENABLE_USB();
            USBD_SwReset();
        }

        if (u32State & USBD_STATE_SUSPEND)
        {
            /* Enable USB but disable PHY */
            USBD_DISABLE_PHY();
        }

        if (u32State & USBD_STATE_RESUME)
        {
            /* Enable USB and enable PHY */
            USBD_ENABLE_USB();
        }

    }

    if (u32IntSts & USBD_INTSTS_NEVWKIF_Msk)
    {
        /*Clear no-event wake up interrupt */
        USBD_CLR_INT_FLAG(USBD_INTSTS_NEVWKIF_Msk);
        /*
           TODO: Implement the function that will be executed when device is woken by non-USB event.
        */
    }

    //------------------------------------------------------------------
    if (u32IntSts & USBD_INTSTS_USB)
    {
        // USB event
        if (u32IntSts & USBD_INTSTS_SETUP)
        {
            // Setup packet
            /* Clear event flag */
            USBD_CLR_INT_FLAG(USBD_INTSTS_SETUP);

            /* Clear the data IN/OUT ready flag of control end-points */
            USBD_STOP_TRANSACTION(EP0);
            USBD_STOP_TRANSACTION(EP1);

            USBD_ProcessSetupPacket();
        }

        // EP events
        if (u32IntSts & USBD_INTSTS_EP0)
        {
            /* Clear event flag */
            USBD_CLR_INT_FLAG(USBD_INTSTS_EP0);
            // control IN
            USBD_CtrlIn();
        }

        if (u32IntSts & USBD_INTSTS_EP1)
        {
            /* Clear event flag */
            USBD_CLR_INT_FLAG(USBD_INTSTS_EP1);

            // control OUT
            USBD_CtrlOut();
        }
    }
}


/*--------------------------------------------------------------------------*/
/**
  * @brief  USBD Endpoint Config.
  * @param  None.
  * @retval None.
  */

void DFU_Init(void)
{
    /* Init setup packet buffer */
    /* Buffer range for setup packet -> [0 ~ 0x7] */
    USBD->STBUFSEG = SETUP_BUF_BASE;

    /*****************************************************/
    /* EP0 ==> control IN endpoint, address 0 */
    USBD_CONFIG_EP(EP0, USBD_CFG_CSTALL | USBD_CFG_EPMODE_IN | 0);
    /* Buffer range for EP0 */
    USBD_SET_EP_BUF_ADDR(EP0, EP0_BUF_BASE);

    /* EP1 ==> control OUT endpoint, address 0 */
    USBD_CONFIG_EP(EP1, USBD_CFG_CSTALL | USBD_CFG_EPMODE_OUT | 0);
    /* Buffer range for EP1 */
    USBD_SET_EP_BUF_ADDR(EP1, EP1_BUF_BASE);

    /* restore device default state */
    dfu_status.bStatus = STATUS_OK;
    dfu_status.bState = STATE_dfuIDLE;

    prog_struct.block_num = 0;
    prog_struct.data_len = 0;

}


void DFU_ClassRequest(void)
{
    uint8_t buf[8];
    uint32_t wValue, wLength;

    USBD_GetSetupPacket(buf);

    wValue  = buf[3] << 8 | buf[2];
    wLength = buf[7] << 8 | buf[6];

    if (buf[0] & 0x80)   /* request data transfer direction */
    {
        switch (buf[1])
        {
            case DFU_GETSTATUS:
            {
                if (dfu_status.bState == STATE_dfuDNLOAD_SYNC)
                {
                    command_Count++;

                    if (command_Count == 5)
                    {
                        dfu_status.bState = STATE_dfuDNLOAD_IDLE;

                        WriteData(prog_struct.block_num * TRANSFER_SIZE, (prog_struct.block_num * TRANSFER_SIZE) + prog_struct.data_len, (uint32_t *)prog_struct.buf);
                        //dfu_status.bStatus = STATUS_errWRITE;

                        command_Count = 0;
                    }
                }

                if (dfu_status.bState == STATE_dfuDNLOAD_IDLE)
                {
                    command_Count++;

                    if (command_Count == 5)
                    {
                        dfu_status.bState = STATE_dfuMANIFEST_SYNC;
                        command_Count = 0;
                    }
                }

                if (dfu_status.bState == STATE_dfuMANIFEST_SYNC)
                {
                    command_Count++;

                    if (command_Count == 5)
                    {
                        dfu_status.bState = STATE_dfuIDLE;
                        command_Count = 0;
                    }
                }

                USBD_PrepareCtrlIn((uint8_t *)&dfu_status.bStatus, 6);
                USBD_PrepareCtrlOut(0, 0);
                break;
            }

            case DFU_GETSTATE:
            {
                USBD_PrepareCtrlIn((uint8_t *)&dfu_status.bState, 1);
                USBD_PrepareCtrlOut(0, 0);
                break;
            }

            case DFU_UPLOAD:
            {
                if (dfu_status.bState == STATE_dfuIDLE || dfu_status.bState == STATE_dfuUPLOAD_IDLE)
                {
                    if (wLength <= 0)
                    {
                        dfu_status.bState = STATE_dfuIDLE;
                        return;
                    }
                    else
                    {
                        if (dfu_status.bState == STATE_dfuIDLE)
                        {
                            dfu_status.bState = STATE_dfuUPLOAD_IDLE;
                        }

                        if (wValue > APROM_BLOCK_NUM)
                        {
                            dfu_status.bState = STATE_dfuIDLE;
                            USBD_PrepareCtrlIn(0, 0);
                            USBD_PrepareCtrlOut(0, 0);
                            break;
                        }

                        ReadData(wValue * TRANSFER_SIZE, (wValue * TRANSFER_SIZE) + wLength, (uint32_t *)prog_struct.buf);
                        USBD_PrepareCtrlIn((uint8_t *)prog_struct.buf, wLength);
                    }

                    USBD_PrepareCtrlOut(0, 0);
                }

                break;
            }

            default:
            {
                // Stall
                /* Setup error, stall the device */
                USBD_SetStall(0);
                break;
            }
        }
    }
    else
    {
        switch (buf[1])
        {
            case DFU_DETACH:
            {
                switch (dfu_status.bState)
                {
                    case STATE_dfuIDLE:
                    case STATE_dfuDNLOAD_SYNC:
                    case STATE_dfuDNLOAD_IDLE:
                    case STATE_dfuMANIFEST_SYNC:
                    case STATE_dfuUPLOAD_IDLE:
                        dfu_status.bStatus = STATUS_OK;
                        dfu_status.bState = STATE_dfuIDLE;
                        dfu_status.iString = 0; /* iString */
                        prog_struct.block_num = 0;
                        prog_struct.data_len = 0;
                        break;

                    default:
                        break;
                }

            }

            case DFU_DNLOAD:
            {
                switch (dfu_status.bState)
                {
                    case STATE_dfuIDLE:
                    case STATE_dfuDNLOAD_IDLE:
                        if (wLength > 0)
                        {
                            /* update the global length and block number */
                            prog_struct.block_num = wValue;
                            prog_struct.data_len = wLength;
                            dfu_status.bState = STATE_dfuDNLOAD_SYNC;

                        }
                        else
                        {
                            manifest_state = MANIFEST_IN_PROGRESS;
                            dfu_status.bState = STATE_dfuMANIFEST_SYNC;

                        }

                        /* enable EP0 prepare receive the buffer */
                        USBD_PrepareCtrlOut((uint8_t *)prog_struct.buf, wLength);
                        USBD_PrepareCtrlIn(0, 0);
                        break;
                }

                break;
            }


            case DFU_CLRSTATUS:
            {
                //  if (STATE_dfuERROR == dfu_status.bState) {
                dfu_status.bStatus = STATUS_OK;
                dfu_status.bState = STATE_dfuIDLE;
                // } //else {
                /* state Error */
                // dfu_status.bStatus = STATUS_errUNKNOWN;
                // dfu_status.bState = STATE_dfuERROR;
                // }

                dfu_status.iString = 0; /* iString: index = 0 */
                break;

            }


            case DFU_ABORT:
            {
                switch (dfu_status.bState)
                {
                    case STATE_dfuIDLE:
                    case STATE_dfuDNLOAD_SYNC:
                    case STATE_dfuDNLOAD_IDLE:
                    case STATE_dfuMANIFEST_SYNC:
                    case STATE_dfuUPLOAD_IDLE:
                        dfu_status.bStatus = STATUS_OK;
                        dfu_status.bState = STATE_dfuIDLE;
                        dfu_status.iString = 0; /* iString: index = 0 */

                        prog_struct.block_num = 0;
                        prog_struct.data_len = 0;
                        break;

                    default:
                        break;
                }

            }


            default:
            {
                /* Setup error, stall the device */
                USBD_SetStall(0);
                break;
            }

        }

    }
}

使用特权

评论回复
8
goodluck09876|  楼主 | 2021-1-8 19:28 | 只看该作者
感觉这个很复杂……

用起来很难啊!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

220

主题

5843

帖子

21

粉丝