Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] add DFU runtime #858

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions source/Core/BSP/Pine64/Setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Debug.h"
#include "Pins.h"
#include "gd32vf103.h"
#include "usb.h"
#include <string.h>
#define ADC_NORM_CHANNELS 2
#define ADC_NORM_SAMPLES 32
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
195 changes: 195 additions & 0 deletions source/Core/BSP/Pine64/usb.c
Original file line number Diff line number Diff line change
@@ -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);
}
9 changes: 9 additions & 0 deletions source/Core/BSP/Pine64/usb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifdef __cplusplus
extern "C" {
#endif

void setup_usb(void);

#ifdef __cplusplus
}
#endif
2 changes: 2 additions & 0 deletions source/NOTES
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fails/hangs in
usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs)