diff --git a/Makefile b/Makefile index beb889e4e8702ef63f284dd65b82a898454d3f63..b589275757e2eaecf30215a1f3b37660176636d6 100644 --- a/Makefile +++ b/Makefile @@ -121,9 +121,11 @@ LDSCRIPT= $(STARTUPLD)/STM32F411xE.ld # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. -CSRC = $(ALLCSRC) \ - $(SRCDIR)/crc32.c \ - $(SRCDIR)/main.c +CSRC = $(ALLCSRC) \ + $(SRCDIR)/crc32.c \ + $(SRCDIR)/main.c \ + $(SRCDIR)/serial.c \ + $(SRCDIR)/usb.c # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/cfg/halconf.h b/cfg/halconf.h index ddb46c0da9da2a2878d77bffe34dd217a7de5a22..fb8be9548eb031b5f212a48e5fb67f09de089276 100644 --- a/cfg/halconf.h +++ b/cfg/halconf.h @@ -142,14 +142,14 @@ * @brief Enables the SERIAL subsystem. */ #if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL TRUE +#define HAL_USE_SERIAL FALSE #endif /** * @brief Enables the SERIAL over USB subsystem. */ #if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL_USB FALSE +#define HAL_USE_SERIAL_USB TRUE #endif /** @@ -184,7 +184,7 @@ * @brief Enables the USB subsystem. */ #if !defined(HAL_USE_USB) || defined(__DOXYGEN__) -#define HAL_USE_USB FALSE +#define HAL_USE_USB TRUE #endif /** @@ -412,7 +412,7 @@ * buffers. */ #if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_BUFFERS_SIZE 16 +#define SERIAL_BUFFERS_SIZE 1 #endif /*===========================================================================*/ @@ -447,7 +447,7 @@ * buffers. */ #if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_USB_BUFFERS_SIZE 256 +#define SERIAL_USB_BUFFERS_SIZE 512 #endif /** diff --git a/cfg/mcuconf.h b/cfg/mcuconf.h index ffb098a57e645e0b0a359abaf55a1bdbcabcb9d1..2c3e198cb51f84d9aed3d68d86a91f4a6d8cfa76 100644 --- a/cfg/mcuconf.h +++ b/cfg/mcuconf.h @@ -39,23 +39,23 @@ * HAL driver system settings. */ #define STM32_NO_INIT FALSE -#define STM32_HSI_ENABLED TRUE -#define STM32_LSI_ENABLED TRUE +#define STM32_HSI_ENABLED FALSE +#define STM32_LSI_ENABLED FALSE #define STM32_HSE_ENABLED TRUE #define STM32_LSE_ENABLED FALSE -#define STM32_CLOCK48_REQUIRED FALSE +#define STM32_CLOCK48_REQUIRED TRUE #define STM32_SW STM32_SW_PLL #define STM32_PLLSRC STM32_PLLSRC_HSE -#define STM32_PLLM_VALUE 8 -#define STM32_PLLN_VALUE 200 -#define STM32_PLLP_VALUE 2 -#define STM32_PLLQ_VALUE 7 +#define STM32_PLLM_VALUE 4 +#define STM32_PLLN_VALUE 192 +#define STM32_PLLP_VALUE 4 +#define STM32_PLLQ_VALUE 8 #define STM32_HPRE STM32_HPRE_DIV1 #define STM32_PPRE1 STM32_PPRE1_DIV4 #define STM32_PPRE2 STM32_PPRE2_DIV2 #define STM32_RTCSEL STM32_RTCSEL_LSI #define STM32_RTCPRE_VALUE 8 -#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1SEL STM32_MCO1SEL_PLL #define STM32_MCO1PRE STM32_MCO1PRE_DIV1 #define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK #define STM32_MCO2PRE STM32_MCO2PRE_DIV5 @@ -261,7 +261,7 @@ * SERIAL driver system settings. */ #define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART2 FALSE #define STM32_SERIAL_USE_USART3 FALSE #define STM32_SERIAL_USE_UART4 FALSE #define STM32_SERIAL_USE_UART5 FALSE @@ -325,7 +325,7 @@ /* * USB driver system settings. */ -#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG1 TRUE #define STM32_USB_USE_OTG2 FALSE #define STM32_USB_OTG1_IRQ_PRIORITY 14 #define STM32_USB_OTG2_IRQ_PRIORITY 14 diff --git a/src/serial.c b/src/serial.c new file mode 100644 index 0000000000000000000000000000000000000000..a688a7c4e0cdef13e00defb3dd960075f98310af --- /dev/null +++ b/src/serial.c @@ -0,0 +1,118 @@ +// This file is part of the execution-time evaluation for the qronos observer abstractions. +// Copyright (C) 2022-2023 Tim Rheinfels <tim.rheinfels@fau.de> +// See https://gitlab.cs.fau.de/qronos-state-abstractions/execution-time +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +/// +/// @file serial.c +/// +/// @brief Provides the implementation of the serial over USB utilities +/// +/// @author Tim Rheinfels (tim.rheinfels@fau.de) +/// + +#include "serial.h" + +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <ch.h> +#include <hal.h> +#include <chprintf.h> + +#include <crc32.h> +#include <usb.h> + +/// +/// @brief Buffer used for formatting output +/// +static char serial_buffer[1024u]; + +void serial_init(void) +{ + +} + +void serial_printf(const char *fmt, ...) +{ + + va_list ap; + va_start(ap, fmt); + size_t n = chvsnprintf(serial_buffer, sizeof(serial_buffer), fmt, ap); + va_end(ap); + + // Check for overruns + osalDbgAssert(n < sizeof(serial_buffer), "line buffer overrun"); + + // Add to checksum and print + for(size_t i = 0u; i < n; ++i) + { + crc32_add(serial_buffer[i]); + } + + // Write to serial driver + size_t written = streamWrite((BaseSequentialStream *) &usb_serial_driver, (const uint8_t *) serial_buffer, n); + osalDbgAssert(n == written, "lost characters"); + +} + +void serial_print_vector(const char *name, float *M, size_t n) +{ + serial_printf("\"%s\": [", name); + for(size_t i = 0u; i < n; ++i) + { + serial_printf("%u,\n", serial_encode(M[i])); + } + serial_printf("],\n"); +} + +void serial_print_matrix(const char *name, float *M, size_t n, size_t m) +{ + serial_printf("\"%s\": [", name); + for(size_t i = 0u; i < n; ++i) + { + serial_printf("["); + for(size_t j = 0u; j < m; ++j) + { + serial_printf("%u,\n", serial_encode(M[i*m+j])); + } + serial_printf("],"); + } + serial_printf("],\n"); +} + +void serial_reset_checksum(void) +{ + + crc32_reset(); + +} + +void serial_print_checksum(void) +{ + + uint32_t checksum = crc32_get(); + + chprintf((BaseSequentialStream *) &usb_serial_driver, "CRC32: 0x%08x\n", checksum); + +} + +uint32_t serial_encode(float f) +{ + uint32_t i; + memcpy(&i, &f, sizeof(i)); + return i; +} diff --git a/src/serial.h b/src/serial.h new file mode 100644 index 0000000000000000000000000000000000000000..55cd2e09adbd7f25bb61a2af244e485e8fab75fd --- /dev/null +++ b/src/serial.h @@ -0,0 +1,83 @@ +// This file is part of the execution-time evaluation for the qronos observer abstractions. +// Copyright (C) 2022-2023 Tim Rheinfels <tim.rheinfels@fau.de> +// See https://gitlab.cs.fau.de/qronos-state-abstractions/execution-time +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +/// +/// @file serial.h +/// +/// @brief Provides the interface for the serial utilities +/// +/// @author Tim Rheinfels (tim.rheinfels@fau.de) +/// + +#ifndef SERIAL_H +#define SERIAL_H + +#include <stddef.h> +#include <stdint.h> + +/// +/// @brief Initializes the serial over USB utilities +/// +void serial_init(void); + +/// +/// @brief Formats the string @p fmt using the variadic parameters and outputs the result via serial over USB +/// +/// @param[in] fmt Format string +/// @param[in] ... Parameters used for the format string @p fmt +/// +void serial_printf(const char *fmt, ...); + +/// +/// @brief Formats the vector @p M of size @p n named @p name and outputs the result via serial over USB +/// +/// @param[in] name Name for the vector +/// @param[in] M Vector data +/// @param[in] n Number of rows +/// +void serial_print_vector(const char *name, float *M, size_t n); + +/// +/// @brief Formats the matrix @p M of size @p n by @p m named @p name and outputs the result via serial over USB +/// +/// @param[in] name Name for the vector +/// @param[in] M Vector data +/// @param[in] n Number of rows +/// @param[in] m Number of columns +/// +void serial_print_matrix(const char *name, float *M, size_t n, size_t m); + +/// +/// @brief Resets the serial checksum +/// +void serial_reset_checksum(void); + +/// +/// @brief Prints the accumulated serial checksum via serial over USB +/// +void serial_print_checksum(void); + +/// +/// @brief Encodes the single-precision float @p f as interger +/// +/// @param[in] f Single-precision float to encode +/// +/// @returns 32-bit unsigned representing the float @p f +/// +uint32_t serial_encode(float f); + +#endif // SERIAL_H diff --git a/src/usb.c b/src/usb.c new file mode 100644 index 0000000000000000000000000000000000000000..27232e5152f18d0ecc49316d0dbdf78934d13ee3 --- /dev/null +++ b/src/usb.c @@ -0,0 +1,423 @@ +// This file is part of the execution-time evaluation for the qronos observer abstractions. +// Copyright (C) 2022-2023 Tim Rheinfels <tim.rheinfels@fau.de> +// See https://gitlab.cs.fau.de/qronos-state-abstractions/execution-time +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +/// +/// @file usb.c +/// +/// @brief Provides the implementation of the USB driver +/// +/// @author Tim Rheinfels <tim.rheinfels@fau.de> +/// + +#include "usb.h" + +#include <ch.h> +#include <hal.h> + +SerialUSBDriver usb_serial_driver; + +/// +/// @brief Flag indicating that a client terminal is connected +/// +static volatile bool active = false; + +// Set USB active flag when SET_CONTROL_LINE_STATE request occurs +/// +/// @brief USB request handler setting the @ref active flag when a SET_CONTROL_LINE_STATE request occurs or passes the request to @ref sduRequestsHook otherwise +/// +/// @param[in] usb USB driver instance +/// +/// @returns Either +/// - true if the USB request was handled or +/// - false otherwise +/// +static bool usb_request_handler(USBDriver *usb) +{ + osalSysLockFromISR(); + uint8_t rtype = usb->setup[0u]; + if(((rtype & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_HOST2DEV) + && (((rtype & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS)) + && (((rtype & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE))) + { + if((usb->setup[1u] == 0x22u)) + { + active = true; + osalSysUnlockFromISR(); + return true; + } + } + + osalSysUnlockFromISR(); + return sduRequestsHook(usb); +} + +// Adapted from chibios-contrib/demo/STM32/RT-STM32F411-DISCOVERY-blinker + +// Forward declarations + +/// +/// @brief USB config structure for ChibiOS/HAL driver +/// +extern const USBConfig usbcfg; + +/// +/// @brief Serial over USB config structure for ChibiOS/HAL driver +/// +extern const SerialUSBConfig serusbcfg; + +#define USBD1_DATA_REQUEST_EP 1 ///< Endpoint for data requests (IN direction) +#define USBD1_DATA_AVAILABLE_EP 1 ///< Endpoint for data available (OUT direction) +#define USBD1_INTERRUPT_REQUEST_EP 2 ///< Endpoint for interrupt requests (IN direction) + +/// +/// @brief USB device descriptor +/// +static const uint8_t vcom_device_descriptor_data[18] = { + USB_DESC_DEVICE (0x0110, /* bcdUSB (1.1). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0xCAFE, /* idVendor. */ + 0xF00D, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/// +/// @brief Wrapper for USB device descriptor +/// +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/// +/// @brief USB configuration descriptor +/// +static const uint8_t vcom_configuration_descriptor_data[67] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(67, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/// +/// @brief Wrapper for USB configuration descriptor +/// +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/// +/// @brief Language descriptor representing U.S. English +/// +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + +/// +/// @brief String descriptor for vendor clear name +/// +static const uint8_t vcom_string1[] = { + USB_DESC_BYTE(38), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + 'i', 0, 'n', 0, 'f', 0, '4', 0, '@', 0, 'F', 0, 'A', 0, 'U', 0, +}; + +/// +/// @brief String descriptor for device clear name +/// +static const uint8_t vcom_string2[] = { + USB_DESC_BYTE(88), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + 'S', 0, 't', 0, 'a', 0, 't', 0, 'e', 0, ' ', 0, + 'A', 0, 'b', 0, 's', 0, 't', 0, 'r', 0, 'a', 0, 'c', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0, 's', 0, ' ', 0, + 'E', 0, 'x', 0, 'e', 0, 'c', 0, 'u', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0, ' ', 0, + 'T', 0, 'i', 0, 'm', 0, 'e', 0, ' ', 0, + 'B', 0, 'e', 0, 'n', 0, 'c', 0, 'h', 0, 'm', 0, 'a', 0, 'r', 0, 'k', 0, +}; + +/// +/// @brief Wrapper for USB string descriptors +/// +static const USBDescriptor vcom_strings[] = { + {sizeof(vcom_string0), vcom_string0}, + {sizeof(vcom_string1), vcom_string1}, + {sizeof(vcom_string2), vcom_string2} +}; + +/// +/// @brief Handles descriptor requests +/// +/// @param[in] usbp USB driver instance +/// @param[in] dtype Descriptor type +/// @param[in] dindex Descriptor index +/// @param[in] lang Language identifier +/// +/// @returns Either +/// - pointer to the requested descriptor of parameters are valid or +/// - NULL otherwise +/// +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 3) + return &vcom_strings[dindex]; + } + return NULL; +} + +/// +/// @brief State for the IN direction of endpoint 1 +/// +static USBInEndpointState ep1instate; + +/// +/// @brief State for the OUT direction of endpoint 1 +/// +static USBOutEndpointState ep1outstate; + +/// +/// @brief Configuration for endpoint 1 +/// +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/// +/// @brief State for the IN direction of endpoint 2 +/// +static USBInEndpointState ep2instate; + +/// +/// @brief Configuration for endpoint 2 +/// +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/// +/// @brief USB event handler for the active flag and SDU driver state +/// +/// @param[in] usbp USB driver instance +/// @param[in] event Event to handle +/// +static void usb_event(USBDriver *usbp, usbevent_t event) { + + switch (event) { + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + active = false; + usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&usb_serial_driver); + + chSysUnlockFromISR(); + return; + case USB_EVENT_RESET: + /* Falls into.*/ + case USB_EVENT_UNCONFIGURED: + /* Falls into.*/ + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + active = false; + sduSuspendHookI(&usb_serial_driver); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + chSysLockFromISR(); + + /* Connection event on wakeup.*/ + sduWakeupHookI(&usb_serial_driver); + + chSysUnlockFromISR(); + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/// +/// @brief Handler for start-of-frame condition calling the SDU sof handler +/// +/// @param[in] usbp USB driver instance +/// +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&usb_serial_driver); + osalSysUnlockFromISR(); +} + +/// +/// @brief USB driver configuration +/// +const USBConfig usbcfg = { + usb_event, + get_descriptor, + usb_request_handler, + sof_handler +}; + +/// +/// @brief Serial over USB driver configuration +/// +const SerialUSBConfig serusbcfg = { + &USBD1, + USBD1_DATA_REQUEST_EP, + USBD1_DATA_AVAILABLE_EP, + USBD1_INTERRUPT_REQUEST_EP +}; + +void usb_init(void) +{ + + palSetPadMode(GPIOA, 11, PAL_MODE_ALTERNATE(10)); + palSetPadMode(GPIOA, 12, PAL_MODE_ALTERNATE(10)); + + sduObjectInit(&usb_serial_driver); + sduStart(&usb_serial_driver, &serusbcfg); + + usbDisconnectBus(&USBD1); + chThdSleepMilliseconds(1000); + usbStart(&USBD1, &usbcfg); + usbConnectBus(&USBD1); + +} + +bool usb_active(void) +{ + return active; +} diff --git a/src/usb.h b/src/usb.h new file mode 100644 index 0000000000000000000000000000000000000000..85a47eddd1cbfb1ca9d1b363a523c6292afdc970 --- /dev/null +++ b/src/usb.h @@ -0,0 +1,51 @@ +// This file is part of the execution-time evaluation for the qronos observer abstractions. +// Copyright (C) 2022-2023 Tim Rheinfels <tim.rheinfels@fau.de> +// See https://gitlab.cs.fau.de/qronos-state-abstractions/execution-time +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +/// +/// @file usb.h +/// +/// @brief Provides the interface for the USB driver +/// +/// @author Tim Rheinfels <tim.rheinfels@fau.de> +/// + +#ifndef USB_H +#define USB_H + +#include <ch.h> +#include <hal.h> + +/// +/// @brief USB serial driver instance +/// +extern SerialUSBDriver usb_serial_driver; + +/// +/// @brief Initializes the USB stack +/// +void usb_init(void); + +/// +/// @brief Checks if there is a terminal attached to the USB over serial driver +/// +/// @returns Either +/// - true if a client terminal is attached or +/// - false otherwise +/// +bool usb_active(void); + +#endif // USB_H