diff --git a/source/Core/BSP/Pine64/Setup.cpp b/source/Core/BSP/Pine64/Setup.cpp index 76bd8260d2..9f82253d2f 100644 --- a/source/Core/BSP/Pine64/Setup.cpp +++ b/source/Core/BSP/Pine64/Setup.cpp @@ -9,6 +9,7 @@ #include "Debug.h" #include "Pins.h" #include "gd32vf103.h" +#include "usb.h" #include #define ADC_NORM_CHANNELS 2 #define ADC_NORM_SAMPLES 32 @@ -42,6 +43,8 @@ void hardware_init() { /* enable TIMER1 - PWM control timing*/ timer_enable(TIMER1); timer_enable(TIMER2); + + setup_usb(); } // channel 0 -> temperature sensor, 1-> VIN uint16_t getADC(uint8_t channel) { diff --git a/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Include/gd32vf103.h b/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Include/gd32vf103.h index c8a2fcc814..a14b316a3a 100644 --- a/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Include/gd32vf103.h +++ b/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Include/gd32vf103.h @@ -211,6 +211,7 @@ typedef enum EXCn { #define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ #define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) +#define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000) #define RTC_FREQ LXTAL_VALUE // The TIMER frequency is just the RTC frequency diff --git a/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Source/system_gd32vf103.c b/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Source/system_gd32vf103.c index fcb8786c56..96874a58f2 100644 --- a/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Source/system_gd32vf103.c +++ b/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Source/system_gd32vf103.c @@ -33,7 +33,7 @@ /* ToDo: add here your necessary defines for device initialization following is an example for different system frequencies */ #ifndef SYSTEM_CLOCK -#define SYSTEM_CLOCK __SYSTEM_CLOCK_108M_PLL_HXTAL +#define SYSTEM_CLOCK __SYSTEM_CLOCK_96M_PLL_HXTAL #endif /** @@ -80,12 +80,80 @@ * program is not using it. Debugging systems require the variable to be physically * present in memory so that it can be examined to configure the debugger. */ -uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL; /* System Clock Frequency (Core Clock) */ +uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL; /* System Clock Frequency (Core Clock) */ /*---------------------------------------------------------------------------- Clock functions *----------------------------------------------------------------------------*/ +static void system_clock_96m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + if(HXTAL_VALUE==25000000){ + + /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + }else if(HXTAL_VALUE==8000000){ + /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); + + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 ); + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + /*! \brief configure the system clock to 108M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source \param[in] none @@ -172,7 +240,7 @@ static void system_clock_108m_hxtal(void) { \param[out] none \retval none */ -static void system_clock_config(void) { system_clock_108m_hxtal(); } +static void system_clock_config(void) { system_clock_96m_hxtal(); } /** * \brief Function to update the variable \ref SystemCoreClock diff --git a/source/Core/BSP/Pine64/usb.c b/source/Core/BSP/Pine64/usb.c new file mode 100644 index 0000000000..a028860a50 --- /dev/null +++ b/source/Core/BSP/Pine64/usb.c @@ -0,0 +1,195 @@ +#include "drv_usb_dev.h" +#include "drv_usb_hw.h" +#include "drv_usbd_int.h" +#include "drv_usb_core.h" +#include "usbd_core.h" +#include "usbd_enum.h" + +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#define USBD_VID 0x0001U +#define USBD_PID 0x0001U +#define USB_DFU_CLASS 0xFEU +#define USB_DFU_SUBCLASS_UPGRADE 0x01U +#define USB_DFU_PROTOCOL_DFU 0x01U + + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +/* USB dfu function descriptor structure */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU Specification release. */ +} usb_desc_dfu_func; + + +/* USB configuration descriptor structure */ +typedef struct { + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + + +static const usb_desc_dev dfu_runtime_dev = { + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x00U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +static const usb_desc_LANGID desc_LANGID_ENG = { + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID, +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = { + .header = { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'M', 'e'}, +}; + +/* USB product string */ +static const usb_desc_str product_string = { + .header = { + .bLength = USB_STRING_LEN(7U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'P', 'i', 'n', 'e', 'c', 'i', 'l'}, +}; + +/* USBD serial string */ +static usb_desc_str serial_string = { + .header = { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static const usb_desc_str config_string = { + .header = { + .bLength = USB_STRING_LEN(6U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'C', 'O', 'N', 'F', 'I', 'G'}, +}; + +static const usb_desc_str interface_string = { + .header = { + .bLength = USB_STRING_LEN(3U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'I', 'T', 'F'}, +}; + +static const usb_dfu_desc_config_set dfu_runtime_config = { + .config = { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = sizeof(usb_dfu_desc_config_set), + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = STR_IDX_CONFIG, + .bmAttributes = 0b01000000, + .bMaxPower = 0x32U, + }, + .dfu_itf = { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + // FIXME do we really need the transfersize and interface + // string in runtime mode?? + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCOL_DFU, + .iInterface = STR_IDX_ITF, + }, + .dfu_func = { + .header = { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = 0x21, + }, + .bmAttributes = 0b00001011, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = 2048, + .bcdDFUVersion = 0x011AU, + }, +}; + +static void *const dfu_runtime_strings[] = { + [STR_IDX_LANGID] = (uint8_t *)&desc_LANGID_ENG, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string, +}; + +static const usb_desc dfu_runtime = { + .dev_desc = (uint8_t *)&dfu_runtime_dev, + .config_desc = (uint8_t *)&dfu_runtime_config, + .strings = dfu_runtime_strings, +}; + +static usb_core_driver driver = { + .dev.desc = (uint8_t *)&dfu_runtime, +}; + +static uint8_t dfu_runtime_init (usb_dev *udev, uint8_t config_index) +{ + return USBD_OK; +} +#define dfu_runtime_deinit dfu_runtime_init + +static uint8_t dfu_runtime_req_handler (usb_dev *udev, usb_req *req) +{ + return USBD_OK; +} + +static usb_class_core dfu_runtime_class = { + .init = dfu_runtime_init, + .deinit = dfu_runtime_deinit, + .req_proc = dfu_runtime_req_handler, +}; + +void setup_usb(void) { + usb_timer_init(); + usb_rcu_config(); + usbd_init(&driver, USB_CORE_ENUM_FS, &dfu_runtime_class); + usb_intr_config(); +} + +void USBFS_IRQHandler (void) { + usbd_isr (&driver); +} diff --git a/source/Core/BSP/Pine64/usb.h b/source/Core/BSP/Pine64/usb.h new file mode 100644 index 0000000000..e4661db65c --- /dev/null +++ b/source/Core/BSP/Pine64/usb.h @@ -0,0 +1,9 @@ +#ifdef __cplusplus +extern "C" { +#endif + +void setup_usb(void); + +#ifdef __cplusplus +} +#endif diff --git a/source/NOTES b/source/NOTES new file mode 100644 index 0000000000..31505562d5 --- /dev/null +++ b/source/NOTES @@ -0,0 +1,2 @@ +fails/hangs in +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs)