diff --git a/src/stm32/fdcan.c b/src/stm32/fdcan.c index a1624f8..5344d26 100644 --- a/src/stm32/fdcan.c +++ b/src/stm32/fdcan.c @@ -60,16 +60,23 @@ || CONFIG_STM32_CANBUS_PB5_PB6 ||CONFIG_STM32_CANBUS_PB12_PB13) #define SOC_CAN FDCAN1 #define MSG_RAM (((struct fdcan_ram_layout*)SRAMCAN_BASE)->fdcan1) + #if CONFIG_MACH_STM32H7 || CONFIG_MACH_STM32G4 + #define CAN_IT0_IRQn FDCAN1_IT0_IRQn + #endif #else #define SOC_CAN FDCAN2 #define MSG_RAM (((struct fdcan_ram_layout*)SRAMCAN_BASE)->fdcan2) + #if CONFIG_MACH_STM32H7 || CONFIG_MACH_STM32G4 + #define CAN_IT0_IRQn FDCAN2_IT0_IRQn + #endif #endif #if CONFIG_MACH_STM32G0 #define CAN_IT0_IRQn TIM16_FDCAN_IT0_IRQn #define CAN_FUNCTION GPIO_FUNCTION(3) // Alternative function mapping number -#elif CONFIG_MACH_STM32H7 || CONFIG_MACH_STM32G4 - #define CAN_IT0_IRQn FDCAN1_IT0_IRQn +#endif + +#if CONFIG_MACH_STM32H7 || CONFIG_MACH_STM32G4 #define CAN_FUNCTION GPIO_FUNCTION(9) // Alternative function mapping number #endif @@ -162,10 +169,10 @@ canhw_set_filter(uint32_t id) can_filter(1, id); can_filter(2, id + 1); -#if CONFIG_MACH_STM32G0 +#if CONFIG_MACH_STM32G0 || CONFIG_MACH_STM32G4 SOC_CAN->RXGFC = ((id ? 3 : 1) << FDCAN_RXGFC_LSS_Pos | 0x02 << FDCAN_RXGFC_ANFS_Pos); -#elif CONFIG_MACH_STM32H7 || CONFIG_MAC_STM32G4 +#elif CONFIG_MACH_STM32H7 uint32_t flssa = (uint32_t)MSG_RAM.FLS - SRAMCAN_BASE; SOC_CAN->SIDFC = flssa | ((id ? 3 : 1) << FDCAN_SIDFC_LSS_Pos); SOC_CAN->GFC = 0x02 << FDCAN_GFC_ANFS_Pos; @@ -293,7 +300,7 @@ can_init(void) SOC_CAN->NBTP = btr; -#if CONFIG_MACH_STM32H7 || CONFIG_MAC_STM32G4 +#if CONFIG_MACH_STM32H7 /* Setup message RAM addresses */ uint32_t f0sa = (uint32_t)MSG_RAM.RXF0 - SRAMCAN_BASE; SOC_CAN->RXF0C = f0sa | (ARRAY_SIZE(MSG_RAM.RXF0) << FDCAN_RXF0C_F0S_Pos); diff --git a/src/stm32/stm32f0_serial.c b/src/stm32/stm32f0_serial.c index 4f6495f..c987f14 100644 --- a/src/stm32/stm32f0_serial.c +++ b/src/stm32/stm32f0_serial.c @@ -68,7 +68,7 @@ DECL_CONSTANT_STR("RESERVE_PINS_serial", "PD9,PD8"); #define GPIO_Rx GPIO('D', 9) #define GPIO_Tx GPIO('D', 8) - #define USARTx_FUNCTION GPIO_FUNCTION(7) + #define USARTx_FUNCTION GPIO_FUNCTION(CONFIG_MACH_STM32G0 ? 0 : 7) #define USARTx USART3 #define USARTx_IRQn USART3_IRQn #elif CONFIG_STM32_SERIAL_UART4 @@ -78,6 +78,13 @@ #define USARTx_FUNCTION GPIO_FUNCTION(8) #define USARTx UART4 #define USARTx_IRQn UART4_IRQn +#elif CONFIG_STM32_SERIAL_USART5 + DECL_CONSTANT_STR("RESERVE_PINS_serial", "PD2,PD3"); + #define GPIO_Rx GPIO('D', 2) + #define GPIO_Tx GPIO('D', 3) + #define USARTx_FUNCTION GPIO_FUNCTION(3) + #define USARTx USART5 + #define USARTx_IRQn USART5_IRQn #endif #if CONFIG_MACH_STM32F031 @@ -90,6 +97,17 @@ // Some of the stm32g0 MCUs have slightly different register names #if CONFIG_MACH_STM32G0B1 #define USART2_IRQn USART2_LPUART2_IRQn + #define USART3_IRQn USART3_4_5_6_LPUART1_IRQn + #define USART4_IRQn USART3_4_5_6_LPUART1_IRQn + #define USART5_IRQn USART3_4_5_6_LPUART1_IRQn + #define USART6_IRQn USART3_4_5_6_LPUART1_IRQn + #endif + #if CONFIG_MACH_STM32G0B0 + #define USART2_IRQn USART2_IRQn + #define USART3_IRQn USART3_4_5_6_IRQn + #define USART4_IRQn USART3_4_5_6_IRQn + #define USART5_IRQn USART3_4_5_6_IRQn + #define USART6_IRQn USART3_4_5_6_IRQn #endif #define USART_CR1_RXNEIE USART_CR1_RXNEIE_RXFNEIE #define USART_CR1_TXEIE USART_CR1_TXEIE_TXFNFIE diff --git a/src/stm32/stm32g0.c b/src/stm32/stm32g0.c index 5802038..819a5ed 100644 --- a/src/stm32/stm32g0.c +++ b/src/stm32/stm32g0.c @@ -32,18 +32,30 @@ lookup_clock_line(uint32_t periph_base) uint32_t bit = 1 << ((periph_base - AHBPERIPH_BASE) / 0x400); return (struct cline){.en=&RCC->AHBENR, .rst=&RCC->AHBRSTR, .bit=bit}; } +#ifdef USART5_BASE + if (periph_base == USART5_BASE) + return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<8}; +#endif +#ifdef USART6_BASE + if (periph_base == USART6_BASE) + return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<9}; +#endif #if defined(FDCAN1_BASE) || defined(FDCAN2_BASE) if ((periph_base == FDCAN1_BASE) || (periph_base == FDCAN2_BASE)) return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<12}; #endif +#ifdef USB_BASE if (periph_base == USB_BASE) return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<13}; +#endif #ifdef CRS_BASE if (periph_base == CRS_BASE) return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<16}; #endif +#ifdef I2C3_BASE if (periph_base == I2C3_BASE) return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<23}; +#endif if (periph_base == TIM1_BASE) return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<11}; if (periph_base == SPI1_BASE) @@ -106,8 +118,11 @@ clock_setup(void) } pllcfgr |= (pll_freq/pll_base) << RCC_PLLCFGR_PLLN_Pos; pllcfgr |= (pll_freq/CONFIG_CLOCK_FREQ - 1) << RCC_PLLCFGR_PLLR_Pos; - pllcfgr |= (pll_freq/FREQ_USB - 1) << RCC_PLLCFGR_PLLQ_Pos; - RCC->PLLCFGR = pllcfgr | RCC_PLLCFGR_PLLREN | RCC_PLLCFGR_PLLQEN; +#ifdef RCC_PLLCFGR_PLLQ + pllcfgr |= ((pll_freq/FREQ_USB - 1) << RCC_PLLCFGR_PLLQ_Pos) + | RCC_PLLCFGR_PLLQEN; +#endif + RCC->PLLCFGR = pllcfgr | RCC_PLLCFGR_PLLREN; RCC->CR |= RCC_CR_PLLON; // Wait for PLL lock @@ -119,8 +134,10 @@ clock_setup(void) while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != (2 << RCC_CFGR_SWS_Pos)) ; +#ifdef USB_BASE // Use PLLQCLK for USB (setting USBSEL=2 works in practice) RCC->CCIPR2 = 2 << RCC_CCIPR2_USBSEL_Pos; +#endif } @@ -146,7 +163,7 @@ void armcm_main(void) { // Disable internal pull-down resistors on UCPDx CCx pins - SYSCFG->CFGR1 |= (SYSCFG_CFGR1_UCPD1_STROBE | SYSCFG_CFGR1_UCPD2_STROBE); + SYSCFG->CFGR1 |= (SYSCFG_CFGR1_UCPD1_STROBE | SYSCFG_CFGR1_UCPD2_STROBE); SCB->VTOR = (uint32_t)VectorTable; // Reset clock registers (in case bootloader has changed them) diff --git a/src/stm32/stm32h7.c b/src/stm32/stm32h7.c index dc9a29d..387e47d 100644 --- a/src/stm32/stm32h7.c +++ b/src/stm32/stm32h7.c @@ -40,6 +40,9 @@ lookup_clock_line(uint32_t periph_base) uint32_t bit = 1 << ((periph_base - D2_AHB2PERIPH_BASE) / 0x400); return (struct cline){.en=&RCC->AHB2ENR, .rst=&RCC->AHB2RSTR, .bit=bit}; } else if (periph_base >= D2_AHB1PERIPH_BASE) { + if (periph_base == ADC12_COMMON_BASE) + return (struct cline){.en = &RCC->AHB1ENR, .rst = &RCC->AHB1RSTR, + .bit = RCC_AHB1ENR_ADC12EN}; uint32_t bit = 1 << ((periph_base - D2_AHB1PERIPH_BASE) / 0x400); return (struct cline){.en=&RCC->AHB1ENR, .rst=&RCC->AHB1RSTR, .bit=bit}; } else if (periph_base >= D2_APB2PERIPH_BASE) { @@ -231,6 +234,12 @@ armcm_main(void) RCC->D2CCIP1R = 0x00000000; RCC->D2CCIP2R = 0x00000000; RCC->D3CCIPR = 0x00000000; + RCC->APB1LENR = 0x00000000; + RCC->APB1HENR = 0x00000000; + RCC->APB2ENR = 0x00000000; + RCC->APB3ENR = 0x00000000; + RCC->APB4ENR = 0x00000000; + SCB->VTOR = (uint32_t)VectorTable; dfu_reboot_check(); diff --git a/src/stm32/usbfs.c b/src/stm32/usbfs.c index f7559ef..5385c95 100644 --- a/src/stm32/usbfs.c +++ b/src/stm32/usbfs.c @@ -1,6 +1,6 @@ // Hardware interface to "fullspeed USB controller" // -// Copyright (C) 2018-2021 Kevin O'Connor +// Copyright (C) 2018-2023 Kevin O'Connor // // This file may be distributed under the terms of the GNU GPLv3 license. @@ -15,7 +15,7 @@ #include "internal.h" // GPIO #include "sched.h" // DECL_INIT -#if CONFIG_MACH_STM32F103 || CONFIG_MACH_STM32G4 +#if CONFIG_MACH_STM32F1 // Transfer memory is accessed with 32bits, but contains only 16bits of data typedef volatile uint32_t epmword_t; #define WSIZE 2 @@ -25,6 +25,11 @@ typedef volatile uint16_t epmword_t; #define WSIZE 2 #define USBx_IRQn USB_IRQn +#elif CONFIG_MACH_STM32G4 + // Transfer memory is accessed with 16bits and contains 16bits of data + typedef volatile uint16_t epmword_t; + #define WSIZE 2 + #define USBx_IRQn USB_LP_IRQn #elif CONFIG_MACH_STM32G0 // Transfer memory is accessed with 32bits and contains 32bits of data typedef volatile uint32_t epmword_t; @@ -48,6 +53,12 @@ #define USB_CNTR_FRES USB_CNTR_USBRST #endif +// Some chip variants do not define these fields +#ifndef USB_EP_DTOG_TX_Pos +#define USB_EP_DTOG_TX_Pos 6 +#define USB_EP_DTOG_RX_Pos 14 +#endif + /**************************************************************** * USB transfer memory @@ -55,52 +66,50 @@ // Layout of the USB transfer memory #define EPM ((epmword_t*)USB_PMAADDR) -#define EPM_EP_DESC(ep) (&EPM[(ep) * (8 / WSIZE)]) +#define EPM_EP_DESC(ep, bufnum) (&EPM[((ep)*2 + (bufnum)) * (4 / WSIZE)]) #define EPM_BUF_OFFSET 0x10 #define EPM_EP_BUF_SIZE (64 / WSIZE + 1) -#define EPM_EP_TX_BUF(ep) (&EPM[EPM_BUF_OFFSET + (ep)*2*EPM_EP_BUF_SIZE]) -#define EPM_EP_RX_BUF(ep) (&EPM[EPM_BUF_OFFSET + (1+(ep)*2)*EPM_EP_BUF_SIZE]) +#define EPM_EP_BUF(ep, bufnum) \ + (&EPM[EPM_BUF_OFFSET + ((ep)*2 + (bufnum)) * EPM_EP_BUF_SIZE]) +#define BUFTX 0 +#define BUFRX 1 // Configure the usb descriptor for an endpoint static void -epm_ep_desc_setup(int ep, int rx_size) +epm_ep_desc_setup(int ep, int bufnum, int rx_size) { - uint32_t addr_tx = (EPM_EP_TX_BUF(ep) - EPM) * WSIZE, count_tx = 0; - uint32_t addr_rx = (EPM_EP_RX_BUF(ep) - EPM) * WSIZE; + uint32_t addr = (EPM_EP_BUF(ep, bufnum) - EPM) * WSIZE; uint32_t count_rx = (rx_size <= 30 ? DIV_ROUND_UP(rx_size, 2) << 10 : ((DIV_ROUND_UP(rx_size, 32) - 1) << 10) | 0x8000); - epmword_t *desc = EPM_EP_DESC(ep); + epmword_t *desc = EPM_EP_DESC(ep, bufnum); if (WSIZE == 2) { - desc[0] = addr_tx; - desc[1] = count_tx; - desc[2] = addr_rx; - desc[3] = count_rx; + desc[0] = addr; + desc[1] = count_rx; } else { - desc[0] = addr_tx | (count_tx << 16); - desc[1] = addr_rx | (count_rx << 16); + *desc = addr | (count_rx << 16); } } // Return number of read bytes on an rx endpoint static uint32_t -epm_get_ep_count_rx(int ep) +epm_get_ep_count_rx(int ep, int bufnum) { - epmword_t *desc = EPM_EP_DESC(ep); + epmword_t *desc = EPM_EP_DESC(ep, bufnum); if (WSIZE == 2) - return desc[3] & 0x3ff; - return (desc[1] >> 16) & 0x3ff; + return desc[1] & 0x3ff; + return (*desc >> 16) & 0x3ff; } // Set number of bytes ready to be transmitted on a tx endpoint static void -epm_set_ep_count_tx(int ep, uint32_t count) +epm_set_ep_count_tx(int ep, int bufnum, uint32_t count) { - epmword_t *desc = EPM_EP_DESC(ep); + epmword_t *desc = EPM_EP_DESC(ep, bufnum); if (WSIZE == 2) { desc[1] = count; } else { - uint32_t addr_tx = (EPM_EP_TX_BUF(ep) - EPM) * WSIZE; - desc[0] = addr_tx | (count << 16); + uint32_t addr_tx = (EPM_EP_BUF(ep, bufnum) - EPM) * WSIZE; + *desc = addr_tx | (count << 16); } } @@ -108,18 +117,22 @@ epm_set_ep_count_tx(int ep, uint32_t count) static void btable_configure(void) { - epm_ep_desc_setup(0, USB_CDC_EP0_SIZE); - epm_ep_desc_setup(USB_CDC_EP_ACM, 0); - epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, USB_CDC_EP_BULK_OUT_SIZE); - epm_ep_desc_setup(USB_CDC_EP_BULK_IN, 0); + epm_ep_desc_setup(0, BUFTX, 0); + epm_ep_desc_setup(0, BUFRX, USB_CDC_EP0_SIZE); + epm_ep_desc_setup(USB_CDC_EP_ACM, BUFTX, 0); + epm_ep_desc_setup(USB_CDC_EP_ACM, BUFRX, 0); + epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 0, USB_CDC_EP_BULK_OUT_SIZE); + epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 1, USB_CDC_EP_BULK_OUT_SIZE); + epm_ep_desc_setup(USB_CDC_EP_BULK_IN, 0, 0); + epm_ep_desc_setup(USB_CDC_EP_BULK_IN, 1, 0); } // Read a packet stored in dedicated usb memory static uint32_t -btable_read_packet(int ep, uint8_t *dest, int max_len) +btable_read_packet(int ep, int bufnum, uint8_t *dest, int max_len) { - epmword_t *src = EPM_EP_RX_BUF(ep); - uint32_t count = epm_get_ep_count_rx(ep); + epmword_t *src = EPM_EP_BUF(ep, bufnum); + uint32_t count = epm_get_ep_count_rx(ep, bufnum); if (count > max_len) count = max_len; int i; @@ -145,9 +158,9 @@ btable_read_packet(int ep, uint8_t *dest, int max_len) // Write a packet to dedicated usb memory static void -btable_write_packet(int ep, const uint8_t *src, int count) +btable_write_packet(int ep, int bufnum, const uint8_t *src, int count) { - epmword_t *dest = EPM_EP_TX_BUF(ep); + epmword_t *dest = EPM_EP_BUF(ep, bufnum); int i; for (i=0; i> (USB_EP_DTOG_RX_Pos - USB_EP_DTOG_TX_Pos)) ^ epr) + & USB_EP_DTOG_TX); } @@ -202,39 +216,77 @@ set_stat_rxtx_bits(uint32_t epr, uint32_t bits) * USB interface ****************************************************************/ +static uint32_t bulk_out_pop_count, bulk_out_push_flag; + int_fast8_t usb_read_bulk_out(void *data, uint_fast8_t max_len) { - uint32_t epr = USB_EPR[USB_CDC_EP_BULK_OUT]; - if ((epr & USB_EPRX_STAT) == USB_EP_RX_VALID) + if (readl(&bulk_out_push_flag)) // No data ready return -1; - uint32_t count = btable_read_packet(USB_CDC_EP_BULK_OUT, data, max_len); - USB_EPR[USB_CDC_EP_BULK_OUT] = set_stat_rx_bits(epr, USB_EP_RX_VALID); + uint32_t ep = USB_CDC_EP_BULK_OUT; + int bufnum = bulk_out_pop_count & 1; + bulk_out_pop_count++; + uint32_t count = btable_read_packet(ep, bufnum, data, max_len); + writel(&bulk_out_push_flag, USB_EP_DTOG_TX); + + // Check if irq handler pulled another packet before push flag update + uint32_t epr = USB_EPR[ep]; + if (epr_is_dbuf_blocking(epr) && readl(&bulk_out_push_flag)) { + // Second packet was already read - must notify hardware + writel(&bulk_out_push_flag, 0); + USB_EPR[ep] = calc_epr_bits(epr, 0, 0) | USB_EP_DTOG_TX; + } + return count; } +static uint32_t bulk_in_push_pos, bulk_in_pop_flag; +#define BI_START 2 + int_fast8_t usb_send_bulk_in(void *data, uint_fast8_t len) { - uint32_t epr = USB_EPR[USB_CDC_EP_BULK_IN]; - if ((epr & USB_EPTX_STAT) != USB_EP_TX_NAK) + if (readl(&bulk_in_pop_flag)) // No buffer space available return -1; - btable_write_packet(USB_CDC_EP_BULK_IN, data, len); - USB_EPR[USB_CDC_EP_BULK_IN] = set_stat_tx_bits(epr, USB_EP_TX_VALID); + uint32_t ep = USB_CDC_EP_BULK_IN; + uint32_t bipp = bulk_in_push_pos, bufnum = bipp & 1; + bulk_in_push_pos = bipp ^ 1; + btable_write_packet(ep, bufnum, data, len); + writel(&bulk_in_pop_flag, USB_EP_DTOG_RX); + + // Check if hardware needs to be notified + uint32_t epr = USB_EPR[ep]; + if (epr_is_dbuf_blocking(epr) && readl(&bulk_in_pop_flag)) { + writel(&bulk_in_pop_flag, 0); + if (unlikely(bipp & BI_START)) { + // Two packets are always sent when starting in double + // buffering mode, so wait for second packet before starting. + if (bipp == (BI_START | 1)) { + bulk_in_push_pos = 0; + writel(&bulk_in_pop_flag, USB_EP_KIND); // Dummy flag + USB_EPR[ep] = calc_epr_bits(epr, USB_EPTX_STAT + , USB_EP_TX_VALID); + } + } else { + USB_EPR[ep] = calc_epr_bits(epr, 0, 0) | USB_EP_DTOG_RX; + } + } + return len; } int_fast8_t usb_read_ep0(void *data, uint_fast8_t max_len) { - uint32_t epr = USB_EPR[0]; + uint32_t ep = 0, epr = USB_EPR[ep]; if ((epr & USB_EPRX_STAT) != USB_EP_RX_NAK) // No data ready return -1; - uint32_t count = btable_read_packet(0, data, max_len); - USB_EPR[0] = set_stat_rxtx_bits(epr, USB_EP_RX_VALID | USB_EP_TX_NAK); + uint32_t count = btable_read_packet(ep, BUFRX, data, max_len); + USB_EPR[ep] = calc_epr_bits(epr, USB_EPRX_STAT | USB_EPTX_STAT + , USB_EP_RX_VALID | USB_EP_TX_NAK); return count; } @@ -247,23 +299,24 @@ usb_read_ep0_setup(void *data, uint_fast8_t max_len) int_fast8_t usb_send_ep0(const void *data, uint_fast8_t len) { - uint32_t epr = USB_EPR[0]; + uint32_t ep = 0, epr = USB_EPR[ep]; if ((epr & USB_EPRX_STAT) != USB_EP_RX_VALID) // Transfer interrupted return -2; if ((epr & USB_EPTX_STAT) != USB_EP_TX_NAK) // No buffer space available return -1; - btable_write_packet(0, data, len); - USB_EPR[0] = set_stat_tx_bits(epr, USB_EP_TX_VALID); + btable_write_packet(ep, BUFTX, data, len); + USB_EPR[ep] = calc_epr_bits(epr, USB_EPTX_STAT, USB_EP_TX_VALID); return len; } void usb_stall_ep0(void) { - USB_EPR[0] = set_stat_rxtx_bits(USB_EPR[0] - , USB_EP_RX_STALL | USB_EP_TX_STALL); + uint32_t ep = 0, epr = USB_EPR[ep]; + USB_EPR[ep] = calc_epr_bits(epr, USB_EPRX_STAT | USB_EPTX_STAT + , USB_EP_RX_STALL | USB_EP_TX_STALL); } static uint8_t set_address; @@ -278,6 +331,13 @@ usb_set_address(uint_fast8_t addr) void usb_set_configure(void) { + uint32_t ep = USB_CDC_EP_BULK_OUT; + bulk_out_pop_count = 0; + USB_EPR[ep] = calc_epr_bits(USB_EPR[ep], USB_EPRX_STAT, USB_EP_RX_VALID); + + ep = USB_CDC_EP_BULK_IN; + bulk_in_push_pos = BI_START; + writel(&bulk_in_pop_flag, 0); } @@ -289,13 +349,22 @@ usb_set_configure(void) static void usb_reset(void) { - USB_EPR[0] = 0 | USB_EP_CONTROL | USB_EP_RX_VALID | USB_EP_TX_NAK; - USB_EPR[USB_CDC_EP_ACM] = (USB_CDC_EP_ACM | USB_EP_INTERRUPT - | USB_EP_RX_NAK | USB_EP_TX_NAK); - USB_EPR[USB_CDC_EP_BULK_OUT] = (USB_CDC_EP_BULK_OUT | USB_EP_BULK - | USB_EP_RX_VALID | USB_EP_TX_NAK); - USB_EPR[USB_CDC_EP_BULK_IN] = (USB_CDC_EP_BULK_IN | USB_EP_BULK - | USB_EP_RX_NAK | USB_EP_TX_NAK); + uint32_t ep = 0; + USB_EPR[ep] = 0 | USB_EP_CONTROL | USB_EP_RX_VALID | USB_EP_TX_NAK; + + ep = USB_CDC_EP_ACM; + USB_EPR[ep] = (USB_CDC_EP_ACM | USB_EP_INTERRUPT + | USB_EP_RX_NAK | USB_EP_TX_NAK); + + ep = USB_CDC_EP_BULK_OUT; + USB_EPR[ep] = (USB_CDC_EP_BULK_OUT | USB_EP_BULK | USB_EP_KIND + | USB_EP_RX_NAK | USB_EP_DTOG_TX); + bulk_out_push_flag = USB_EP_DTOG_TX; + + ep = USB_CDC_EP_BULK_IN; + USB_EPR[ep] = (USB_CDC_EP_BULK_IN | USB_EP_BULK | USB_EP_KIND + | USB_EP_TX_NAK); + bulk_in_pop_flag = USB_EP_DTOG_RX; USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM; USB->DADDR = USB_DADDR_EF; @@ -308,20 +377,25 @@ USB_IRQHandler(void) uint32_t istr = USB->ISTR; if (istr & USB_ISTR_CTR) { // Endpoint activity - uint32_t ep = istr & USB_ISTR_EP_ID; - uint32_t epr = USB_EPR[ep]; - USB_EPR[ep] = epr & EPR_RWBITS; - if (ep == 0) { + uint32_t ep = istr & USB_ISTR_EP_ID, epr = USB_EPR[ep]; + if (ep == USB_CDC_EP_BULK_OUT) { + USB_EPR[ep] = (calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0) + | bulk_out_push_flag); + bulk_out_push_flag = 0; + usb_notify_bulk_out(); + } else if (ep == USB_CDC_EP_BULK_IN) { + USB_EPR[ep] = (calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0) + | bulk_in_pop_flag); + bulk_in_pop_flag = 0; + usb_notify_bulk_in(); + } else if (ep == 0) { + USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0); usb_notify_ep0(); if (epr & USB_EP_CTR_TX && set_address) { // Apply address after last "in" message transmitted USB->DADDR = set_address; set_address = 0; } - } else if (ep == USB_CDC_EP_BULK_OUT) { - usb_notify_bulk_out(); - } else if (ep == USB_CDC_EP_BULK_IN) { - usb_notify_bulk_in(); } } if (istr & USB_ISTR_RESET) { diff --git a/src/stm32/usbotg.c b/src/stm32/usbotg.c index b61c99c..b2d5245 100644 --- a/src/stm32/usbotg.c +++ b/src/stm32/usbotg.c @@ -397,11 +397,11 @@ OTG_FS_IRQHandler(void) } if (sts & USB_OTG_GINTSTS_IEPINT) { // Can transmit data - disable irq and notify endpoint - uint32_t daint = OTGD->DAINT; - OTGD->DAINTMSK &= ~daint; - if (daint & (1 << 0)) + uint32_t daint = OTGD->DAINT, msk = OTGD->DAINTMSK, pend = daint & msk; + OTGD->DAINTMSK = msk & ~daint; + if (pend & (1 << 0)) usb_notify_ep0(); - if (daint & (1 << USB_CDC_EP_BULK_IN)) + if (pend & (1 << USB_CDC_EP_BULK_IN)) usb_notify_bulk_in(); } } @@ -426,7 +426,7 @@ usb_init(void) OTG->GUSBCFG = (USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL | (6 << USB_OTG_GUSBCFG_TRDT_Pos)); OTGD->DCFG |= (3 << USB_OTG_DCFG_DSPD_Pos); -#if CONFIG_MACH_STM32F446 || CONFIG_MACH_STM32H7 +#if CONFIG_MACH_STM32F446 || CONFIG_MACH_STM32H7 || CONFIG_MACH_STM32F7 OTG->GOTGCTL = USB_OTG_GOTGCTL_BVALOEN | USB_OTG_GOTGCTL_BVALOVAL; #else OTG->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS;