From 359082f80a911a42629c75f8f8198623866588ed Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 18 Apr 2019 17:12:14 +0900 Subject: [PATCH] Testing USB on STM32L4. --- ChangeLog | 2 +- board/board-st-nucleo-f103.h | 6 +- board/board-st-nucleo-l432.h | 28 ++++---- example-cdc/Makefile | 8 +-- example-cdc/board.h | 2 +- example-cdc/sample.ld.m4 | 107 ++++++++++++++++++++++++++++ mcu/clk_gpio_init-stm32l.c | 10 +++ mcu/stm32l.h | 23 +++--- mcu/sys-stm32l4.c | 74 ++++++++++++------- mcu/usb-st-common.c | 2 +- mcu/usb-stm32f103.c | 2 +- mcu/{usb-stm32l.c => usb-stm32l4.c} | 16 ++--- usb_lld.h | 4 ++ 13 files changed, 215 insertions(+), 69 deletions(-) create mode 100644 example-cdc/sample.ld.m4 rename mcu/{usb-stm32l.c => usb-stm32l4.c} (94%) diff --git a/ChangeLog b/ChangeLog index 0a6f159..4e5024f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 2019-04-17 NIIBE Yutaka - * mcu/usb-stm32l.c: New. + * mcu/usb-stm32l4.c: New. * mcu/usb-st-common.c: Factor out from usb-stm32f103.c. 2019-04-12 NIIBE Yutaka diff --git a/board/board-st-nucleo-f103.h b/board/board-st-nucleo-f103.h index 2d60670..5e064ad 100644 --- a/board/board-st-nucleo-f103.h +++ b/board/board-st-nucleo-f103.h @@ -11,8 +11,10 @@ * * At CN10, connect USB cable * Vbus RED --> 10 NC ----------> CN7 (6 E5V) - * D+ GREEN --> 12 PA11 ---[1K5]--> CN6 (4 3V3) - * D- WHITE --> 14 PA12 + * D+ GREEN --> 12 PA12 ---[1K5]--> CN6 (4 3V3) + * D- WHITE --> 14 PA11 + * 16 PB12 (USART3-CK) ---> smartcard CK + * 18 * GND BLACK --> 20 GND */ diff --git a/board/board-st-nucleo-l432.h b/board/board-st-nucleo-l432.h index 95834a0..7a5506b 100644 --- a/board/board-st-nucleo-l432.h +++ b/board/board-st-nucleo-l432.h @@ -8,8 +8,8 @@ * Vbus RED --> 4 * * At CN3, connect USB cable - * D- GREEN --> 13 PA11 - * D+ WHITE --> 5 PA12 + * D- WHITE --> 13 PA11 + * D+ GREEN --> 5 PA12 * GND BLACK --> 4 GND */ @@ -23,25 +23,25 @@ /* * Port A setup. * - * MODER: 10 10 - 10 01 - 01 11 - 10 10 11 11 - 11 11 - 11 10 - 11 11 + * MODER: 10 10 - 10 10 - 10 11 - 10 10 11 11 - 11 11 - 11 10 - 11 11 * - * PA2 - USART2-TX: AF7 - * PA8 - USART1-CK: AF7 - * PA9 - USART1-TX: AF7 Open-drain pull-up - * PA11 - Push Pull output medium-speed 0 (until USB enabled) (USBDM: AF10) - * PA12 - Push Pull output medium-speed 0 (until USB enabled) (USBDP: AF10) - * PA13 - SWDIO - * PA14 - SWDCLK - * PA15 - USART2-RX: AF3 + * PA2 - USART2-TX: AF7 output push-pull + * PA8 - USART1-CK: AF7 output push-pull + * PA9 - USART1-TX: AF7 output(input) Open-drain pull-up + * PA11 - USBDM: AF10 input/output + * PA12 - USBDP: AF10 input/output + * PA13 - SWDIO: AF0 + * PA14 - SWDCLK: AF0 + * PA15 - USART2-RX: AF3 input * ------------------------ Default * PAx - analog input */ -#define VAL_GPIO_OTHER_MODER 0xA97AFFEF +#define VAL_GPIO_OTHER_MODER 0xAABAFFEF #define VAL_GPIO_OTHER_OTYPER 0x00000200 -#define VAL_GPIO_OTHER_OSPEEDR 0xFB7FFFFF +#define VAL_GPIO_OTHER_OSPEEDR 0xFFFFFFFF #define VAL_GPIO_OTHER_PUPDR 0x00040000 #define VAL_GPIO_OTHER_AFRL 0x00000700 -#define VAL_GPIO_OTHER_AFRH 0x30000077 +#define VAL_GPIO_OTHER_AFRH 0x300AA077 /* * Port B setup. diff --git a/example-cdc/Makefile b/example-cdc/Makefile index 1d64f78..5246c42 100644 --- a/example-cdc/Makefile +++ b/example-cdc/Makefile @@ -3,10 +3,10 @@ PROJECT = sample CHOPSTX = .. -LDSCRIPT= sample.ld +LDSCRIPT= sample.ld.m4 CSRC = sample.c usb-cdc.c -CHIP=stm32f103 +CHIP=stm32l4 USE_SYS = yes USE_USB = yes @@ -18,9 +18,9 @@ CC = $(CROSS)gcc LD = $(CROSS)gcc OBJCOPY = $(CROSS)objcopy -MCU = cortex-m3 +MCU = cortex-m4 CWARN = -Wall -Wextra -Wstrict-prototypes -DEFS = -DUSE_SYS3 -DFREE_STANDING -DMHZ=72 +DEFS = -DUSE_SYS3 -DFREE_STANDING -DMHZ=80 OPT = -O3 -Os -g LIBS = diff --git a/example-cdc/board.h b/example-cdc/board.h index b673327..8075a6c 120000 --- a/example-cdc/board.h +++ b/example-cdc/board.h @@ -1 +1 @@ -../board/board-fst-01.h \ No newline at end of file +../board/board-st-nucleo-l432.h \ No newline at end of file diff --git a/example-cdc/sample.ld.m4 b/example-cdc/sample.ld.m4 new file mode 100644 index 0000000..e4b2548 --- /dev/null +++ b/example-cdc/sample.ld.m4 @@ -0,0 +1,107 @@ +/* + * ST32L4 memory setup. + */ +MEMORY +{ + flash : org = 0x08000000, len = 256k + ram : org = 0x20000000, len = 48k +} + +__ram_start__ = ORIGIN(ram); +__ram_size__ = 20k; +__ram_end__ = __ram_start__ + __ram_size__; + +SECTIONS +{ + . = 0; + + _text = .; + + .startup : ALIGN(128) SUBALIGN(128) + { + KEEP(*(.startup.vectors)) + . = ALIGN(16); + _sys = .; + . = ALIGN(16); + KEEP(*(.sys.version)) + KEEP(*(.sys.board_id)) + KEEP(*(.sys.board_name)) + build/sys-*.o(.text) + build/sys-*.o(.text.*) + build/sys-*.o(.rodata) + build/sys-*.o(.rodata.*) + . = ALIGN(1024); + } > flash =0xffffffff + + .text : ALIGN(16) SUBALIGN(16) + { + *(.text.startup.*) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + *(.glue_7t) + *(.glue_7) + *(.gcc*) + . = ALIGN(8); + } > flash + + .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > flash + + .ARM.exidx : { + PROVIDE(__exidx_start = .); + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + PROVIDE(__exidx_end = .); + } > flash + + .eh_frame_hdr : {*(.eh_frame_hdr)} > flash + + .eh_frame : ONLY_IF_RO {*(.eh_frame)} > flash + + .textalign : ONLY_IF_RO { . = ALIGN(8); } > flash + + _etext = .; + _textdata = _etext; + + .stacks (NOLOAD) : + { + *(.main_stack) + *(.process_stack.0) + *(.process_stack.1) + *(.process_stack.2) + *(.process_stack.3) + . = ALIGN(8); + } > ram + + .data : + { + . = ALIGN(4); + PROVIDE(_data = .); + *(.data) + . = ALIGN(4); + *(.data.*) + . = ALIGN(4); + *(.ramtext) + . = ALIGN(4); + PROVIDE(_edata = .); + } > ram AT > flash + + .bss : + { + . = ALIGN(4); + PROVIDE(_bss_start = .); + *(.bss) + . = ALIGN(4); + *(.bss.*) + . = ALIGN(4); + *(COMMON) + . = ALIGN(4); + PROVIDE(_bss_end = .); + } > ram + + PROVIDE(end = .); + _end = .; +} + +__heap_base__ = _end; +__heap_end__ = __ram_end__; diff --git a/mcu/clk_gpio_init-stm32l.c b/mcu/clk_gpio_init-stm32l.c index b3a8ccf..f52740f 100644 --- a/mcu/clk_gpio_init-stm32l.c +++ b/mcu/clk_gpio_init-stm32l.c @@ -55,6 +55,16 @@ clock_init (void) RCC->CFGR |= 0x03; while ((RCC->CFGR & 0x0C) != 0x0C) ; + + /* Peripheral clock selection */ + RCC->CCIPR = ( (0x00 << 26) | /* HSI48 for USB */ + (0x00 << 2) | /* PCLK for USART2 */ + (0x00 << 0) ); /* PCLK for USART1 */ + + /* Enable HSI48 clock */ + RCC->CRRCR |= 1; + while ((RCC->CRRCR & 0x02) == 0) + ; } static struct GPIO *const GPIO_LED = (struct GPIO *)GPIO_LED_BASE; diff --git a/mcu/stm32l.h b/mcu/stm32l.h index 1f60f14..3cc0d59 100644 --- a/mcu/stm32l.h +++ b/mcu/stm32l.h @@ -109,17 +109,10 @@ struct GPIO { }; #define GPIOA_BASE (AHB2PERIPH_BASE) -#define GPIOA ((struct GPIO *) GPIOA_BASE) +static struct GPIO *const GPIOA = (struct GPIO *)GPIOA_BASE; #define GPIOB_BASE (AHB2PERIPH_BASE + 0x0400) -#define GPIOB ((struct GPIO *) GPIOB_BASE) -#define GPIOC_BASE (AHB2PERIPH_BASE + 0x0800) -#define GPIOC ((struct GPIO *) GPIOC_BASE) -#define GPIOD_BASE (AHB2PERIPH_BASE + 0x0C00) -#define GPIOD ((struct GPIO *) GPIOD_BASE) -#define GPIOE_BASE (AHB2PERIPH_BASE + 0x1000) -#define GPIOE ((struct GPIO *) GPIOE_BASE) -#define GPIOH_BASE (AHB2PERIPH_BASE + 0x1C00) -#define GPIOH ((struct GPIO *) GPIOH_BASE) +static struct GPIO *const GPIOB = (struct GPIO *)GPIOB_BASE; + struct FLASH { volatile uint32_t ACR; @@ -139,3 +132,13 @@ struct FLASH { #define FLASH_R_BASE (AHB1PERIPH_BASE + 0x2000) static struct FLASH *const FLASH = (struct FLASH *)FLASH_R_BASE; + +struct USB_STM32L4 { + volatile uint16_t LPMCSR; + volatile uint16_t reserved0; + volatile uint16_t BCDR; + volatile uint16_t reserved1; +}; + +#define USB_STM32L4_BASE (0x40006854UL) +static struct USB_STM32L4 *const USB_STM32L4 = (struct USB_STM32L4 *)USB_STM32L4_BASE; diff --git a/mcu/sys-stm32l4.c b/mcu/sys-stm32l4.c index d5dda21..c494cd6 100644 --- a/mcu/sys-stm32l4.c +++ b/mcu/sys-stm32l4.c @@ -47,16 +47,25 @@ static void wait (int count) void usb_lld_sys_shutdown (void) { + USB_STM32L4->BCDR &= 0x7fff; /* DP disable */ RCC->APB1ENR1 &= ~(RCC_APB1_1_USB | RCC_APB1_1_CRS); RCC->APB1RSTR1 |= (RCC_APB1_1_USB | RCC_APB1_1_CRS); } +struct CRS +{ + volatile uint32_t CR; + volatile uint32_t CFGR; + volatile uint32_t ISR; + volatile uint32_t ICR; +}; +static struct CRS *const CRS = ((struct CRS *)(APB1PERIPH_BASE + 0x6000)); + + void usb_lld_sys_init (void) { - /* XXX: should configure CRS (clock recovery system) and HSI48 clock */ - - if ((RCC->APB1ENR1 & RCC_APB1_1_USB) + if ((RCC->APB1ENR1 & RCC_APB1_1_USB) && (RCC->APB1RSTR1 & RCC_APB1_1_USB) == 0) /* Make sure the device is disconnected, even after core reset. */ { @@ -65,10 +74,46 @@ usb_lld_sys_init (void) wait (5*MHZ); } + /* Enable USB clock and CRC clock */ RCC->APB1ENR1 |= (RCC_APB1_1_USB | RCC_APB1_1_CRS); RCC->APB1RSTR1 = (RCC_APB1_1_USB | RCC_APB1_1_CRS); RCC->APB1RSTR1 = 0; + + USB_STM32L4->BCDR |= 0x8000; /* DP enable */ + + /* Configure CRS (clock recovery system) for HSI48 clock */ + CRS->CFGR = ( (0x00 << 31) | /* Polarity rising */ + (0x02 << 28) | /* USB SOF for Sync */ + (0x00 << 24) | /* divider = 1 */ + (0x22 << 16) | /* Frequency error limit */ + 0xBB7F ); /* Reload value */ + + CRS->CR |= ( (1 << 6) | /* Automatic trimming enable */ + (1 << 5) ); /* Frequency error counter enable */ } + +void +nvic_system_reset (void) +{ + SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SCB_AIRCR_SYSRESETREQ); + asm volatile ("dsb"); + for (;;); +} + +const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = { + 3*2+2, /* bLength */ + 0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */ + /* sys version: "3.0" */ + '3', 0, '.', 0, '0', 0, +}; + +#if defined(USE_SYS3) || defined(USE_SYS_BOARD_ID) +const uint32_t __attribute__((section(".sys.board_id"))) +sys_board_id = BOARD_ID; + +const uint8_t __attribute__((section(".sys.board_name"))) +sys_board_name[] = BOARD_NAME; +#endif /* Not yet implemented, API should be reconsidered */ @@ -133,26 +178,3 @@ flash_erase_all_and_exec (void (*entry)(void)) { (void)entry; } - -void -nvic_system_reset (void) -{ - SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SCB_AIRCR_SYSRESETREQ); - asm volatile ("dsb"); - for (;;); -} - -const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = { - 3*2+2, /* bLength */ - 0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */ - /* sys version: "3.0" */ - '3', 0, '.', 0, '0', 0, -}; - -#if defined(USE_SYS3) || defined(USE_SYS_BOARD_ID) -const uint32_t __attribute__((section(".sys.board_id"))) -sys_board_id = BOARD_ID; - -const uint8_t __attribute__((section(".sys.board_name"))) -sys_board_name[] = BOARD_NAME; -#endif diff --git a/mcu/usb-st-common.c b/mcu/usb-st-common.c index 3005136..179b03a 100644 --- a/mcu/usb-st-common.c +++ b/mcu/usb-st-common.c @@ -41,7 +41,7 @@ struct USB { volatile uint16_t reserved4; }; -struct USB *const USB = (struct USB *)REG_BASE; +static struct USB *const USB = (struct USB *)REG_BASE; #define ISTR_CTR (0x8000) /* Correct TRansfer (read-only bit) */ #define ISTR_OVR (0x4000) /* OVeR/underrun (clear-only bit) */ diff --git a/mcu/usb-stm32f103.c b/mcu/usb-stm32f103.c index 679ae82..8d74499 100644 --- a/mcu/usb-stm32f103.c +++ b/mcu/usb-stm32f103.c @@ -119,7 +119,7 @@ handle_setup0 (struct usb_dev *dev) uint8_t req_no; HANDLER handler; - pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(epbuf_get_rx_addr (ENDP0) * 2)); + pw = (uint16_t *)(PMA_ADDR + (epbuf_get_rx_addr (ENDP0) * 2)); w = *pw++; dev->dev_req.type = (w & 0xff); diff --git a/mcu/usb-stm32l.c b/mcu/usb-stm32l4.c similarity index 94% rename from mcu/usb-stm32l.c rename to mcu/usb-stm32l4.c index 2be2984..c73058c 100644 --- a/mcu/usb-stm32l.c +++ b/mcu/usb-stm32l4.c @@ -1,5 +1,5 @@ /* - * usb-stm32l.c - USB driver for STM32L + * usb-stm32l4.c - USB driver for STM32L4 * * Copyright (C) 2019 Flying Stone Technology * Author: NIIBE Yutaka @@ -29,7 +29,7 @@ #include #include -#include "sys-stm32l.h" +#include "sys-stm32l4.h" #include "usb_lld.h" #include "usb_lld_driver.h" @@ -119,7 +119,7 @@ handle_setup0 (struct usb_dev *dev) uint8_t req_no; HANDLER handler; - pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(epbuf_get_rx_addr (ENDP0))); + pw = (uint16_t *)(PMA_ADDR + epbuf_get_rx_addr (ENDP0)); w = *pw++; dev->dev_req.type = (w & 0xff); @@ -174,22 +174,20 @@ usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n) if ((addr & 1)) { - p = (uint16_t *)(PMA_ADDR + (addr - 1) * 2); + p = (uint16_t *)(PMA_ADDR + (addr - 1)); w = *p; w = (w & 0xff) | (*s++) << 8; - *p = w; - p += 2; + *p++ = w; n--; } else - p = (uint16_t *)(PMA_ADDR + addr * 2); + p = (uint16_t *)(PMA_ADDR + addr); while (n >= 2) { w = *s++; w |= (*s++) << 8; - *p = w; - p += 2; + *p++ = w; n -= 2; } diff --git a/usb_lld.h b/usb_lld.h index ce08f73..7a7961e 100644 --- a/usb_lld.h +++ b/usb_lld.h @@ -153,7 +153,11 @@ void usb_lld_setup_endp (struct usb_dev *dev, int ep_num, int rx_en, int tx_en); void usb_lld_stall_tx (int ep_num); void usb_lld_stall_rx (int ep_num); #else +#if defined(MCU_STM32L4) +#define INTR_REQ_USB 67 +#else #define INTR_REQ_USB 20 +#endif /* EP_TYPE[1:0] EndPoint TYPE */ #define EP_BULK (0x0000) /* EndPoint BULK */ #define EP_CONTROL (0x0200) /* EndPoint CONTROL */