MindSDK_MM32F3270/driver_examples/usb/usb_basic/main.c
Yilin Sun 6a70c509d4 Initial MM32F3270 SDK.
Signed-off-by: Yilin Sun <imi415@imi.moe>
2023-03-27 17:11:47 +08:00

248 lines
8.6 KiB
C

/*
* Copyright 2021 MindMotion Microelectronics Co., Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "board_init.h"
#include "hal_usb.h"
#include "app_usb_desc.h"
/*
* Macros.
*/
/*
* Variables.
*/
/* BOARD_USB_PORT buffer descriptor table buffer. */
__attribute__((aligned(512u))) static USB_BufDespTable_Type usb_bd_tbl;
/* setup Packet Buffer, be used for receive setup packet. */
static uint8_t app_usb_setup_buffer[8u];
/* xfer Buffer, be used for xfer packet. */
static uint8_t app_usb_xfer_buffer[64u];
/* be used for remember BOARD_USB_PORT addr before set addr in BOARD_USB_PORT. */
static uint8_t app_usb_device_addr;
/* bd index flag, be used to recorgnize which bd can be used. */
static uint32_t app_usb_bd_oddeven[2u];
/*
* Declerations.
*/
void app_usb_init(void);
/*
* Functions.
*/
int main(void)
{
BOARD_Init();
printf("USB basic example.\r\n");
app_usb_init();
while (1)
{
}
}
void app_usb_init(void)
{
memset(&usb_bd_tbl, 0, sizeof(usb_bd_tbl));
USB_Device_Init_Type usb_init;
usb_init.BufDespTable_Addr = (uint32_t)&usb_bd_tbl; /* set bdt addr. */
USB_InitDevice(BOARD_USB_PORT, &usb_init); /* enable BOARD_USB_PORT. */
USB_Enable(BOARD_USB_PORT, true);
NVIC_ClearPendingIRQ(BOARD_USB_IRQn);
USB_EnableInterrupts(BOARD_USB_PORT, USB_INT_RESET, true); /* enable interrupts. */
USB_EnableInterrupts(BOARD_USB_PORT, USB_INT_TOKENDONE, true); /* enable interrupts. */
USB_EnableInterrupts(BOARD_USB_PORT, USB_INT_STALL, true); /* enable interrupts. */
NVIC_SetPriority(BOARD_USB_IRQn, 3u);
NVIC_EnableIRQ(BOARD_USB_IRQn);
}
/* BOARD_USB_PORT setup handler. */
void app_usb_setup_handler(void)
{
uint16_t len = 0;
if ( USB_SETUP_DESC_GETDESC == app_usb_setup_buffer[1] ) /* BOARD_USB_PORT std req code 6: get descriptor. */
{
if ( USB_SETUP_DESC_GETDESC_DEVDESC == (app_usb_setup_buffer[3] ) ) /* desc type 1: device desc. */
{
memcpy( app_usb_xfer_buffer, usb_dev_desc, sizeof(usb_dev_desc) );
len = sizeof(usb_dev_desc);
}
else if ( USB_SETUP_DESC_GETDESC_CFGDESC == (app_usb_setup_buffer[3] ) ) /* desc type 2: configuration desc. */
{
memcpy( app_usb_xfer_buffer, usb_conf_desc, sizeof(usb_conf_desc) );
len = sizeof(usb_conf_desc);
}
else if( USB_SETUP_DESC_GETDESC_STRDESC == ( app_usb_setup_buffer[3] ) ) /* desc type 3: string desc. */
{
if( USB_SETUP_DESC_GETDESC_STRDESC_LANGUAGEID == ( app_usb_setup_buffer[2] ) ) /* language id. */
{
memcpy( app_usb_xfer_buffer, usb_language_id, sizeof(usb_language_id) );
len = sizeof(usb_language_id);
}
else if( USB_SETUP_DESC_GETDESC_STRDESC_MANUFACTURER == (app_usb_setup_buffer[2] ) ) /* manufacturer. */
{
memcpy( app_usb_xfer_buffer, usb_str_desc, sizeof(usb_str_desc) );
len = sizeof(usb_str_desc);
}
else if( USB_SETUP_DESC_GETDESC_STRDESC_PRODUCT == (app_usb_setup_buffer[2] ) ) /* product. */
{
memcpy( app_usb_xfer_buffer, usb_str_desc, sizeof(usb_str_desc) );
len = sizeof(usb_str_desc);
}
else if( USB_SETUP_DESC_GETDESC_STRDESC_SN == ( app_usb_setup_buffer[2] ) ) /* sn. */
{
memcpy( app_usb_xfer_buffer, usb_str_desc, sizeof(usb_str_desc) );
len = sizeof(usb_str_desc);
}
else /* send ZLP. */
{
len = 0;
}
}
else if( USB_SETUP_DESC_GETDESC_DEVQUALIFIER == (app_usb_setup_buffer[3] ) ) /* desc type 3: device qualifier. */
{
USB_EnableEndPointStall(BOARD_USB_PORT, USB_EP_0, true); /* BOARD_USB_PORT HS need, fs mode enter stall status. */
return;
}
else if( USB_SETUP_DESC_GETDESC_REPORTDESC == ( app_usb_setup_buffer[3] ) ) /* desc type 3: report desc. */
{
memcpy( app_usb_xfer_buffer, usb_rpt_desc, sizeof(usb_rpt_desc) );
len = sizeof(usb_rpt_desc);
}
else /* send ZLP. */
{
len = 0;
}
}
else if( USB_SETUP_DESC_SETADDR == app_usb_setup_buffer[1] ) /* get BOARD_USB_PORT device addr from host. */
{
app_usb_device_addr = app_usb_setup_buffer[2];
len = 0;
}
else if( USB_SETUP_DESC_SETCFG == app_usb_setup_buffer[1] ) /* enable EP1. */
{
USB_EnableEndPoint(BOARD_USB_PORT, 1, USB_EndPointMode_Bulk, true);
len = 0;
}
else if(USB_SETUP_DESC_SETIDEL == app_usb_setup_buffer[1] ) /* send ZLP. */
{
len = 0;
}
/* if buffer size more than std req need, size = need. */
if(len > ( ( (uint16_t)app_usb_setup_buffer[7] )<<8) + app_usb_setup_buffer[6] )
{
len = ( ( (uint16_t)app_usb_setup_buffer[7] )<<8) + app_usb_setup_buffer[6];
}
if(len != 0)
{
/* ready for receive ZLP from host. */
USB_BufDesp_Xfer(&usb_bd_tbl.Index[app_usb_bd_oddeven[0u] ^ 1u], 1u, app_usb_setup_buffer, sizeof(app_usb_setup_buffer) );
USB_BufDesp_Xfer(&usb_bd_tbl.Index[app_usb_bd_oddeven[0u] ], 1u, app_usb_setup_buffer, sizeof(app_usb_setup_buffer) );
}
else
{
/* ready for receive setup packet. */
USB_BufDesp_Xfer(&usb_bd_tbl.Index[app_usb_bd_oddeven[0u]], 1u, app_usb_setup_buffer, sizeof(app_usb_setup_buffer) );
}
/* send data. */
USB_BufDesp_Xfer(&usb_bd_tbl.Index[app_usb_bd_oddeven[1u]], 1u, app_usb_xfer_buffer, len);
}
/* tokdne handler. */
void app_usb_tokdne_handler(void)
{
/* get something information. */
uint32_t ep_index = USB_GetEndPointIndex(BOARD_USB_PORT); /* endpoint index. */
USB_BufDesp_OddEven_Type bd_oddeven = USB_GetBufDespOddEven(BOARD_USB_PORT); /* odd_even. */
USB_BufDesp_Type *bd = USB_GetBufDesp(BOARD_USB_PORT); /* which bd xfer data done. */
USB_TokenPid_Type token = USB_BufDesp_GetTokenPid(bd); /* token pid. */
USB_BufDesp_Reset(bd); /* reset the bd. */
USB_ClearInterruptStatus(BOARD_USB_PORT, USB_INT_TOKENDONE); /* clear the interrupt flag. */
if(USB_TokenPid_IN == token)
{
/* oddeven change. */
app_usb_bd_oddeven[ (ep_index << 1u) + 1u] = 2u + (bd_oddeven ^ 1u);
}
else
{
/* oddeven change. */
app_usb_bd_oddeven[ (ep_index << 1u) ] = bd_oddeven ^ 1u;
}
if(USB_TokenPid_SETUP == token)
{
/* setup process. */
app_usb_setup_handler();
USB_EnableSuspend(BOARD_USB_PORT, false);
}
else if(0u != app_usb_device_addr && 0u == USB_BufDesp_GetPacketSize(bd) )
{
/* set BOARD_USB_PORT address after recv device addr from Host and send ZLP for Host. */
USB_SetDeviceAddr(BOARD_USB_PORT, app_usb_device_addr);
app_usb_device_addr = 0u;
}
}
/* reset handler. */
void app_usb_reset_handler(void *buffer, uint8_t len)
{
/* reset the odd_even flag. */
app_usb_bd_oddeven[0u] = 0u;
app_usb_bd_oddeven[1u] = 2u;
/* reset bd oddeven. */
USB_EnableOddEvenReset(BOARD_USB_PORT, true);
USB_EnableOddEvenReset(BOARD_USB_PORT, false);
/* device addr = 0. */
USB_SetDeviceAddr(BOARD_USB_PORT, 0x00u);
app_usb_device_addr = 0;
for (uint32_t i = 0u; i < 16u; i++)
{
/* disable all end point. */
USB_EnableEndPoint(BOARD_USB_PORT, i, USB_EndPointMode_NULL, false);
}
/* enable ep0. */
USB_EnableEndPoint(BOARD_USB_PORT, 0u, USB_EndPointMode_Control, true);
/* prepare for recv setup packet. */
USB_BufDesp_Xfer(&usb_bd_tbl.Index[app_usb_bd_oddeven[0u] ], 1u, buffer, len);
}
/* BOARD_USB_PORT interrupt handler. */
void BOARD_USB_IRQHandler(void)
{
/* get interrupt status. */
uint32_t flag = USB_GetInterruptStatus(BOARD_USB_PORT);
if (flag & USB_INT_RESET)
{ /* BOARD_USB_PORT reset. */
USB_ClearInterruptStatus(BOARD_USB_PORT, USB_INT_RESET);
app_usb_reset_handler( app_usb_setup_buffer,sizeof(app_usb_setup_buffer) );
return;
}
if (flag & USB_INT_TOKENDONE)
{ /* BOARD_USB_PORT token done. */
app_usb_tokdne_handler();
return;
}
if (flag & USB_INT_STALL)
{ /* BOARD_USB_PORT stall. */
USB_ClearInterruptStatus(BOARD_USB_PORT, USB_INT_STALL);
USB_EnableEndPointStall(BOARD_USB_PORT, USB_EP_0, false); /* get qualifier will make ep0 stall, clear it. */
USB_BufDesp_Xfer(&usb_bd_tbl.Index[app_usb_bd_oddeven[0u] ], 1, app_usb_setup_buffer, sizeof(app_usb_setup_buffer) );
return;
}
}
/* EOF. */