/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* STM32F072-discovery board configuration */ #include "common.h" #include "ec_version.h" #include "gpio.h" #include "hooks.h" #include "queue_policies.h" #include "registers.h" #include "spi.h" #include "task.h" #include "usart-stm32f0.h" #include "usart_tx_dma.h" #include "usart_rx_dma.h" #include "usb_gpio.h" #include "usb_spi.h" #include "usb-stream.h" #include "util.h" /****************************************************************************** * Build GPIO tables and expose a subset of the GPIOs over USB. */ void button_event(enum gpio_signal signal); #include "gpio_list.h" static enum gpio_signal const usb_gpio_list[] = { GPIO_USER_BUTTON, GPIO_LED_U, GPIO_LED_D, GPIO_LED_L, GPIO_LED_R, }; /* * This instantiates struct usb_gpio_config const usb_gpio, plus several other * variables, all named something beginning with usb_gpio_ */ USB_GPIO_CONFIG(usb_gpio, usb_gpio_list, USB_IFACE_GPIO, USB_EP_GPIO); /****************************************************************************** * Setup USART1 as a loopback device, it just echo's back anything sent to it. */ static struct usart_config const loopback_usart; static struct queue const loopback_queue = QUEUE_DIRECT(64, uint8_t, loopback_usart.producer, loopback_usart.consumer); static struct usart_rx_dma const loopback_rx_dma = USART_RX_DMA(STM32_DMAC_CH3, 8); static struct usart_tx_dma const loopback_tx_dma = USART_TX_DMA(STM32_DMAC_CH2, 16); static struct usart_config const loopback_usart = USART_CONFIG(usart1_hw, loopback_rx_dma.usart_rx, loopback_tx_dma.usart_tx, 115200, loopback_queue, loopback_queue); /****************************************************************************** * Forward USART4 as a simple USB serial interface. */ static struct usart_config const forward_usart; struct usb_stream_config const forward_usb; static struct queue const usart_to_usb = QUEUE_DIRECT(64, uint8_t, forward_usart.producer, forward_usb.consumer); static struct queue const usb_to_usart = QUEUE_DIRECT(64, uint8_t, forward_usb.producer, forward_usart.consumer); static struct usart_tx_dma const forward_tx_dma = USART_TX_DMA(STM32_DMAC_CH7, 16); static struct usart_config const forward_usart = USART_CONFIG(usart4_hw, usart_rx_interrupt, forward_tx_dma.usart_tx, 115200, usart_to_usb, usb_to_usart); #define USB_STREAM_RX_SIZE 16 #define USB_STREAM_TX_SIZE 16 USB_STREAM_CONFIG(forward_usb, USB_IFACE_STREAM, USB_STR_STREAM_NAME, USB_EP_STREAM, USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, usb_to_usart, usart_to_usb) /****************************************************************************** * Handle button presses by cycling the LEDs on the board. Also run a tick * handler to cycle them when they are not actively under USB control. */ void button_event(enum gpio_signal signal) { static int count; gpio_set_level(GPIO_LED_U, (count & 0x03) == 0); gpio_set_level(GPIO_LED_R, (count & 0x03) == 1); gpio_set_level(GPIO_LED_D, (count & 0x03) == 2); gpio_set_level(GPIO_LED_L, (count & 0x03) == 3); count++; } void usb_gpio_tick(void) { if (usb_gpio.state->set_mask || usb_gpio.state->clear_mask) return; button_event(0); } DECLARE_HOOK(HOOK_TICK, usb_gpio_tick, HOOK_PRIO_DEFAULT); /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { [USB_STR_DESC] = usb_string_desc, [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), [USB_STR_PRODUCT] = USB_STRING_DESC("discovery-stm32f072"), [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), [USB_STR_STREAM_NAME] = USB_STRING_DESC("Forward"), [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Shell"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); /****************************************************************************** * Support SPI bridging over USB, this requires usb_spi_board_enable and * usb_spi_board_disable to be defined to enable and disable the SPI bridge. */ /* SPI devices */ const struct spi_device_t spi_devices[] = { { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS}, }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); void usb_spi_board_enable(struct usb_spi_config const *config) { /* Remap SPI2 to DMA channels 6 and 7 */ STM32_SYSCFG_CFGR1 |= (1 << 24); /* Configure SPI GPIOs */ gpio_config_module(MODULE_SPI_FLASH, 1); /* Set all four SPI pins to high speed */ STM32_GPIO_OSPEEDR(GPIO_B) |= 0xff000000; /* Enable clocks to SPI2 module */ STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; /* Reset SPI2 */ STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; spi_enable(CONFIG_SPI_FLASH_PORT, 1); } void usb_spi_board_disable(struct usb_spi_config const *config) { spi_enable(CONFIG_SPI_FLASH_PORT, 0); /* Disable clocks to SPI2 module */ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; /* Release SPI GPIOs */ gpio_config_module(MODULE_SPI_FLASH, 0); } USB_SPI_CONFIG(usb_spi, USB_IFACE_SPI, USB_EP_SPI); /****************************************************************************** * Initialize board. */ static void board_init(void) { gpio_enable_interrupt(GPIO_USER_BUTTON); queue_init(&loopback_queue); queue_init(&usart_to_usb); queue_init(&usb_to_usart); usart_init(&loopback_usart); usart_init(&forward_usart); usb_spi_enable(&usb_spi, 1); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);