first submission
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,71 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : usbhd_host_km.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2020/04/30
|
||||
* Description : This file contains all the functions prototypes for the USB
|
||||
* firmware library.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __APP_KM_H
|
||||
#define __APP_KM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Header File */
|
||||
#include "stdint.h"
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Macro Definition */
|
||||
|
||||
/* General */
|
||||
#define DEF_COM_BUF_LEN 1024
|
||||
|
||||
/* USB HID Device Interface Type */
|
||||
#define DEC_KEY 0x01
|
||||
#define DEC_MOUSE 0x02
|
||||
#define DEC_UNKNOW 0xFF
|
||||
|
||||
/* USB Keyboard Lighting Key */
|
||||
#define DEF_KEY_NUM 0x53
|
||||
#define DEF_KEY_CAPS 0x39
|
||||
#define DEF_KEY_SCROLL 0x47
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Variable Declaration */
|
||||
extern uint8_t DevDesc_Buf[ ];
|
||||
extern uint8_t Com_Buf[ ];
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Function Declaration */
|
||||
extern void TIM3_Init( uint16_t arr, uint16_t psc );
|
||||
extern void USBH_AnalyseType( uint8_t *pdev_buf, uint8_t *pcfg_buf, uint8_t *ptype );
|
||||
extern uint8_t USBH_EnumRootDevice( void );
|
||||
extern uint8_t KM_AnalyzeConfigDesc( uint8_t index, uint8_t ep0_size );
|
||||
extern void KM_AnalyzeHidReportDesc( uint8_t index, uint8_t intf_num );
|
||||
extern uint8_t KM_DealHidReportDesc( uint8_t index, uint8_t ep0_size );
|
||||
extern uint8_t USBH_EnumHidDevice( uint8_t index, uint8_t ep0_size );
|
||||
extern uint8_t HUB_AnalyzeConfigDesc( uint8_t index );
|
||||
extern uint8_t HUB_Port_PreEnum1( uint8_t hub_port, uint8_t *pbuf );
|
||||
extern uint8_t HUB_Port_PreEnum2( uint8_t hub_port, uint8_t *pbuf );
|
||||
extern uint8_t HUB_CheckPortSpeed( uint8_t hub_port, uint8_t *pbuf );
|
||||
extern uint8_t USBH_EnumHubPortDevice( uint8_t hub_port, uint8_t *paddr, uint8_t *ptype );
|
||||
extern void KB_AnalyzeKeyValue( uint8_t index, uint8_t intf_num, uint8_t *pbuf, uint16_t len );
|
||||
extern uint8_t KB_SetReport( uint8_t index, uint8_t ep0_size, uint8_t intf_num );
|
||||
extern void USBH_MainDeal( void );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,675 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : ch32f20x_usbfs_host.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/09/01
|
||||
* Description : USB full-speed port host operation functions.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Header File */
|
||||
#include "usb_host_config.h"
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Variable Definition */
|
||||
__attribute__((aligned(4))) uint8_t USBFS_RX_Buf[ USBFS_MAX_PACKET_SIZE ]; // IN, must even address
|
||||
__attribute__((aligned(4))) uint8_t USBFS_TX_Buf[ USBFS_MAX_PACKET_SIZE ]; // OUT, must even address
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFS_RCC_Init
|
||||
*
|
||||
* @brief Set USB port clock.
|
||||
* Note: If the SystemCoreClock is selected as the USB clock source,
|
||||
* only the frequency specified below can be used.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void USBFS_RCC_Init( void )
|
||||
{
|
||||
if( SystemCoreClock == 144000000 )
|
||||
{
|
||||
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div3 );
|
||||
}
|
||||
else if( SystemCoreClock == 96000000 )
|
||||
{
|
||||
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div2 );
|
||||
}
|
||||
else if( SystemCoreClock == 48000000 )
|
||||
{
|
||||
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div1 );
|
||||
}
|
||||
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_OTG_FS, ENABLE );
|
||||
}
|
||||
/*********************************************************************
|
||||
* @fn USBFS_Host_Init
|
||||
*
|
||||
* @brief Initialize USB port host configuration.
|
||||
*
|
||||
* @param sta - ENABLE or DISABLE
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void USBFS_Host_Init( FunctionalState sta )
|
||||
{
|
||||
if( sta == ENABLE )
|
||||
{
|
||||
/* Reset USB module */
|
||||
USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
|
||||
Delay_Us( 10 );
|
||||
USBOTG_H_FS->BASE_CTRL = 0;
|
||||
|
||||
/* Initialize USB host configuration */
|
||||
USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN;
|
||||
USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN;
|
||||
USBOTG_H_FS->HOST_RX_DMA = (uint32_t)USBFS_RX_Buf;
|
||||
USBOTG_H_FS->HOST_TX_DMA = (uint32_t)USBFS_TX_Buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
|
||||
Delay_Us( 10 );
|
||||
USBOTG_H_FS->BASE_CTRL = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_CheckRootHubPortStatus
|
||||
*
|
||||
* @brief Check the current status of the USB port in combination with
|
||||
* the saved status of the root device connected to this port.
|
||||
*
|
||||
* @para dev_sta: The saved status of the root device.
|
||||
*
|
||||
* @return The current status of the port.
|
||||
*/
|
||||
uint8_t USBFSH_CheckRootHubPortStatus( uint8_t dev_sta )
|
||||
{
|
||||
if( USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT )// Check that there is a device connection or disconnection event on the port
|
||||
{
|
||||
USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT; // Clear flag
|
||||
if( USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH ) // Check that there is a device connection to the port
|
||||
{
|
||||
if( ( dev_sta == ROOT_DEV_DISCONNECT ) || ( ( dev_sta != ROOT_DEV_FAILED ) && ( USBFSH_CheckRootHubPortEnable( ) == 0x00 ) ) )
|
||||
{
|
||||
return ROOT_DEV_CONNECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ROOT_DEV_FAILED;
|
||||
}
|
||||
}
|
||||
else // Check that there is no device connection to the port
|
||||
{
|
||||
return ROOT_DEV_DISCONNECT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ROOT_DEV_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_CheckRootHubPortEnable
|
||||
*
|
||||
* @brief Check the enable status of the USB port.
|
||||
* Note: This bit is automatically cleared when the device is disconnected.
|
||||
*
|
||||
* @return The current enable status of the port.
|
||||
*/
|
||||
uint8_t USBFSH_CheckRootHubPortEnable( void )
|
||||
{
|
||||
return ( USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_CheckRootHubPortSpeed
|
||||
*
|
||||
* @brief Check the speed of the USB port.
|
||||
*
|
||||
* @return The current speed of the port.
|
||||
*/
|
||||
uint8_t USBFSH_CheckRootHubPortSpeed( void )
|
||||
{
|
||||
return ( USBOTG_H_FS->MIS_ST & USBFS_UMS_DM_LEVEL? USB_LOW_SPEED: USB_FULL_SPEED );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_SetSelfAddr
|
||||
*
|
||||
* @brief Set the USB device address.
|
||||
*
|
||||
* @para addr: USB device address.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void USBFSH_SetSelfAddr( uint8_t addr )
|
||||
{
|
||||
USBOTG_H_FS->DEV_ADDR = ( USBOTG_H_FS->DEV_ADDR & USBFS_UDA_GP_BIT ) | ( addr & USBFS_USB_ADDR_MASK );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_SetSelfSpeed
|
||||
*
|
||||
* @brief Set USB speed.
|
||||
*
|
||||
* @para speed: USB speed.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void USBFSH_SetSelfSpeed( uint8_t speed )
|
||||
{
|
||||
if( speed == USB_FULL_SPEED )
|
||||
{
|
||||
USBOTG_H_FS->BASE_CTRL &= ~USBFS_UC_LOW_SPEED;
|
||||
USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED;
|
||||
USBOTG_H_FS->HOST_SETUP &= ~USBFS_UH_PRE_PID_EN;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBOTG_H_FS->BASE_CTRL |= USBFS_UC_LOW_SPEED;
|
||||
USBOTG_H_FS->HOST_CTRL |= USBFS_UH_LOW_SPEED;
|
||||
USBOTG_H_FS->HOST_SETUP |= USBFS_UH_PRE_PID_EN;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_ResetRootHubPort
|
||||
*
|
||||
* @brief Reset USB port.
|
||||
*
|
||||
* @para mod: Reset host port operating mode.
|
||||
* 0 -> reset and wait end
|
||||
* 1 -> begin reset
|
||||
* 2 -> end reset
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void USBFSH_ResetRootHubPort( uint8_t mode )
|
||||
{
|
||||
USBFSH_SetSelfAddr( 0x00 );
|
||||
USBFSH_SetSelfSpeed( USB_FULL_SPEED );
|
||||
|
||||
if( mode <= 1 )
|
||||
{
|
||||
USBOTG_H_FS->HOST_CTRL |= USBFS_UH_BUS_RESET; // Start reset
|
||||
}
|
||||
if( mode == 0 )
|
||||
{
|
||||
Delay_Ms( DEF_BUS_RESET_TIME ); // Reset time from 10mS to 20mS
|
||||
}
|
||||
if( mode != 1 )
|
||||
{
|
||||
USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_BUS_RESET; // End reset
|
||||
}
|
||||
Delay_Ms( 2 );
|
||||
|
||||
if( USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT )
|
||||
{
|
||||
if( USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH )
|
||||
{
|
||||
USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_EnableRootHubPort
|
||||
*
|
||||
* @brief Enable USB host port.
|
||||
*
|
||||
* @para *pspeed: USB speed.
|
||||
*
|
||||
* @return Operation result of the enabled port.
|
||||
*/
|
||||
uint8_t USBFSH_EnableRootHubPort( uint8_t *pspeed )
|
||||
{
|
||||
if( USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH )
|
||||
{
|
||||
if( USBFSH_CheckRootHubPortEnable( ) == 0x00 )
|
||||
{
|
||||
*pspeed = USBFSH_CheckRootHubPortSpeed( );
|
||||
if( *pspeed == USB_LOW_SPEED )
|
||||
{
|
||||
USBFSH_SetSelfSpeed( USB_LOW_SPEED );
|
||||
}
|
||||
}
|
||||
USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN;
|
||||
USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN;
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
return ERR_USB_DISCON;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_Transact
|
||||
*
|
||||
* @brief Perform USB transaction.
|
||||
*
|
||||
* @para endp_pid: Token PID.
|
||||
* endp_tog: Toggle
|
||||
* timeout: Timeout time.
|
||||
*
|
||||
* @return USB transfer result.
|
||||
*/
|
||||
uint8_t USBFSH_Transact( uint8_t endp_pid, uint8_t endp_tog, uint16_t timeout )
|
||||
{
|
||||
uint8_t r, trans_retry;
|
||||
uint16_t i;
|
||||
|
||||
USBOTG_H_FS->HOST_TX_CTRL = USBOTG_H_FS->HOST_RX_CTRL = endp_tog;
|
||||
trans_retry = 0;
|
||||
do
|
||||
{
|
||||
USBOTG_H_FS->HOST_EP_PID = endp_pid; // Specify token PID and endpoint number
|
||||
USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; // Allow transfer
|
||||
for( i = DEF_WAIT_USB_TRANSFER_CNT; ( i != 0 ) && ( ( USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER ) == 0 ); i-- )
|
||||
{
|
||||
Delay_Us( 1 ); // Delay for USB transfer
|
||||
}
|
||||
USBOTG_H_FS->HOST_EP_PID = 0x00; // Stop USB transfer
|
||||
if( ( USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER ) == 0 )
|
||||
{
|
||||
return ERR_USB_UNKNOWN;
|
||||
}
|
||||
else // Complete transfer
|
||||
{
|
||||
if( USBOTG_H_FS->INT_ST & USBFS_UIS_TOG_OK )
|
||||
{
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
r = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; // Response status of current USB transaction
|
||||
if( r == USB_PID_STALL )
|
||||
{
|
||||
return ( r | ERR_USB_TRANSFER );
|
||||
}
|
||||
if( r == USB_PID_NAK )
|
||||
{
|
||||
if( timeout == 0 )
|
||||
{
|
||||
return ( r | ERR_USB_TRANSFER );
|
||||
}
|
||||
if( timeout < 0xFFFF )
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
--trans_retry;
|
||||
}
|
||||
else switch ( endp_pid >> 4 )
|
||||
{
|
||||
case USB_PID_SETUP:
|
||||
case USB_PID_OUT:
|
||||
if( r )
|
||||
{
|
||||
return ( r | ERR_USB_TRANSFER );
|
||||
}
|
||||
break;
|
||||
case USB_PID_IN:
|
||||
if( ( r == USB_PID_DATA0 ) || ( r == USB_PID_DATA1 ) )
|
||||
{
|
||||
;
|
||||
}
|
||||
else if( r )
|
||||
{
|
||||
return ( r | ERR_USB_TRANSFER );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ERR_USB_UNKNOWN;
|
||||
}
|
||||
}
|
||||
Delay_Us( 20 );
|
||||
|
||||
if( USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT )
|
||||
{
|
||||
Delay_Us( 200 );
|
||||
|
||||
if( USBFSH_CheckRootHubPortEnable( ) == 0x00 )
|
||||
{
|
||||
return ERR_USB_DISCON; // USB device disconnect event
|
||||
}
|
||||
else
|
||||
{
|
||||
USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT;
|
||||
}
|
||||
}
|
||||
}while( ++trans_retry < 10 );
|
||||
|
||||
return ERR_USB_TRANSFER; // Reply timeout
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_CtrlTransfer
|
||||
*
|
||||
* @brief USB host control transfer.
|
||||
*
|
||||
* @para ep0_size: Device endpoint 0 size
|
||||
* pbuf: Data buffer
|
||||
* plen: Data length
|
||||
*
|
||||
* @return USB control transfer result.
|
||||
*/
|
||||
uint8_t USBFSH_CtrlTransfer( uint8_t ep0_size, uint8_t *pbuf, uint16_t *plen )
|
||||
{
|
||||
uint8_t s;
|
||||
uint16_t rem_len, rx_len, rx_cnt, tx_cnt;
|
||||
|
||||
Delay_Us( 100 );
|
||||
if( plen )
|
||||
{
|
||||
*plen = 0;
|
||||
}
|
||||
USBOTG_H_FS->HOST_TX_LEN = sizeof( USB_SETUP_REQ );
|
||||
s = USBFSH_Transact( ( USB_PID_SETUP << 4 ) | 0x00, 0x00, DEF_CTRL_TRANS_TIMEOVER_CNT ); // SETUP stage
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
USBOTG_H_FS->HOST_TX_CTRL = USBOTG_H_FS->HOST_RX_CTRL = USBFS_UH_T_TOG | USBFS_UH_R_TOG; // Default DATA1
|
||||
rem_len = pUSBFS_SetupRequest->wLength;
|
||||
if( rem_len && pbuf )
|
||||
{
|
||||
if( pUSBFS_SetupRequest->bRequestType & USB_REQ_TYP_IN )
|
||||
{
|
||||
/* Receive data */
|
||||
while( rem_len )
|
||||
{
|
||||
Delay_Us( 100 );
|
||||
s = USBFSH_Transact( ( USB_PID_IN << 4 ) | 0x00, USBOTG_H_FS->HOST_RX_CTRL, DEF_CTRL_TRANS_TIMEOVER_CNT ); // IN
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
USBOTG_H_FS->HOST_RX_CTRL ^= USBFS_UH_R_TOG;
|
||||
|
||||
rx_len = ( USBOTG_H_FS->RX_LEN < rem_len )? USBOTG_H_FS->RX_LEN : rem_len;
|
||||
rem_len -= rx_len;
|
||||
if( plen )
|
||||
{
|
||||
*plen += rx_len; // The total length of the actual successful transmission and reception
|
||||
}
|
||||
for( rx_cnt = 0; rx_cnt != rx_len; rx_cnt++ )
|
||||
{
|
||||
*pbuf = USBFS_RX_Buf[ rx_cnt ];
|
||||
pbuf++;
|
||||
}
|
||||
|
||||
if( ( USBOTG_H_FS->RX_LEN == 0 ) || ( USBOTG_H_FS->RX_LEN & ( ep0_size - 1 ) ) )
|
||||
{
|
||||
break; // Short package
|
||||
}
|
||||
}
|
||||
USBOTG_H_FS->HOST_TX_LEN = 0; // Status stage is OUT
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send data */
|
||||
while( rem_len )
|
||||
{
|
||||
Delay_Us( 100 );
|
||||
USBOTG_H_FS->HOST_TX_LEN = ( rem_len >= ep0_size )? ep0_size : rem_len;
|
||||
for( tx_cnt = 0; tx_cnt != USBOTG_H_FS->HOST_TX_LEN; tx_cnt++ )
|
||||
{
|
||||
USBFS_TX_Buf[ tx_cnt ] = *pbuf;
|
||||
pbuf++;
|
||||
}
|
||||
s = USBFSH_Transact( USB_PID_OUT << 4 | 0x00, USBOTG_H_FS->HOST_TX_CTRL, DEF_CTRL_TRANS_TIMEOVER_CNT ); // OUT
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
USBOTG_H_FS->HOST_TX_CTRL ^= USBFS_UH_T_TOG;
|
||||
|
||||
rem_len -= USBOTG_H_FS->HOST_TX_LEN;
|
||||
if( plen )
|
||||
{
|
||||
*plen += USBOTG_H_FS->HOST_TX_LEN; // The total length of the actual successful transmission and reception
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Delay_Us( 100 );
|
||||
s = USBFSH_Transact( ( USBOTG_H_FS->HOST_TX_LEN )? ( USB_PID_IN << 4 | 0x00 ) : ( USB_PID_OUT << 4 | 0x00 ), USBFS_UH_R_TOG | USBFS_UH_T_TOG, DEF_CTRL_TRANS_TIMEOVER_CNT ); // STATUS stage
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
if( USBOTG_H_FS->HOST_TX_LEN == 0 )
|
||||
{
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
if( USBOTG_H_FS->RX_LEN == 0 )
|
||||
{
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
return ERR_USB_BUF_OVER;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_GetDeviceDescr
|
||||
*
|
||||
* @brief Get the device descriptor of the USB device.
|
||||
*
|
||||
* @para pep0_size: Device endpoint 0 size
|
||||
* pbuf: Data buffer
|
||||
*
|
||||
* @return The result of getting the device descriptor.
|
||||
*/
|
||||
uint8_t USBFSH_GetDeviceDescr( uint8_t *pep0_size, uint8_t *pbuf )
|
||||
{
|
||||
uint8_t s;
|
||||
uint16_t len;
|
||||
|
||||
*pep0_size = DEFAULT_ENDP0_SIZE;
|
||||
memcpy( pUSBFS_SetupRequest, SetupGetDevDesc, sizeof( USB_SETUP_REQ ) );
|
||||
s = USBFSH_CtrlTransfer( *pep0_size, pbuf, &len );
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
*pep0_size = ( (PUSB_DEV_DESCR)pbuf )->bMaxPacketSize0;
|
||||
if( len < ( (PUSB_SETUP_REQ)SetupGetDevDesc )->wLength )
|
||||
{
|
||||
return ERR_USB_BUF_OVER;
|
||||
}
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_GetConfigDescr
|
||||
*
|
||||
* @brief Get the configuration descriptor of the USB device.
|
||||
*
|
||||
* @para ep0_size: Device endpoint 0 size
|
||||
* pbuf: Data buffer
|
||||
* buf_len: Data buffer length
|
||||
* pcfg_len: The length of the device configuration descriptor
|
||||
*
|
||||
* @return The result of getting the configuration descriptor.
|
||||
*/
|
||||
uint8_t USBFSH_GetConfigDescr( uint8_t ep0_size, uint8_t *pbuf, uint16_t buf_len, uint16_t *pcfg_len )
|
||||
{
|
||||
uint8_t s;
|
||||
|
||||
memcpy( pUSBFS_SetupRequest, SetupGetCfgDesc, sizeof( USB_SETUP_REQ ) );
|
||||
s = USBFSH_CtrlTransfer( ep0_size, pbuf, pcfg_len );
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
if( *pcfg_len < ( (PUSB_SETUP_REQ)SetupGetCfgDesc )->wLength )
|
||||
{
|
||||
return ERR_USB_BUF_OVER;
|
||||
}
|
||||
|
||||
*pcfg_len = ( (PUSB_CFG_DESCR)pbuf )->wTotalLength;
|
||||
if( *pcfg_len > buf_len )
|
||||
{
|
||||
*pcfg_len = buf_len;
|
||||
}
|
||||
memcpy( pUSBFS_SetupRequest, SetupGetCfgDesc, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wLength = *pcfg_len;
|
||||
s = USBFSH_CtrlTransfer( ep0_size, pbuf, pcfg_len );
|
||||
return s;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_GetStrDescr
|
||||
*
|
||||
* @brief Get the string descriptor of the USB device.
|
||||
*
|
||||
* @para ep0_size: Device endpoint 0 size
|
||||
* str_num: Index of string descriptor
|
||||
* pbuf: Data buffer
|
||||
*
|
||||
* @return The result of getting the string descriptor.
|
||||
*/
|
||||
uint8_t USBFSH_GetStrDescr( uint8_t ep0_size, uint8_t str_num, uint8_t *pbuf )
|
||||
{
|
||||
uint8_t s;
|
||||
uint16_t len;
|
||||
|
||||
/* Get the string descriptor of the first 4 bytes */
|
||||
memcpy( pUSBFS_SetupRequest, SetupGetStrDesc, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wValue = ( (uint16_t)USB_DESCR_TYP_STRING << 8 ) | str_num;
|
||||
s = USBFSH_CtrlTransfer( ep0_size, pbuf, &len );
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Get the complete string descriptor */
|
||||
len = pbuf[ 0 ];
|
||||
memcpy( pUSBFS_SetupRequest, SetupGetStrDesc, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wValue = ( (uint16_t)USB_DESCR_TYP_STRING << 8 ) | str_num;
|
||||
pUSBFS_SetupRequest->wLength = len;
|
||||
s = USBFSH_CtrlTransfer( ep0_size, pbuf, &len );
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_SetUsbAddress
|
||||
*
|
||||
* @brief Set USB device address.
|
||||
*
|
||||
* @para ep0_size: Device endpoint 0 size
|
||||
* addr: Device address
|
||||
*
|
||||
* @return The result of setting device address.
|
||||
*/
|
||||
uint8_t USBFSH_SetUsbAddress( uint8_t ep0_size, uint8_t addr )
|
||||
{
|
||||
uint8_t s;
|
||||
|
||||
memcpy( pUSBFS_SetupRequest, SetupSetAddr, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wValue = (uint16_t)addr;
|
||||
s = USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
USBFSH_SetSelfAddr( addr );
|
||||
Delay_Ms( DEF_BUS_RESET_TIME >> 1 ); // Wait for the USB device to complete its operation.
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_SetUsbConfig
|
||||
*
|
||||
* @brief Set USB configuration.
|
||||
*
|
||||
* @para ep0_size: Device endpoint 0 size
|
||||
* cfg: Device configuration value
|
||||
*
|
||||
* @return The result of setting device configuration.
|
||||
*/
|
||||
uint8_t USBFSH_SetUsbConfig( uint8_t ep0_size, uint8_t cfg_val )
|
||||
{
|
||||
memcpy( pUSBFS_SetupRequest, SetupSetConfig, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wValue = (uint16_t)cfg_val;
|
||||
return USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_ClearEndpStall
|
||||
*
|
||||
* @brief Clear endpoint stall.
|
||||
*
|
||||
* @para ep0_size: Device endpoint 0 size
|
||||
* endp_num: Endpoint number.
|
||||
*
|
||||
* @return The result of clearing endpoint stall.
|
||||
*/
|
||||
uint8_t USBFSH_ClearEndpStall( uint8_t ep0_size, uint8_t endp_num )
|
||||
{
|
||||
memcpy( pUSBFS_SetupRequest, SetupClearEndpStall, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wIndex = (uint16_t)endp_num;
|
||||
return USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_GetEndpData
|
||||
*
|
||||
* @brief Get data from USB device input endpoint.
|
||||
*
|
||||
* @para endp_num: Endpoint number
|
||||
* endp_tog: Endpoint toggle
|
||||
* pbuf: Data Buffer
|
||||
* plen: Data length
|
||||
*
|
||||
* @return The result of getting data.
|
||||
*/
|
||||
uint8_t USBFSH_GetEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t *plen )
|
||||
{
|
||||
uint8_t s;
|
||||
|
||||
s = USBFSH_Transact( ( USB_PID_IN << 4 ) | endp_num, *pendp_tog, 0 );
|
||||
if( s == ERR_SUCCESS )
|
||||
{
|
||||
*plen = USBOTG_H_FS->RX_LEN;
|
||||
memcpy( pbuf, USBFS_RX_Buf, *plen );
|
||||
|
||||
*pendp_tog ^= USBFS_UH_R_TOG;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USBFSH_SendEndpData
|
||||
*
|
||||
* @brief Send data to the USB device output endpoint.
|
||||
*
|
||||
* @para endp_num: Endpoint number
|
||||
* endp_tog: Endpoint toggle
|
||||
* pbuf: Data Buffer
|
||||
* len: Data length
|
||||
*
|
||||
* @return The result of sending data.
|
||||
*/
|
||||
uint8_t USBFSH_SendEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t len )
|
||||
{
|
||||
uint8_t s;
|
||||
|
||||
memcpy( USBFS_TX_Buf, pbuf, len );
|
||||
USBOTG_H_FS->HOST_TX_LEN = len;
|
||||
s = USBFSH_Transact( ( USB_PID_OUT << 4 ) | endp_num, *pendp_tog, 0 );
|
||||
if( s == ERR_SUCCESS )
|
||||
{
|
||||
*pendp_tog ^= USBFS_UH_T_TOG;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : ch32v20x_usbfs_host.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : USBOTG full speed host header file
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __CH32V20x_USBFS_HOST_H__
|
||||
#define __CH32V20x_USBFS_HOST_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Header File */
|
||||
#include "ch32v20x.h"
|
||||
#include "ch32v20x_usb.h"
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Macro Definition */
|
||||
|
||||
/* USB Setup Request */
|
||||
#define pUSBFS_SetupRequest ( (PUSB_SETUP_REQ)USBFS_TX_Buf )
|
||||
|
||||
/* USB Buffer Size */
|
||||
#ifndef USBFS_MAX_PACKET_SIZE
|
||||
#define USBFS_MAX_PACKET_SIZE 64
|
||||
#endif
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Constant Definition */
|
||||
#ifndef DEF_USB_GEN_ENUM_CMD
|
||||
#define DEF_USB_GEN_ENUM_CMD
|
||||
/* Get Device Descriptor Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupGetDevDesc[ ] =
|
||||
{
|
||||
USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_DEVICE, 0x00, 0x00, sizeof( USB_DEV_DESCR ), 0x00
|
||||
};
|
||||
|
||||
/* Get Configuration Descriptor Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupGetCfgDesc[ ] =
|
||||
{
|
||||
USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_CONFIG, 0x00, 0x00, 0x04, 0x00
|
||||
};
|
||||
|
||||
/* Get String Descriptor Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupGetStrDesc[ ] =
|
||||
{
|
||||
USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_STRING, 0x09, 0x04, 0x04, 0x00
|
||||
};
|
||||
|
||||
/* Set USB Address Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupSetAddr[ ] =
|
||||
{
|
||||
USB_REQ_TYP_OUT, USB_SET_ADDRESS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Set USB Configuration Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupSetConfig[ ] =
|
||||
{
|
||||
USB_REQ_TYP_OUT, USB_SET_CONFIGURATION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Clear Endpoint STALL Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupClearEndpStall[ ] =
|
||||
{
|
||||
USB_REQ_TYP_OUT | USB_REQ_RECIP_ENDP, USB_CLEAR_FEATURE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Set Device Interface Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupSetInterface[ ] =
|
||||
{
|
||||
USB_REQ_RECIP_INTERF, USB_SET_INTERFACE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Variable Declaration */
|
||||
extern __attribute__((aligned(4))) uint8_t USBFS_RX_Buf[ ];
|
||||
extern __attribute__((aligned(4))) uint8_t USBFS_TX_Buf[ ];
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Function Declaration */
|
||||
extern void USBFS_RCC_Init( void );
|
||||
extern void USBFS_Host_Init( FunctionalState sta );
|
||||
extern uint8_t USBFSH_CheckRootHubPortStatus( uint8_t dev_sta );
|
||||
extern uint8_t USBFSH_CheckRootHubPortEnable( void );
|
||||
extern uint8_t USBFSH_CheckRootHubPortSpeed( void );
|
||||
extern void USBFSH_SetSelfAddr( uint8_t addr );
|
||||
extern void USBFSH_SetSelfSpeed( uint8_t speed );
|
||||
extern void USBFSH_ResetRootHubPort( uint8_t mode );
|
||||
extern uint8_t USBFSH_EnableRootHubPort( uint8_t *pspeed );
|
||||
extern uint8_t USBFSH_Transact( uint8_t endp_pid, uint8_t endp_tog, uint16_t timeout );
|
||||
extern uint8_t USBFSH_CtrlTransfer( uint8_t ep0_size, uint8_t *pbuf, uint16_t *plen );
|
||||
extern uint8_t USBFSH_GetDeviceDescr( uint8_t *pep0_size, uint8_t *pbuf );
|
||||
extern uint8_t USBFSH_GetConfigDescr( uint8_t ep0_size, uint8_t *pbuf, uint16_t buf_len, uint16_t *pcfg_len );
|
||||
extern uint8_t USBFSH_GetStrDescr( uint8_t ep0_size, uint8_t str_num, uint8_t *pbuf );
|
||||
extern uint8_t USBFSH_SetUsbAddress( uint8_t ep0_size, uint8_t addr );
|
||||
extern uint8_t USBFSH_SetUsbConfig( uint8_t ep0_size, uint8_t cfg_val );
|
||||
extern uint8_t USBFSH_ClearEndpStall( uint8_t ep0_size, uint8_t endp_num );
|
||||
extern uint8_t USBFSH_GetEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t *plen );
|
||||
extern uint8_t USBFSH_SendEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t len );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,178 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : usb_host_config.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/08/29
|
||||
* Description :
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __USB_HOST_CONFIG_H
|
||||
#define __USB_HOST_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/* Header File */
|
||||
#include "string.h"
|
||||
#include "debug.h"
|
||||
#include "ch32v20x_usb.h"
|
||||
#include "ch32v20x_usbfs_host.h"
|
||||
#include "usb_host_hid.h"
|
||||
#include "usb_host_hub.h"
|
||||
#include "app_km.h"
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Debug Macro Definition */
|
||||
#define DEF_DEBUG_PRINTF 1
|
||||
#if ( DEF_DEBUG_PRINTF == 1 )
|
||||
#define DUG_PRINTF( format, arg... ) printf( format, ##arg )
|
||||
#else
|
||||
#define DUG_PRINTF( format, arg... ) do{ if( 0 )printf( format, ##arg ); }while( 0 );
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* USB Host Communication Related Macro Definition */
|
||||
|
||||
/* USB Host Port General Control */
|
||||
#define DEF_TOTAL_ROOT_HUB 1
|
||||
#define DEF_USBFS_PORT_EN 1
|
||||
#define DEF_USBFS_PORT_INDEX 0x00
|
||||
#define DEF_ONE_USB_SUP_DEV_TOTAL 5
|
||||
#define DEF_NEXT_HUB_PORT_NUM_MAX 4
|
||||
#define DEF_INTERFACE_NUM_MAX 4
|
||||
|
||||
/* USB Root Device Status */
|
||||
#define ROOT_DEV_DISCONNECT 0
|
||||
#define ROOT_DEV_CONNECTED 1
|
||||
#define ROOT_DEV_FAILED 2
|
||||
#define ROOT_DEV_SUCCESS 3
|
||||
|
||||
/* USB Device Address */
|
||||
#define USB_DEVICE_ADDR 0x02
|
||||
|
||||
/* USB Speed */
|
||||
#define USB_LOW_SPEED 0x00
|
||||
#define USB_FULL_SPEED 0x01
|
||||
#define USB_HIGH_SPEED 0x02
|
||||
#define USB_SPEED_CHECK_ERR 0xFF
|
||||
|
||||
/* Configuration Descriptor Type */
|
||||
#define DEF_DECR_CONFIG 0x02
|
||||
#define DEF_DECR_INTERFACE 0x04
|
||||
#define DEF_DECR_ENDPOINT 0x05
|
||||
#define DEF_DECR_HID 0x21
|
||||
|
||||
/* USB Communication Status Code */
|
||||
#define ERR_SUCCESS 0x00
|
||||
#define ERR_USB_CONNECT 0x15
|
||||
#define ERR_USB_DISCON 0x16
|
||||
#define ERR_USB_BUF_OVER 0x17
|
||||
#define ERR_USB_DISK_ERR 0x1F
|
||||
#define ERR_USB_TRANSFER 0x20
|
||||
#define ERR_USB_UNSUPPORT 0xFB
|
||||
#define ERR_USB_UNAVAILABLE 0xFC
|
||||
#define ERR_USB_UNKNOWN 0xFE
|
||||
|
||||
/* USB Device Enumeration Status Code */
|
||||
#define DEF_DEV_DESCR_GETFAIL 0x45
|
||||
#define DEF_DEV_ADDR_SETFAIL 0x46
|
||||
#define DEF_CFG_DESCR_GETFAIL 0x47
|
||||
#define DEF_REP_DESCR_GETFAIL 0x48
|
||||
#define DEF_CFG_VALUE_SETFAIL 0x49
|
||||
#define DEF_DEV_TYPE_UNKNOWN 0xFF
|
||||
|
||||
/* USB Communication Time */
|
||||
#define DEF_BUS_RESET_TIME 11 // USB bus reset time
|
||||
#define DEF_RE_ATTACH_TIMEOUT 100 // Wait for the USB device to reconnect after reset, 100mS timeout
|
||||
#define DEF_WAIT_USB_TRANSFER_CNT 1000 // Wait for the USB transfer to complete
|
||||
#define DEF_CTRL_TRANS_TIMEOVER_CNT 200000/20 // Control transmission delay timing
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Struct Definition */
|
||||
/* Note: Please modify it according to your project. */
|
||||
|
||||
/* HUB Port Device */
|
||||
typedef struct _HUB_DEVICE
|
||||
{
|
||||
uint8_t bStatus;
|
||||
uint8_t bType;
|
||||
uint8_t bAddress;
|
||||
uint8_t bSpeed;
|
||||
uint8_t bEp0MaxPks;
|
||||
uint8_t DeviceIndex;
|
||||
}HUB_DEVICE, *PHUB_DEVICE;
|
||||
|
||||
/* Root HUB Device Structure */
|
||||
typedef struct _ROOT_HUB_DEVICE
|
||||
{
|
||||
uint8_t bStatus;
|
||||
uint8_t bType;
|
||||
uint8_t bAddress;
|
||||
uint8_t bSpeed;
|
||||
uint8_t bEp0MaxPks;
|
||||
uint8_t DeviceIndex;
|
||||
uint8_t bPortNum;
|
||||
HUB_DEVICE Device[ DEF_NEXT_HUB_PORT_NUM_MAX ];
|
||||
} ROOT_HUB_DEVICE, *PROOT_HUB_DEVICE;
|
||||
|
||||
/* USB Host Control Structure */
|
||||
typedef struct __HOST_CTL
|
||||
{
|
||||
uint8_t InterfaceNum;
|
||||
uint8_t ErrorCount;
|
||||
|
||||
struct interface
|
||||
{
|
||||
uint8_t Type;
|
||||
uint16_t HidDescLen;
|
||||
uint8_t HidReportID;
|
||||
uint8_t Full_KB_Flag;
|
||||
|
||||
uint8_t InEndpNum;
|
||||
uint8_t InEndpAddr[ 4 ];
|
||||
uint8_t InEndpType[ 4 ];
|
||||
uint16_t InEndpSize[ 4 ];
|
||||
uint8_t InEndpTog[ 4 ];
|
||||
uint8_t InEndpInterval[ 4 ];
|
||||
uint8_t InEndpTimeCount[ 4 ];
|
||||
|
||||
uint8_t OutEndpNum;
|
||||
uint8_t OutEndpAddr[ 4 ];
|
||||
uint8_t OutEndpType[ 4 ];
|
||||
uint16_t OutEndpSize[ 4 ];
|
||||
uint8_t OutEndpTog[ 4 ];
|
||||
|
||||
uint8_t IDFlag;
|
||||
uint8_t ReportID;
|
||||
|
||||
uint8_t LED_Usage_Min;
|
||||
uint8_t LED_Usage_Max;
|
||||
|
||||
uint8_t SetReport_Swi;
|
||||
uint8_t SetReport_Value;
|
||||
uint8_t SetReport_Flag;
|
||||
|
||||
}Interface[ DEF_INTERFACE_NUM_MAX ];
|
||||
} HOST_CTL, *PHOST_CTL;
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Struct Declaration */
|
||||
extern struct _ROOT_HUB_DEVICE RootHubDev;
|
||||
extern struct __HOST_CTL HostCtl[ ];
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : usb_hid.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/08/29
|
||||
* Description :
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/********************************************************************************/
|
||||
/* Header File */
|
||||
#include "usb_host_config.h"
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HID_GetHidDesr
|
||||
*
|
||||
* @brief Get USB device report descriptor.
|
||||
*
|
||||
* @para num: Interface number.
|
||||
* pbuf: Buffer for saving descriptor.
|
||||
* len: Descriptor length.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
uint8_t HID_GetHidDesr( uint8_t ep0_size, uint8_t intf_num, uint8_t *pbuf, uint16_t *plen )
|
||||
{
|
||||
memcpy( pUSBFS_SetupRequest, SetupGetHidDes, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wIndex = (uint16_t)intf_num;
|
||||
pUSBFS_SetupRequest->wLength = *plen;
|
||||
return USBFSH_CtrlTransfer( ep0_size, pbuf, plen );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HID_SetReport
|
||||
*
|
||||
* @brief Set report.
|
||||
*
|
||||
* @para report: Desired report value.
|
||||
* len: Report length.
|
||||
* index: USB port num
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
uint8_t HID_SetReport( uint8_t ep0_size, uint8_t intf_num, uint8_t *pbuf, uint16_t *plen )
|
||||
{
|
||||
memcpy( pUSBFS_SetupRequest, SetupSetReport, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wIndex = (uint16_t)intf_num;
|
||||
return USBFSH_CtrlTransfer( ep0_size, pbuf, plen );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HID_SetIdleSpeed
|
||||
*
|
||||
* @brief Set idle.
|
||||
*
|
||||
* @para speed: Report ID.
|
||||
* index: Interface number.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
uint8_t HID_SetIdle( uint8_t ep0_size, uint8_t intf_num, uint8_t duration, uint8_t reportid )
|
||||
{
|
||||
memcpy( pUSBFS_SetupRequest, SetupSetidle, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wValue = ( (uint16_t)duration << 8 ) | reportid;
|
||||
pUSBFS_SetupRequest->wIndex = (uint16_t)intf_num;
|
||||
return USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : usb_hid.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/08/29
|
||||
* Description :
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __USB_HOST_HID_H
|
||||
#define __USB_HOST_HID_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/********************************************************************************/
|
||||
/* Header File */
|
||||
#include "stdint.h"
|
||||
|
||||
/********************************************************************************/
|
||||
/* Constant Definition */
|
||||
#ifndef DEF_HID_DED_CMD
|
||||
#define DEF_HID_DED_CMD
|
||||
/* Set Protocol Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupSetprotocol[ ] =
|
||||
{
|
||||
0x21, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Set Idle Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupSetidle[ ] =
|
||||
{
|
||||
0x21, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Set Report Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupSetReport[ ] =
|
||||
{
|
||||
0x21, 0x09, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00
|
||||
};
|
||||
|
||||
/* Get Report Descriptor Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetupGetHidDes[ ] =
|
||||
{
|
||||
0x81, 0x06, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Function Declaration */
|
||||
extern uint8_t HID_GetHidDesr( uint8_t ep0_size, uint8_t intf_num, uint8_t *pbuf, uint16_t *plen );
|
||||
extern uint8_t HID_SetReport( uint8_t ep0_size, uint8_t intf_num, uint8_t *pbuf, uint16_t *plen );
|
||||
extern uint8_t HID_SetIdle( uint8_t ep0_size, uint8_t intf_num, uint8_t duration, uint8_t reportid );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : usb_host_hub.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/08/29
|
||||
* Description :
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/********************************************************************************/
|
||||
/* Header File */
|
||||
#include "usb_host_config.h"
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HUB_ClearPortFeature
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
* @para
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
uint8_t HUB_GetPortStatus( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t *pbuf )
|
||||
{
|
||||
uint16_t len;
|
||||
|
||||
memcpy( pUSBFS_SetupRequest, GetPortStatus, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wIndex = (uint16_t)hub_port;
|
||||
return USBFSH_CtrlTransfer( hub_ep0_size, pbuf, &len );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HUB_ClearPortFeature
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
* @para
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
uint8_t HUB_ClearPortFeature( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t selector )
|
||||
{
|
||||
memcpy( pUSBFS_SetupRequest, ClearPortFeature, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wValue = (uint16_t)selector;
|
||||
pUSBFS_SetupRequest->wIndex = (uint16_t)hub_port;
|
||||
return USBFSH_CtrlTransfer( hub_ep0_size, NULL, NULL );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HUB_SetPortFeature
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
* @para
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
uint8_t HUB_SetPortFeature( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t selector )
|
||||
{
|
||||
memcpy( pUSBFS_SetupRequest, SetPortFeature, sizeof( USB_SETUP_REQ ) );
|
||||
pUSBFS_SetupRequest->wValue = (uint16_t)selector;
|
||||
pUSBFS_SetupRequest->wIndex = (uint16_t)hub_port;
|
||||
return USBFSH_CtrlTransfer( hub_ep0_size, NULL, NULL );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HUB_GetClassDevDescr
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
* @para
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
uint8_t HUB_GetClassDevDescr( uint8_t hub_ep0_size, uint8_t *pbuf, uint16_t *plen )
|
||||
{
|
||||
uint8_t s;
|
||||
|
||||
memcpy( pUSBFS_SetupRequest, GetHubDescr, sizeof( USB_SETUP_REQ ) );
|
||||
s = USBFSH_CtrlTransfer( hub_ep0_size, pbuf, plen );
|
||||
if( s != ERR_SUCCESS )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
pUSBFS_SetupRequest->wLength = *plen = (uint16_t)pbuf[ 0 ];
|
||||
s = USBFSH_CtrlTransfer( hub_ep0_size, pbuf, plen );
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : usb_host_hub.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/08/29
|
||||
* Description :
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __USB_HOST_HUB_H
|
||||
#define __USB_HOST_HUB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/********************************************************************************/
|
||||
/* Header File */
|
||||
#include "stdint.h"
|
||||
|
||||
/********************************************************************************/
|
||||
/* Constant Definition */
|
||||
#ifndef DEF_HUB_DED_CMD
|
||||
#define DEF_HUB_DED_CMD
|
||||
/* Get Port Status Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t GetPortStatus[ ] =
|
||||
{
|
||||
0xA3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00
|
||||
};
|
||||
|
||||
/* Clear Port Feature Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t ClearPortFeature[ ] =
|
||||
{
|
||||
0x23, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Set Port Feature Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t SetPortFeature[ ] =
|
||||
{
|
||||
0x23, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Get Hub Descriptor Command Packet */
|
||||
__attribute__((aligned(4))) static const uint8_t GetHubDescr[ ] =
|
||||
{
|
||||
0xA0, 0x06, 0x00, 0x29, 0x00, 0x00, 0x02, 0x00
|
||||
};
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Function Declaration */
|
||||
extern uint8_t HUB_GetPortStatus( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t *pbuf );
|
||||
extern uint8_t HUB_ClearPortFeature( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t selector );
|
||||
extern uint8_t HUB_SetPortFeature( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t selector );
|
||||
extern uint8_t HUB_GetClassDevDescr( uint8_t hub_ep0_size, uint8_t *pbuf, uint16_t *plen );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : ch32v20x_conf.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : Library configuration file.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#ifndef __CH32V20x_CONF_H
|
||||
#define __CH32V20x_CONF_H
|
||||
|
||||
#include "ch32v20x_adc.h"
|
||||
#include "ch32v20x_bkp.h"
|
||||
#include "ch32v20x_can.h"
|
||||
#include "ch32v20x_crc.h"
|
||||
#include "ch32v20x_dbgmcu.h"
|
||||
#include "ch32v20x_dma.h"
|
||||
#include "ch32v20x_exti.h"
|
||||
#include "ch32v20x_flash.h"
|
||||
#include "ch32v20x_gpio.h"
|
||||
#include "ch32v20x_i2c.h"
|
||||
#include "ch32v20x_iwdg.h"
|
||||
#include "ch32v20x_pwr.h"
|
||||
#include "ch32v20x_rcc.h"
|
||||
#include "ch32v20x_rtc.h"
|
||||
#include "ch32v20x_spi.h"
|
||||
#include "ch32v20x_tim.h"
|
||||
#include "ch32v20x_usart.h"
|
||||
#include "ch32v20x_wwdg.h"
|
||||
#include "ch32v20x_it.h"
|
||||
#include "ch32v20x_misc.h"
|
||||
|
||||
|
||||
#endif /* __CH32V20x_CONF_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : ch32v20x_it.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : Main Interrupt Service Routines.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#include "ch32v20x_it.h"
|
||||
|
||||
void NMI_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
|
||||
void HardFault_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
|
||||
/*********************************************************************
|
||||
* @fn NMI_Handler
|
||||
*
|
||||
* @brief This function handles NMI exception.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HardFault_Handler
|
||||
*
|
||||
* @brief This function handles Hard Fault exception.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : ch32v20x_it.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : This file contains the headers of the interrupt handlers.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#ifndef __CH32V20x_IT_H
|
||||
#define __CH32V20x_IT_H
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#endif /* __CH32V20x_IT_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,540 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : ch32v20x_usb.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : CH32V20x Device Peripheral Access Layer System Header File.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __CH32V20x_USB_H
|
||||
#define __CH32V20x_USB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Header Files */
|
||||
#include "stdint.h"
|
||||
|
||||
/*******************************************************************************/
|
||||
/* USB Communication Related Macro Definition */
|
||||
|
||||
/* USB Endpoint0 Size */
|
||||
#ifndef DEFAULT_ENDP0_SIZE
|
||||
#define DEFAULT_ENDP0_SIZE 8
|
||||
#endif
|
||||
|
||||
/* USB PID */
|
||||
#ifndef USB_PID_SETUP
|
||||
#define USB_PID_NULL 0x00
|
||||
#define USB_PID_SOF 0x05
|
||||
#define USB_PID_SETUP 0x0D
|
||||
#define USB_PID_IN 0x09
|
||||
#define USB_PID_OUT 0x01
|
||||
#define USB_PID_NYET 0x06
|
||||
#define USB_PID_ACK 0x02
|
||||
#define USB_PID_NAK 0x0A
|
||||
#define USB_PID_STALL 0x0E
|
||||
#define USB_PID_DATA0 0x03
|
||||
#define USB_PID_DATA1 0x0B
|
||||
#define USB_PID_DATA2 0x07
|
||||
#define USB_PID_MDATA 0x0F
|
||||
#define USB_PID_PRE 0x0C
|
||||
#define USB_PID_SPLIT 0x08
|
||||
#define USB_PID_PING 0x04
|
||||
#endif
|
||||
|
||||
/* USB standard device request code */
|
||||
#ifndef USB_GET_DESCRIPTOR
|
||||
#define USB_GET_STATUS 0x00
|
||||
#define USB_CLEAR_FEATURE 0x01
|
||||
#define USB_SET_FEATURE 0x03
|
||||
#define USB_SET_ADDRESS 0x05
|
||||
#define USB_GET_DESCRIPTOR 0x06
|
||||
#define USB_SET_DESCRIPTOR 0x07
|
||||
#define USB_GET_CONFIGURATION 0x08
|
||||
#define USB_SET_CONFIGURATION 0x09
|
||||
#define USB_GET_INTERFACE 0x0A
|
||||
#define USB_SET_INTERFACE 0x0B
|
||||
#define USB_SYNCH_FRAME 0x0C
|
||||
#endif
|
||||
|
||||
#define DEF_STRING_DESC_LANG 0x00
|
||||
#define DEF_STRING_DESC_MANU 0x01
|
||||
#define DEF_STRING_DESC_PROD 0x02
|
||||
#define DEF_STRING_DESC_SERN 0x03
|
||||
|
||||
/* USB hub class request code */
|
||||
#ifndef HUB_GET_DESCRIPTOR
|
||||
#define HUB_GET_STATUS 0x00
|
||||
#define HUB_CLEAR_FEATURE 0x01
|
||||
#define HUB_GET_STATE 0x02
|
||||
#define HUB_SET_FEATURE 0x03
|
||||
#define HUB_GET_DESCRIPTOR 0x06
|
||||
#define HUB_SET_DESCRIPTOR 0x07
|
||||
#endif
|
||||
|
||||
/* USB HID class request code */
|
||||
#ifndef HID_GET_REPORT
|
||||
#define HID_GET_REPORT 0x01
|
||||
#define HID_GET_IDLE 0x02
|
||||
#define HID_GET_PROTOCOL 0x03
|
||||
#define HID_SET_REPORT 0x09
|
||||
#define HID_SET_IDLE 0x0A
|
||||
#define HID_SET_PROTOCOL 0x0B
|
||||
#endif
|
||||
|
||||
/* Bit Define for USB Request Type */
|
||||
#ifndef USB_REQ_TYP_MASK
|
||||
#define USB_REQ_TYP_IN 0x80
|
||||
#define USB_REQ_TYP_OUT 0x00
|
||||
#define USB_REQ_TYP_READ 0x80
|
||||
#define USB_REQ_TYP_WRITE 0x00
|
||||
#define USB_REQ_TYP_MASK 0x60
|
||||
#define USB_REQ_TYP_STANDARD 0x00
|
||||
#define USB_REQ_TYP_CLASS 0x20
|
||||
#define USB_REQ_TYP_VENDOR 0x40
|
||||
#define USB_REQ_TYP_RESERVED 0x60
|
||||
#define USB_REQ_RECIP_MASK 0x1F
|
||||
#define USB_REQ_RECIP_DEVICE 0x00
|
||||
#define USB_REQ_RECIP_INTERF 0x01
|
||||
#define USB_REQ_RECIP_ENDP 0x02
|
||||
#define USB_REQ_RECIP_OTHER 0x03
|
||||
#define USB_REQ_FEAT_REMOTE_WAKEUP 0x01
|
||||
#define USB_REQ_FEAT_ENDP_HALT 0x00
|
||||
#endif
|
||||
|
||||
/* USB Descriptor Type */
|
||||
#ifndef USB_DESCR_TYP_DEVICE
|
||||
#define USB_DESCR_TYP_DEVICE 0x01
|
||||
#define USB_DESCR_TYP_CONFIG 0x02
|
||||
#define USB_DESCR_TYP_STRING 0x03
|
||||
#define USB_DESCR_TYP_INTERF 0x04
|
||||
#define USB_DESCR_TYP_ENDP 0x05
|
||||
#define USB_DESCR_TYP_QUALIF 0x06
|
||||
#define USB_DESCR_TYP_SPEED 0x07
|
||||
#define USB_DESCR_TYP_OTG 0x09
|
||||
#define USB_DESCR_TYP_BOS 0X0F
|
||||
#define USB_DESCR_TYP_HID 0x21
|
||||
#define USB_DESCR_TYP_REPORT 0x22
|
||||
#define USB_DESCR_TYP_PHYSIC 0x23
|
||||
#define USB_DESCR_TYP_CS_INTF 0x24
|
||||
#define USB_DESCR_TYP_CS_ENDP 0x25
|
||||
#define USB_DESCR_TYP_HUB 0x29
|
||||
#endif
|
||||
|
||||
/* USB Device Class */
|
||||
#ifndef USB_DEV_CLASS_HUB
|
||||
#define USB_DEV_CLASS_RESERVED 0x00
|
||||
#define USB_DEV_CLASS_AUDIO 0x01
|
||||
#define USB_DEV_CLASS_COMMUNIC 0x02
|
||||
#define USB_DEV_CLASS_HID 0x03
|
||||
#define USB_DEV_CLASS_MONITOR 0x04
|
||||
#define USB_DEV_CLASS_PHYSIC_IF 0x05
|
||||
#define USB_DEV_CLASS_POWER 0x06
|
||||
#define USB_DEV_CLASS_PRINTER 0x07
|
||||
#define USB_DEV_CLASS_STORAGE 0x08
|
||||
#define USB_DEV_CLASS_HUB 0x09
|
||||
#define USB_DEV_CLASS_VEN_SPEC 0xFF
|
||||
#endif
|
||||
|
||||
/* USB Hub Class Request */
|
||||
#ifndef HUB_GET_HUB_DESCRIPTOR
|
||||
#define HUB_CLEAR_HUB_FEATURE 0x20
|
||||
#define HUB_CLEAR_PORT_FEATURE 0x23
|
||||
#define HUB_GET_BUS_STATE 0xA3
|
||||
#define HUB_GET_HUB_DESCRIPTOR 0xA0
|
||||
#define HUB_GET_HUB_STATUS 0xA0
|
||||
#define HUB_GET_PORT_STATUS 0xA3
|
||||
#define HUB_SET_HUB_DESCRIPTOR 0x20
|
||||
#define HUB_SET_HUB_FEATURE 0x20
|
||||
#define HUB_SET_PORT_FEATURE 0x23
|
||||
#endif
|
||||
|
||||
/* Hub Class Feature Selectors */
|
||||
#ifndef HUB_PORT_RESET
|
||||
#define HUB_C_HUB_LOCAL_POWER 0
|
||||
#define HUB_C_HUB_OVER_CURRENT 1
|
||||
#define HUB_PORT_CONNECTION 0
|
||||
#define HUB_PORT_ENABLE 1
|
||||
#define HUB_PORT_SUSPEND 2
|
||||
#define HUB_PORT_OVER_CURRENT 3
|
||||
#define HUB_PORT_RESET 4
|
||||
#define HUB_PORT_POWER 8
|
||||
#define HUB_PORT_LOW_SPEED 9
|
||||
#define HUB_C_PORT_CONNECTION 16
|
||||
#define HUB_C_PORT_ENABLE 17
|
||||
#define HUB_C_PORT_SUSPEND 18
|
||||
#define HUB_C_PORT_OVER_CURRENT 19
|
||||
#define HUB_C_PORT_RESET 20
|
||||
#endif
|
||||
|
||||
/* USB HID Class Request Code */
|
||||
#ifndef HID_GET_REPORT
|
||||
#define HID_GET_REPORT 0x01
|
||||
#define HID_GET_IDLE 0x02
|
||||
#define HID_GET_PROTOCOL 0x03
|
||||
#define HID_SET_REPORT 0x09
|
||||
#define HID_SET_IDLE 0x0A
|
||||
#define HID_SET_PROTOCOL 0x0B
|
||||
#endif
|
||||
|
||||
/* USB UDisk */
|
||||
#ifndef USB_BO_CBW_SIZE
|
||||
#define USB_BO_CBW_SIZE 0x1F
|
||||
#define USB_BO_CSW_SIZE 0x0D
|
||||
#endif
|
||||
#ifndef USB_BO_CBW_SIG0
|
||||
#define USB_BO_CBW_SIG0 0x55
|
||||
#define USB_BO_CBW_SIG1 0x53
|
||||
#define USB_BO_CBW_SIG2 0x42
|
||||
#define USB_BO_CBW_SIG3 0x43
|
||||
#define USB_BO_CSW_SIG0 0x55
|
||||
#define USB_BO_CSW_SIG1 0x53
|
||||
#define USB_BO_CSW_SIG2 0x42
|
||||
#define USB_BO_CSW_SIG3 0x53
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/* USBFS Related Register Macro Definition */
|
||||
|
||||
/* R8_USB_CTRL */
|
||||
#define USBFS_UC_HOST_MODE 0x80
|
||||
#define USBFS_UC_LOW_SPEED 0x40
|
||||
#define USBFS_UC_DEV_PU_EN 0x20
|
||||
#define USBFS_UC_SYS_CTRL_MASK 0x30
|
||||
#define USBFS_UC_SYS_CTRL0 0x00
|
||||
#define USBFS_UC_SYS_CTRL1 0x10
|
||||
#define USBFS_UC_SYS_CTRL2 0x20
|
||||
#define USBFS_UC_SYS_CTRL3 0x30
|
||||
#define USBFS_UC_INT_BUSY 0x08
|
||||
#define USBFS_UC_RESET_SIE 0x04
|
||||
#define USBFS_UC_CLR_ALL 0x02
|
||||
#define USBFS_UC_DMA_EN 0x01
|
||||
|
||||
/* R8_USB_INT_EN */
|
||||
#define USBFS_UIE_DEV_SOF 0x80
|
||||
#define USBFS_UIE_DEV_NAK 0x40
|
||||
#define USBFS_UIE_FIFO_OV 0x10
|
||||
#define USBFS_UIE_HST_SOF 0x08
|
||||
#define USBFS_UIE_SUSPEND 0x04
|
||||
#define USBFS_UIE_TRANSFER 0x02
|
||||
#define USBFS_UIE_DETECT 0x01
|
||||
#define USBFS_UIE_BUS_RST 0x01
|
||||
|
||||
/* R8_USB_DEV_AD */
|
||||
#define USBFS_UDA_GP_BIT 0x80
|
||||
#define USBFS_USB_ADDR_MASK 0x7F
|
||||
|
||||
/* R8_USB_MIS_ST */
|
||||
#define USBFS_UMS_SOF_PRES 0x80
|
||||
#define USBFS_UMS_SOF_ACT 0x40
|
||||
#define USBFS_UMS_SIE_FREE 0x20
|
||||
#define USBFS_UMS_R_FIFO_RDY 0x10
|
||||
#define USBFS_UMS_BUS_RESET 0x08
|
||||
#define USBFS_UMS_SUSPEND 0x04
|
||||
#define USBFS_UMS_DM_LEVEL 0x02
|
||||
#define USBFS_UMS_DEV_ATTACH 0x01
|
||||
|
||||
/* R8_USB_INT_FG */
|
||||
#define USBFS_U_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received
|
||||
#define USBFS_U_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
|
||||
#define USBFS_U_SIE_FREE 0x20 // RO, indicate USB SIE free status
|
||||
#define USBFS_UIF_FIFO_OV 0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_HST_SOF 0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_SUSPEND 0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_DETECT 0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_BUS_RST 0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
|
||||
|
||||
/* R8_USB_INT_ST */
|
||||
#define USBFS_UIS_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received for USB device mode
|
||||
#define USBFS_UIS_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
|
||||
#define USBFS_UIS_TOKEN_MASK 0x30 // RO, bit mask of current token PID code received for USB device mode
|
||||
#define USBFS_UIS_TOKEN_OUT 0x00
|
||||
#define USBFS_UIS_TOKEN_SOF 0x10
|
||||
#define USBFS_UIS_TOKEN_IN 0x20
|
||||
#define USBFS_UIS_TOKEN_SETUP 0x30
|
||||
// bUIS_TOKEN1 & bUIS_TOKEN0: current token PID code received for USB device mode
|
||||
// 00: OUT token PID received
|
||||
// 01: SOF token PID received
|
||||
// 10: IN token PID received
|
||||
// 11: SETUP token PID received
|
||||
#define USBFS_UIS_ENDP_MASK 0x0F // RO, bit mask of current transfer endpoint number for USB device mode
|
||||
#define USBFS_UIS_H_RES_MASK 0x0F // RO, bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received
|
||||
|
||||
/* R32_USB_OTG_CR */
|
||||
#define USBFS_CR_SESS_VTH 0x20
|
||||
#define USBFS_CR_VBUS_VTH 0x10
|
||||
#define USBFS_CR_OTG_EN 0x08
|
||||
#define USBFS_CR_IDPU 0x04
|
||||
#define USBFS_CR_CHARGE_VBUS 0x02
|
||||
#define USBFS_CR_DISCHAR_VBUS 0x01
|
||||
|
||||
/* R32_USB_OTG_SR */
|
||||
#define USBFS_SR_ID_DIG 0x08
|
||||
#define USBFS_SR_SESS_END 0x04
|
||||
#define USBFS_SR_SESS_VLD 0x02
|
||||
#define USBFS_SR_VBUS_VLD 0x01
|
||||
|
||||
/* R8_UDEV_CTRL */
|
||||
#define USBFS_UD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
|
||||
#define USBFS_UD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
|
||||
#define USBFS_UD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
|
||||
#define USBFS_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed
|
||||
#define USBFS_UD_GP_BIT 0x02 // general purpose bit
|
||||
#define USBFS_UD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable
|
||||
|
||||
/* R8_UEP4_1_MOD */
|
||||
#define USBFS_UEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT)
|
||||
#define USBFS_UEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN)
|
||||
#define USBFS_UEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1
|
||||
// bUEPn_RX_EN & bUEPn_TX_EN & bUEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA
|
||||
// 0 0 x: disable endpoint and disable buffer
|
||||
// 1 0 0: 64 bytes buffer for receiving (OUT endpoint)
|
||||
// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes
|
||||
// 0 1 0: 64 bytes buffer for transmittal (IN endpoint)
|
||||
// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes
|
||||
// 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes
|
||||
// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes
|
||||
#define USBFS_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT)
|
||||
#define USBFS_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
|
||||
// bUEP4_RX_EN & bUEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA
|
||||
// 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
|
||||
// 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes
|
||||
// 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes
|
||||
// 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
|
||||
// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes
|
||||
#define USBFS_UEP4_BUF_MOD 0x01
|
||||
|
||||
/* R8_UEP2_3_MOD */
|
||||
#define USBFS_UEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT)
|
||||
#define USBFS_UEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN)
|
||||
#define USBFS_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
|
||||
#define USBFS_UEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT)
|
||||
#define USBFS_UEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN)
|
||||
#define USBFS_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
|
||||
|
||||
/* R8_UEP5_6_MOD */
|
||||
#define USBFS_UEP6_RX_EN 0x80 // enable USB endpoint 6 receiving (OUT)
|
||||
#define USBFS_UEP6_TX_EN 0x40 // enable USB endpoint 6 transmittal (IN)
|
||||
#define USBFS_UEP6_BUF_MOD 0x10 // buffer mode of USB endpoint 6
|
||||
#define USBFS_UEP5_RX_EN 0x08 // enable USB endpoint 5 receiving (OUT)
|
||||
#define USBFS_UEP5_TX_EN 0x04 // enable USB endpoint 5 transmittal (IN)
|
||||
#define USBFS_UEP5_BUF_MOD 0x01 // buffer mode of USB endpoint 5
|
||||
|
||||
/* R8_UEP7_MOD */
|
||||
#define USBFS_UEP7_RX_EN 0x08 // enable USB endpoint 7 receiving (OUT)
|
||||
#define USBFS_UEP7_TX_EN 0x04 // enable USB endpoint 7 transmittal (IN)
|
||||
#define USBFS_UEP7_BUF_MOD 0x01 // buffer mode of USB endpoint 7
|
||||
|
||||
/* R8_UEPn_TX_CTRL */
|
||||
#define USBFS_UEP_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
|
||||
#define USBFS_UEP_T_TOG 0x04 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1
|
||||
#define USBFS_UEP_T_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN)
|
||||
#define USBFS_UEP_T_RES_ACK 0x00
|
||||
#define USBFS_UEP_T_RES_NONE 0x01
|
||||
#define USBFS_UEP_T_RES_NAK 0x02
|
||||
#define USBFS_UEP_T_RES_STALL 0x03
|
||||
// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN)
|
||||
// 00: DATA0 or DATA1 then expecting ACK (ready)
|
||||
// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions
|
||||
// 10: NAK (busy)
|
||||
// 11: STALL (error)
|
||||
// host aux setup
|
||||
|
||||
/* R8_UEPn_RX_CTRL, n=0-7 */
|
||||
#define USBFS_UEP_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
|
||||
#define USBFS_UEP_R_TOG 0x04 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1
|
||||
#define USBFS_UEP_R_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X receiving (OUT)
|
||||
#define USBFS_UEP_R_RES_ACK 0x00
|
||||
#define USBFS_UEP_R_RES_NONE 0x01
|
||||
#define USBFS_UEP_R_RES_NAK 0x02
|
||||
#define USBFS_UEP_R_RES_STALL 0x03
|
||||
// RB_UEP_R_RES1 & RB_UEP_R_RES0: handshake response type for USB endpoint X receiving (OUT)
|
||||
// 00: ACK (ready)
|
||||
// 01: no response, time out to host, for non-zero endpoint isochronous transactions
|
||||
// 10: NAK (busy)
|
||||
// 11: STALL (error)
|
||||
|
||||
/* R8_UHOST_CTRL */
|
||||
#define USBFS_UH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
|
||||
#define USBFS_UH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
|
||||
#define USBFS_UH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
|
||||
#define USBFS_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
|
||||
#define USBFS_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
|
||||
#define USBFS_UH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
|
||||
|
||||
/* R32_UH_EP_MOD */
|
||||
#define USBFS_UH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal
|
||||
#define USBFS_UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
|
||||
// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA
|
||||
// 0 x: disable endpoint and disable buffer
|
||||
// 1 0: 64 bytes buffer for transmittal (OUT endpoint)
|
||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes
|
||||
#define USBFS_UH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving
|
||||
#define USBFS_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
|
||||
// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA
|
||||
// 0 x: disable endpoint and disable buffer
|
||||
// 1 0: 64 bytes buffer for receiving (IN endpoint)
|
||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes
|
||||
|
||||
/* R16_UH_SETUP */
|
||||
#define USBFS_UH_PRE_PID_EN 0x0400 // USB host PRE PID enable for low speed device via hub
|
||||
#define USBFS_UH_SOF_EN 0x0004 // USB host automatic SOF enable
|
||||
|
||||
/* R8_UH_EP_PID */
|
||||
#define USBFS_UH_TOKEN_MASK 0xF0 // bit mask of token PID for USB host transfer
|
||||
#define USBFS_UH_ENDP_MASK 0x0F // bit mask of endpoint number for USB host transfer
|
||||
|
||||
/* R8_UH_RX_CTRL */
|
||||
#define USBFS_UH_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
|
||||
#define USBFS_UH_R_TOG 0x04 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
|
||||
#define USBFS_UH_R_RES 0x01 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions
|
||||
|
||||
/* R8_UH_TX_CTRL */
|
||||
#define USBFS_UH_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
|
||||
#define USBFS_UH_T_TOG 0x04 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
|
||||
#define USBFS_UH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Struct Definition */
|
||||
|
||||
/* USB Setup Request */
|
||||
typedef struct __attribute__((packed)) _USB_SETUP_REQ
|
||||
{
|
||||
uint8_t bRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
} USB_SETUP_REQ, *PUSB_SETUP_REQ;
|
||||
|
||||
/* USB Device Descriptor */
|
||||
typedef struct __attribute__((packed)) _USB_DEVICE_DESCR
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t bcdDevice;
|
||||
uint8_t iManufacturer;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
} USB_DEV_DESCR, *PUSB_DEV_DESCR;
|
||||
|
||||
/* USB Configuration Descriptor */
|
||||
typedef struct __attribute__((packed)) _USB_CONFIG_DESCR
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t wTotalLength;
|
||||
uint8_t bNumInterfaces;
|
||||
uint8_t bConfigurationValue;
|
||||
uint8_t iConfiguration;
|
||||
uint8_t bmAttributes;
|
||||
uint8_t MaxPower;
|
||||
} USB_CFG_DESCR, *PUSB_CFG_DESCR;
|
||||
|
||||
/* USB Interface Descriptor */
|
||||
typedef struct __attribute__((packed)) _USB_INTERF_DESCR
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bInterfaceNumber;
|
||||
uint8_t bAlternateSetting;
|
||||
uint8_t bNumEndpoints;
|
||||
uint8_t bInterfaceClass;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
uint8_t iInterface;
|
||||
} USB_ITF_DESCR, *PUSB_ITF_DESCR;
|
||||
|
||||
/* USB Endpoint Descriptor */
|
||||
typedef struct __attribute__((packed)) _USB_ENDPOINT_DESCR
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bEndpointAddress;
|
||||
uint8_t bmAttributes;
|
||||
uint8_t wMaxPacketSizeL;
|
||||
uint8_t wMaxPacketSizeH;
|
||||
uint8_t bInterval;
|
||||
} USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
|
||||
|
||||
/* USB Configuration Descriptor Set */
|
||||
typedef struct __attribute__((packed)) _USB_CONFIG_DESCR_LONG
|
||||
{
|
||||
USB_CFG_DESCR cfg_descr;
|
||||
USB_ITF_DESCR itf_descr;
|
||||
USB_ENDP_DESCR endp_descr[ 1 ];
|
||||
} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG;
|
||||
|
||||
/* USB HUB Descriptor */
|
||||
typedef struct __attribute__((packed)) _USB_HUB_DESCR
|
||||
{
|
||||
uint8_t bDescLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bNbrPorts;
|
||||
uint8_t wHubCharacteristicsL;
|
||||
uint8_t wHubCharacteristicsH;
|
||||
uint8_t bPwrOn2PwrGood;
|
||||
uint8_t bHubContrCurrent;
|
||||
uint8_t DeviceRemovable;
|
||||
uint8_t PortPwrCtrlMask;
|
||||
} USB_HUB_DESCR, *PUSB_HUB_DESCR;
|
||||
|
||||
/* USB HID Descriptor */
|
||||
typedef struct __attribute__((packed)) _USB_HID_DESCR
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdHID;
|
||||
uint8_t bCountryCode;
|
||||
uint8_t bNumDescriptors;
|
||||
uint8_t bDescriptorTypeX;
|
||||
uint8_t wDescriptorLengthL;
|
||||
uint8_t wDescriptorLengthH;
|
||||
} USB_HID_DESCR, *PUSB_HID_DESCR;
|
||||
|
||||
/* USB UDisk */
|
||||
typedef struct __attribute__((packed)) _UDISK_BOC_CBW
|
||||
{
|
||||
uint32_t mCBW_Sig;
|
||||
uint32_t mCBW_Tag;
|
||||
uint32_t mCBW_DataLen;
|
||||
uint8_t mCBW_Flag;
|
||||
uint8_t mCBW_LUN;
|
||||
uint8_t mCBW_CB_Len;
|
||||
uint8_t mCBW_CB_Buf[ 16 ];
|
||||
} UDISK_BOC_CBW, *PXUDISK_BOC_CBW;
|
||||
|
||||
/* USB UDisk */
|
||||
typedef struct __attribute__((packed)) _UDISK_BOC_CSW
|
||||
{
|
||||
uint32_t mCBW_Sig;
|
||||
uint32_t mCBW_Tag;
|
||||
uint32_t mCSW_Residue;
|
||||
uint8_t mCSW_Status;
|
||||
} UDISK_BOC_CSW, *PXUDISK_BOC_CSW;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CH32V20x_USB_H */
|
||||
@@ -0,0 +1,67 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : main.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/09/01
|
||||
* Description : Main program body.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
* @Note
|
||||
* This example demonstrates the process of enumerating the keyboard and mouse
|
||||
* by a USB host and obtaining data based on the polling time of the input endpoints
|
||||
* of the keyboard and mouse.
|
||||
* The USBFS port also supports enumeration of keyboard and mouse attached at tier
|
||||
* level 2(Hub 1).
|
||||
*/
|
||||
|
||||
/*
|
||||
* @Note
|
||||
* The USBFS module uses the system clock as the clock source, so the SystemCoreClock can
|
||||
* only be set to 144MHz, 96MHz or 48MHz.
|
||||
*/
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Header Files */
|
||||
#include "usb_host_config.h"
|
||||
|
||||
/*********************************************************************
|
||||
* @fn main
|
||||
*
|
||||
* @brief Main program.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
int main( void )
|
||||
{
|
||||
/* Initialize system configuration */
|
||||
Delay_Init( );
|
||||
USART_Printf_Init( 115200 );
|
||||
DUG_PRINTF( "SystemClk:%d\r\n", SystemCoreClock );
|
||||
DUG_PRINTF( "USBFS HOST KM Test\r\n" );
|
||||
|
||||
/* Initialize TIM3 */
|
||||
TIM3_Init( 9, SystemCoreClock / 10000 - 1 );
|
||||
DUG_PRINTF( "TIM3 Init OK!\r\n" );
|
||||
|
||||
/* Initialize USBFS host */
|
||||
#if DEF_USBFS_PORT_EN
|
||||
DUG_PRINTF( "USBFS Host Init\r\n" );
|
||||
USBFS_RCC_Init( );
|
||||
USBFS_Host_Init( ENABLE );
|
||||
memset( &RootHubDev.bStatus, 0, sizeof( ROOT_HUB_DEVICE ) );
|
||||
memset( &HostCtl[ DEF_USBFS_PORT_INDEX * DEF_ONE_USB_SUP_DEV_TOTAL ].InterfaceNum, 0, DEF_ONE_USB_SUP_DEV_TOTAL * sizeof( HOST_CTL ) );
|
||||
#endif
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
USBH_MainDeal( );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,986 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : system_ch32v20x.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : CH32V20x Device Peripheral Access Layer System Source File.
|
||||
* For HSE = 32Mhz (CH32V208x/CH32V203RBT6)
|
||||
* For HSE = 8Mhz (other CH32V203x)
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#include "ch32v20x.h"
|
||||
|
||||
/*
|
||||
* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
|
||||
* reset the HSI is used as SYSCLK source).
|
||||
* If none of the define below is enabled, the HSI is used as System clock source.
|
||||
*/
|
||||
//#define SYSCLK_FREQ_HSE HSE_VALUE
|
||||
//#define SYSCLK_FREQ_48MHz_HSE 48000000
|
||||
//#define SYSCLK_FREQ_56MHz_HSE 56000000
|
||||
//#define SYSCLK_FREQ_72MHz_HSE 72000000
|
||||
#define SYSCLK_FREQ_96MHz_HSE 96000000
|
||||
//#define SYSCLK_FREQ_120MHz_HSE 120000000
|
||||
//#define SYSCLK_FREQ_144MHz_HSE 144000000
|
||||
//#define SYSCLK_FREQ_HSI HSI_VALUE
|
||||
//#define SYSCLK_FREQ_48MHz_HSI 48000000
|
||||
//#define SYSCLK_FREQ_56MHz_HSI 56000000
|
||||
//#define SYSCLK_FREQ_72MHz_HSI 72000000
|
||||
//#define SYSCLK_FREQ_96MHz_HSI 96000000
|
||||
//#define SYSCLK_FREQ_120MHz_HSI 120000000
|
||||
//#define SYSCLK_FREQ_144MHz_HSI 144000000
|
||||
|
||||
/* Clock Definitions */
|
||||
#ifdef SYSCLK_FREQ_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#else
|
||||
uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
|
||||
|
||||
#endif
|
||||
|
||||
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
|
||||
|
||||
/* system_private_function_proto_types */
|
||||
static void SetSysClock(void);
|
||||
|
||||
#ifdef SYSCLK_FREQ_HSE
|
||||
static void SetSysClockToHSE( void );
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSE
|
||||
static void SetSysClockTo48_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSE
|
||||
static void SetSysClockTo56_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSE
|
||||
static void SetSysClockTo72_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSE
|
||||
static void SetSysClockTo96_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSE
|
||||
static void SetSysClockTo120_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSE
|
||||
static void SetSysClockTo144_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSI
|
||||
static void SetSysClockTo48_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSI
|
||||
static void SetSysClockTo56_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSI
|
||||
static void SetSysClockTo72_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSI
|
||||
static void SetSysClockTo96_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSI
|
||||
static void SetSysClockTo120_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSI
|
||||
static void SetSysClockTo144_HSI( void );
|
||||
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SystemInit
|
||||
*
|
||||
* @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
|
||||
* the PLL and update the SystemCoreClock variable.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void SystemInit (void)
|
||||
{
|
||||
RCC->CTLR |= (uint32_t)0x00000001;
|
||||
RCC->CFGR0 &= (uint32_t)0xF8FF0000;
|
||||
RCC->CTLR &= (uint32_t)0xFEF6FFFF;
|
||||
RCC->CTLR &= (uint32_t)0xFFFBFFFF;
|
||||
RCC->CFGR0 &= (uint32_t)0xFF80FFFF;
|
||||
RCC->INTR = 0x009F0000;
|
||||
SetSysClock();
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SystemCoreClockUpdate
|
||||
*
|
||||
* @brief Update SystemCoreClock variable according to Clock Register Values.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void SystemCoreClockUpdate (void)
|
||||
{
|
||||
uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0;
|
||||
|
||||
tmp = RCC->CFGR0 & RCC_SWS;
|
||||
|
||||
switch (tmp)
|
||||
{
|
||||
case 0x00:
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
case 0x04:
|
||||
SystemCoreClock = HSE_VALUE;
|
||||
break;
|
||||
case 0x08:
|
||||
pllmull = RCC->CFGR0 & RCC_PLLMULL;
|
||||
pllsource = RCC->CFGR0 & RCC_PLLSRC;
|
||||
pllmull = ( pllmull >> 18) + 2;
|
||||
|
||||
if(pllmull == 17) pllmull = 18;
|
||||
|
||||
if (pllsource == 0x00)
|
||||
{
|
||||
if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE){
|
||||
SystemCoreClock = HSI_VALUE * pllmull;
|
||||
}
|
||||
else{
|
||||
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (CH32V20x_D8W)
|
||||
if((RCC->CFGR0 & (3<<22)) == (3<<22))
|
||||
{
|
||||
SystemCoreClock = ((HSE_VALUE>>1)) * pllmull;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
|
||||
{
|
||||
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
|
||||
SystemCoreClock = ((HSE_VALUE>>2) >> 1) * pllmull;
|
||||
#else
|
||||
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
|
||||
SystemCoreClock = (HSE_VALUE>>2) * pllmull;
|
||||
#else
|
||||
SystemCoreClock = HSE_VALUE * pllmull;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2);
|
||||
|
||||
break;
|
||||
default:
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
|
||||
SystemCoreClock >>= tmp;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClock
|
||||
*
|
||||
* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClock(void)
|
||||
{
|
||||
#ifdef SYSCLK_FREQ_HSE
|
||||
SetSysClockToHSE();
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSE
|
||||
SetSysClockTo48_HSE();
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSE
|
||||
SetSysClockTo56_HSE();
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSE
|
||||
SetSysClockTo72_HSE();
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSE
|
||||
SetSysClockTo96_HSE();
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSE
|
||||
SetSysClockTo120_HSE();
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSE
|
||||
SetSysClockTo144_HSE();
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSI
|
||||
SetSysClockTo48_HSI();
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSI
|
||||
SetSysClockTo56_HSI();
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSI
|
||||
SetSysClockTo72_HSI();
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSI
|
||||
SetSysClockTo96_HSI();
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSI
|
||||
SetSysClockTo120_HSI();
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSI
|
||||
SetSysClockTo144_HSI();
|
||||
|
||||
#endif
|
||||
|
||||
/* If none of the define above is enabled, the HSI is used as System clock
|
||||
* source (default after reset)
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
#ifdef SYSCLK_FREQ_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockToHSE
|
||||
*
|
||||
* @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockToHSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
|
||||
|
||||
/* Select HSE as system clock source
|
||||
* CH32V20x_D6 (HSE=8MHZ)
|
||||
* CH32V20x_D8 (HSE=32MHZ)
|
||||
* CH32V20x_D8W (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
|
||||
|
||||
/* Wait till HSE is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo48_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo48_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo56_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo56_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo72_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo72_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo96_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo96_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo120_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo120_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if(HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
#if defined (CH32V20x_D8W)
|
||||
RCC->CFGR0 |= (uint32_t)(3<<22);
|
||||
/* HCLK = SYSCLK/2 */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2;
|
||||
#else
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
#endif
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 15 = 120 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/2 * 15 = 240 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo144_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo144_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo48_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo48_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo56_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo56_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 7 = 48 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo72_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo72_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo96_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo96_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 12 = 96 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo120_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo120_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 15 = 120 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo144_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo144_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 18 = 144 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : system_ch32v20x.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : CH32V20x Device Peripheral Access Layer System Header File.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#ifndef __SYSTEM_ch32v20x_H
|
||||
#define __SYSTEM_ch32v20x_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
|
||||
|
||||
/* System_Exported_Functions */
|
||||
extern void SystemInit(void);
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__CH32V20x_SYSTEM_H */
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user