stm32: Add support for USB on L0 MCUs.

This commit is contained in:
Damien George 2019-07-16 14:45:53 +10:00
parent 788e7f50f2
commit 4c1ad1f691
6 changed files with 100 additions and 6 deletions

View File

@ -331,12 +331,17 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\
hal_uart.c \
)
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4))
SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\
ll_usb.c \
)
endif
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l4))
SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\
hal_sd.c \
ll_sdmmc.c \
ll_fmc.c \
ll_usb.c \
)
endif

View File

@ -79,6 +79,17 @@ static inline void restore_irq_pri(uint32_t basepri) {
__set_BASEPRI(basepri);
}
#else
static inline uint32_t raise_irq_pri(uint32_t pri) {
return disable_irq();
}
// "state" should be the value returned from raise_irq_pri
static inline void restore_irq_pri(uint32_t state) {
enable_irq(state);
}
#endif
MP_DECLARE_CONST_FUN_OBJ_0(pyb_wfi_obj);

View File

@ -98,6 +98,27 @@ void SystemClock_Config(void) {
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
#if MICROPY_HW_ENABLE_RNG || MICROPY_HW_ENABLE_USB
// Enable the 48MHz internal oscillator
RCC->CRRCR |= RCC_CRRCR_HSI48ON;
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48;
while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY)) {
// Wait for HSI48 to be ready
}
// Select RC48 as HSI48 for USB and RNG
RCC->CCIPR |= RCC_CCIPR_HSI48SEL;
#if MICROPY_HW_ENABLE_USB
// Synchronise HSI48 with 1kHz USB SoF
__HAL_RCC_CRS_CLK_ENABLE();
CRS->CR = 0x20 << CRS_CR_TRIM_Pos;
CRS->CFGR = 2 << CRS_CFGR_SYNCSRC_Pos | 0x22 << CRS_CFGR_FELIM_Pos
| __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000) << CRS_CFGR_RELOAD_Pos;
#endif
#endif
}
#endif

View File

@ -298,6 +298,16 @@ void DebugMon_Handler(void) {
/* file (startup_stm32f4xx.s). */
/******************************************************************************/
#if defined(STM32L0)
#if MICROPY_HW_USB_FS
void USB_IRQHandler(void) {
HAL_PCD_IRQHandler(&pcd_fs_handle);
}
#endif
#else
/**
* @brief This function handles USB-On-The-Go FS global interrupt request.
* @param None
@ -405,6 +415,8 @@ void OTG_HS_WKUP_IRQHandler(void) {
}
#endif
#endif // !defined(STM32L0)
/**
* @brief This function handles PPP interrupt request.
* @param None

View File

@ -140,11 +140,14 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t* pbuf, ui
if (length & 1) {
// The actual connection state is delayed to give the host a chance to
// configure its serial port (in most cases to disable local echo)
PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData;
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTING;
usbd_cdc_connect_tx_timer = 8; // wait for 8 SOF IRQs
USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM;
#if defined(STM32L0)
USB->CNTR |= USB_CNTR_SOFM;
#else
PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData;
hpcd->Instance->GINTMSK |= USB_OTG_GINTMSK_SOFM;
#endif
} else {
cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED;
}
@ -216,7 +219,11 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
--usbd_cdc_connect_tx_timer;
} else {
usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData;
#if defined(STM32L0)
USB->CNTR &= ~USB_CNTR_SOFM;
#else
hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM;
#endif
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc[i];
if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) {

View File

@ -44,6 +44,11 @@ PCD_HandleTypeDef pcd_fs_handle;
PCD_HandleTypeDef pcd_hs_handle;
#endif
#if defined(STM32L0)
// The STM32L0xx has a single USB device-only instance
#define USB_OTG_FS USB
#endif
/*******************************************************************************
PCD BSP Routines
*******************************************************************************/
@ -57,6 +62,8 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
if (hpcd->Instance == USB_OTG_FS) {
#if defined(STM32H7)
const uint32_t otg_alt = GPIO_AF10_OTG1_FS;
#elif defined(STM32L0)
const uint32_t otg_alt = GPIO_AF0_USB;
#else
const uint32_t otg_alt = GPIO_AF10_OTG_FS;
#endif
@ -83,7 +90,11 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
#endif
// Enable USB FS Clocks
#if defined(STM32L0)
__HAL_RCC_USB_CLK_ENABLE();
#else
__USB_OTG_FS_CLK_ENABLE();
#endif
#if defined(STM32L4)
// Enable VDDUSB
@ -97,8 +108,13 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
#endif
// Configure and enable USB FS interrupt
#if defined(STM32L0)
NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS);
HAL_NVIC_EnableIRQ(USB_IRQn);
#else
NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS);
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
#endif
}
#if MICROPY_HW_USB_HS
else if (hpcd->Instance == USB_OTG_HS) {
@ -174,6 +190,10 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
* @retval None
*/
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) {
#if defined(STM32L0)
__HAL_RCC_USB_CLK_DISABLE();
#else
if (hpcd->Instance == USB_OTG_FS) {
/* Disable USB FS Clocks */
__USB_OTG_FS_CLK_DISABLE();
@ -186,6 +206,8 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) {
__SYSCFG_CLK_DISABLE();
}
#endif
#endif
}
/*******************************************************************************
@ -339,9 +361,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
#else
pcd_fs_handle.Init.dev_endpoints = 4;
#endif
pcd_fs_handle.Init.use_dedicated_ep1 = 0;
pcd_fs_handle.Init.ep0_mps = 0x40;
pcd_fs_handle.Init.dma_enable = 0;
pcd_fs_handle.Init.low_power_enable = 0;
pcd_fs_handle.Init.phy_itface = PCD_PHY_EMBEDDED;
pcd_fs_handle.Init.Sof_enable = 0;
@ -350,11 +370,15 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
pcd_fs_handle.Init.lpm_enable = DISABLE;
pcd_fs_handle.Init.battery_charging_enable = DISABLE;
#endif
#if !defined(STM32L0)
pcd_fs_handle.Init.use_dedicated_ep1 = 0;
pcd_fs_handle.Init.dma_enable = 0;
#if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
pcd_fs_handle.Init.vbus_sensing_enable = 0; // No VBUS Sensing on USB0
#else
pcd_fs_handle.Init.vbus_sensing_enable = 1;
#endif
#endif
// Link The driver to the stack
pcd_fs_handle.pData = pdev;
@ -363,6 +387,18 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
// Initialize LL Driver
HAL_PCD_Init(&pcd_fs_handle);
#if defined(STM32L0)
// We have 512 16-bit words it total to use here (when using PCD_SNG_BUF)
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x00, PCD_SNG_BUF, 64); // EP0
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x80, PCD_SNG_BUF, 128); // EP0
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x01, PCD_SNG_BUF, 192); // MSC / HID
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x81, PCD_SNG_BUF, 256); // MSC / HID
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x02, PCD_SNG_BUF, 320); // unused
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x82, PCD_SNG_BUF, 320); // CDC CMD
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x03, PCD_SNG_BUF, 384); // CDC DATA
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x83, PCD_SNG_BUF, 448); // CDC DATA
#else
// We have 320 32-bit words in total to use here
#if MICROPY_HW_USB_CDC_NUM == 2
HAL_PCD_SetRxFiFo(&pcd_fs_handle, 128);
@ -379,6 +415,8 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 2, 32); // CDC CMD
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 3, 64); // CDC DATA
#endif
#endif
}
#endif
#if MICROPY_HW_USB_HS