/* mbed Microcontroller Library ******************************************************************************* * Copyright (c) 2015, STMicroelectronics * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* */ /* Notes for Teacup: Copied from $(MBED)/libraries/mbed/targets/hal/TARGET_STM/TARGET_STM32F4/serial_api.c. Used only to get things running quickly. Without serial it's almost impossible to see wether code changes work. Should go away soon, because all this MBED stuff is too bloated for Teacup's purposes. - Prefixed names of #include files with mbed- to match the names of the copies in the Teacup repo. - Wrapped the whole file in #ifdef __ARMEL__ to not cause conflicts with AVR builds. - Prefixed function names with mbed_ to not conflict with Teacup names. - Fixed mbed_uart0_irq() function prototype. */ #ifdef __ARM_STM32F411__ #include "mbed-serial_api.h" #if DEVICE_SERIAL #include "mbed-cmsis_stm32.h" #include "mbed-pinmap.h" #include #include "mbed-PeripheralPins_stm32.h" #define UART_NUM (8) static uint32_t serial_irq_ids[UART_NUM] = {0, 0, 0, 0, 0, 0, 0, 0}; static uart_irq_handler irq_handler; UART_HandleTypeDef UartHandle; int stdio_uart_inited = 0; serial_t stdio_uart; static void mbed_init_uart(serial_t *obj) { UartHandle.Instance = (USART_TypeDef *)(obj->uart); UartHandle.Init.BaudRate = obj->baudrate; UartHandle.Init.WordLength = obj->databits; UartHandle.Init.StopBits = obj->stopbits; UartHandle.Init.Parity = obj->parity; UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; if (obj->pin_rx == NC) { UartHandle.Init.Mode = UART_MODE_TX; } else if (obj->pin_tx == NC) { UartHandle.Init.Mode = UART_MODE_RX; } else { UartHandle.Init.Mode = UART_MODE_TX_RX; } if (HAL_UART_Init(&UartHandle) != HAL_OK) { } } void mbed_serial_init(serial_t *obj, PinName tx, PinName rx) { // Get the peripheral name (UART_1, UART_2, ...) from the pin and assign it to the object obj->uart = UART_2; // Enable USART clock switch (obj->uart) { case UART_1: __HAL_RCC_USART1_CLK_ENABLE(); obj->index = 0; break; case UART_2: __HAL_RCC_USART2_CLK_ENABLE(); obj->index = 1; break; #if defined(USART3_BASE) case UART_3: __HAL_RCC_USART3_CLK_ENABLE(); obj->index = 2; break; #endif #if defined(UART4_BASE) case UART_4: __HAL_RCC_UART4_CLK_ENABLE(); obj->index = 3; break; #endif #if defined(UART5_BASE) case UART_5: __HAL_RCC_UART5_CLK_ENABLE(); obj->index = 4; break; #endif #if defined(USART6_BASE) case UART_6: __HAL_RCC_USART6_CLK_ENABLE(); obj->index = 5; break; #endif #if defined(UART7_BASE) case UART_7: __HAL_RCC_UART7_CLK_ENABLE(); obj->index = 6; break; #endif #if defined(UART8_BASE) case UART_8: __HAL_RCC_UART8_CLK_ENABLE(); obj->index = 7; break; #endif } // Configure the UART pins pin_function(tx, 0x393); pin_mode(tx, PullUp); pin_function(rx, 0x393); pin_mode(rx, PullUp); // Configure UART obj->baudrate = 9600; obj->databits = UART_WORDLENGTH_8B; obj->stopbits = UART_STOPBITS_1; obj->parity = UART_PARITY_NONE; obj->pin_tx = tx; obj->pin_rx = rx; mbed_init_uart(obj); // For stdio management if (obj->uart == STDIO_UART) { stdio_uart_inited = 1; memcpy(&stdio_uart, obj, sizeof(serial_t)); } } void mbed_serial_free(serial_t *obj) { // Reset UART and disable clock switch (obj->uart) { case UART_1: __USART1_FORCE_RESET(); __USART1_RELEASE_RESET(); __USART1_CLK_DISABLE(); break; case UART_2: __USART2_FORCE_RESET(); __USART2_RELEASE_RESET(); __USART2_CLK_DISABLE(); break; #if defined(USART3_BASE) case UART_3: __USART3_FORCE_RESET(); __USART3_RELEASE_RESET(); __USART3_CLK_DISABLE(); break; #endif #if defined(UART4_BASE) case UART_4: __UART4_FORCE_RESET(); __UART4_RELEASE_RESET(); __UART4_CLK_DISABLE(); break; #endif #if defined(UART5_BASE) case UART_5: __UART5_FORCE_RESET(); __UART5_RELEASE_RESET(); __UART5_CLK_DISABLE(); break; #endif #if defined(USART6_BASE) case UART_6: __USART6_FORCE_RESET(); __USART6_RELEASE_RESET(); __USART6_CLK_DISABLE(); break; #endif #if defined(UART7_BASE) case UART_7: __UART7_FORCE_RESET(); __UART7_RELEASE_RESET(); __UART7_CLK_DISABLE(); break; #endif #if defined(UART8_BASE) case UART_8: __UART8_FORCE_RESET(); __UART8_RELEASE_RESET(); __UART8_CLK_DISABLE(); break; #endif } // Configure GPIOs pin_function(obj->pin_tx, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); pin_function(obj->pin_rx, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); serial_irq_ids[obj->index] = 0; } void mbed_serial_baud(serial_t *obj, int baudrate) { obj->baudrate = baudrate; mbed_init_uart(obj); } void mbed_serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) { if (data_bits == 9) { obj->databits = UART_WORDLENGTH_9B; } else { obj->databits = UART_WORDLENGTH_8B; } switch (parity) { case ParityOdd: case ParityForced0: obj->parity = UART_PARITY_ODD; break; case ParityEven: case ParityForced1: obj->parity = UART_PARITY_EVEN; break; default: // ParityNone obj->parity = UART_PARITY_NONE; break; } if (stop_bits == 2) { obj->stopbits = UART_STOPBITS_2; } else { obj->stopbits = UART_STOPBITS_1; } mbed_init_uart(obj); } /****************************************************************************** * INTERRUPTS HANDLING ******************************************************************************/ static void mbed_uart_irq(UARTName name, int id) { UartHandle.Instance = (USART_TypeDef *)name; if (serial_irq_ids[id] != 0) { if (__HAL_UART_GET_FLAG(&UartHandle, UART_FLAG_TC) != RESET) { irq_handler(serial_irq_ids[id], TxIrq); __HAL_UART_CLEAR_FLAG(&UartHandle, UART_FLAG_TC); } if (__HAL_UART_GET_FLAG(&UartHandle, UART_FLAG_RXNE) != RESET) { irq_handler(serial_irq_ids[id], RxIrq); __HAL_UART_CLEAR_FLAG(&UartHandle, UART_FLAG_RXNE); } } } static void mbed_uart1_irq(void) { mbed_uart_irq(UART_1, 0); } static void mbed_uart2_irq(void) { mbed_uart_irq(UART_2, 1); } #if defined(USART3_BASE) static void mbed_uart3_irq(void) { mbed_uart_irq(UART_3, 2); } #endif #if defined(UART4_BASE) static void mbed_uart4_irq(void) { mbed_uart_irq(UART_4, 3); } #endif #if defined(UART5_BASE) static void mbed_uart5_irq(void) { mbed_uart_irq(UART_5, 4); } #endif #if defined(USART6_BASE) static void mbed_uart6_irq(void) { mbed_uart_irq(UART_6, 5); } #endif #if defined(UART7_BASE) static void mbed_uart7_irq(void) { mbed_uart_irq(UART_7, 6); } #endif #if defined(UART8_BASE) static void mbed_uart8_irq(void) { mbed_uart_irq(UART_8, 7); } #endif void mbed_serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { irq_handler = handler; serial_irq_ids[obj->index] = id; } void mbed_serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { IRQn_Type irq_n = (IRQn_Type)0; uint32_t vector = 0; UartHandle.Instance = (USART_TypeDef *)(obj->uart); switch (obj->uart) { case UART_1: irq_n = USART1_IRQn; vector = (uint32_t)&mbed_uart1_irq; break; case UART_2: irq_n = USART2_IRQn; vector = (uint32_t)&mbed_uart2_irq; break; #if defined(USART3_BASE) case UART_3: irq_n = USART3_IRQn; vector = (uint32_t)&mbed_uart3_irq; break; #endif #if defined(UART4_BASE) case UART_4: irq_n = UART4_IRQn; vector = (uint32_t)&mbed_uart4_irq; break; #endif #if defined(UART5_BASE) case UART_5: irq_n = UART5_IRQn; vector = (uint32_t)&mbed_uart5_irq; break; #endif #if defined(USART6_BASE) case UART_6: irq_n = USART6_IRQn; vector = (uint32_t)&mbed_uart6_irq; break; #endif #if defined(UART7_BASE) case UART_7: irq_n = UART7_IRQn; vector = (uint32_t)&mbed_uart7_irq; break; #endif #if defined(UART8_BASE) case UART_8: irq_n = UART8_IRQn; vector = (uint32_t)&mbed_uart8_irq; break; #endif } if (enable) { if (irq == RxIrq) { __HAL_UART_ENABLE_IT(&UartHandle, UART_IT_RXNE); } else { // TxIrq __HAL_UART_ENABLE_IT(&UartHandle, UART_IT_TC); } NVIC_SetVector(irq_n, vector); NVIC_EnableIRQ(irq_n); } else { // disable int all_disabled = 0; if (irq == RxIrq) { __HAL_UART_DISABLE_IT(&UartHandle, UART_IT_RXNE); // Check if TxIrq is disabled too if ((UartHandle.Instance->CR1 & USART_CR1_TXEIE) == 0) all_disabled = 1; } else { // TxIrq __HAL_UART_DISABLE_IT(&UartHandle, UART_IT_TXE); // Check if RxIrq is disabled too if ((UartHandle.Instance->CR1 & USART_CR1_RXNEIE) == 0) all_disabled = 1; } if (all_disabled) NVIC_DisableIRQ(irq_n); } } /****************************************************************************** * READ/WRITE ******************************************************************************/ int mbed_serial_getc(serial_t *obj) { USART_TypeDef *uart = (USART_TypeDef *)(obj->uart); while (!mbed_serial_readable(obj)); return (int)(uart->DR & 0x1FF); } void mbed_serial_putc(serial_t *obj, int c) { USART_TypeDef *uart = (USART_TypeDef *)(obj->uart); while (!mbed_serial_writable(obj)); uart->DR = (uint32_t)(c & 0x1FF); } int mbed_serial_readable(serial_t *obj) { int status; UartHandle.Instance = (USART_TypeDef *)(obj->uart); // Check if data is received status = ((__HAL_UART_GET_FLAG(&UartHandle, UART_FLAG_RXNE) != RESET) ? 1 : 0); return status; } int mbed_serial_writable(serial_t *obj) { int status; UartHandle.Instance = (USART_TypeDef *)(obj->uart); // Check if data is transmitted status = ((__HAL_UART_GET_FLAG(&UartHandle, UART_FLAG_TXE) != RESET) ? 1 : 0); return status; } void mbed_serial_clear(serial_t *obj) { UartHandle.Instance = (USART_TypeDef *)(obj->uart); __HAL_UART_CLEAR_FLAG(&UartHandle, UART_FLAG_TXE); __HAL_UART_CLEAR_FLAG(&UartHandle, UART_FLAG_RXNE); } void mbed_serial_break_set(serial_t *obj) { UartHandle.Instance = (USART_TypeDef *)(obj->uart); HAL_LIN_SendBreak(&UartHandle); } void mbed_serial_break_clear(serial_t *obj) { } #endif /* DEVICE_SERIAL */ #endif /* __ARM_STM32F411__ */