/** * @brief Check if Rx IRQ has been raised * * @param dev UART device struct * * @return 1 if an IRQ is ready, 0 otherwise */ static int uart_k20_irq_rx_ready(struct device *dev) { volatile struct K20_UART *uart = UART_STRUCT(dev); return (uart->c2.field.rx_full_int_dma_tx_en == 0) ? 0 : uart->s1.field.rx_data_full; }
/** * @brief Initialize UART channel * * This routine is called to reset the chip in a quiescent state. * It is assumed that this function is called only once per UART. * * @param dev UART device struct * * @return 0 */ static int uart_stm32_init(struct device *dev) { const struct uart_stm32_config *config = DEV_CFG(dev); struct uart_stm32_data *data = DEV_DATA(dev); UART_HandleTypeDef *UartHandle = &data->huart; __uart_stm32_get_clock(dev); /* enable clock */ #if defined(CONFIG_SOC_SERIES_STM32F1X) || defined(CONFIG_SOC_SERIES_STM32L4X) clock_control_on(data->clock, config->clock_subsys); #elif defined(CONFIG_SOC_SERIES_STM32F4X) clock_control_on(data->clock, (clock_control_subsys_t *)&config->pclken); #endif UartHandle->Instance = UART_STRUCT(dev); UartHandle->Init.WordLength = UART_WORDLENGTH_8B; UartHandle->Init.StopBits = UART_STOPBITS_1; UartHandle->Init.Parity = UART_PARITY_NONE; UartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE; UartHandle->Init.Mode = UART_MODE_TX_RX; UartHandle->Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(UartHandle); #ifdef CONFIG_UART_INTERRUPT_DRIVEN config->uconf.irq_config_func(dev); #endif return 0; }
/** * @brief Initialize UART channel * * This routine is called to reset the chip in a quiescent state. * It is assumed that this function is called only once per UART. * * @param dev UART device struct * * @return DEV_OK */ static int uart_k20_init(struct device *dev) { int old_level; /* old interrupt lock level */ union C1 c1; /* UART C1 register value */ union C2 c2; /* UART C2 register value */ volatile struct K20_UART *uart = UART_STRUCT(dev); struct uart_device_config * const dev_cfg = DEV_CFG(dev); struct uart_k20_dev_data_t * const dev_data = DEV_DATA(dev); /* disable interrupts */ old_level = irq_lock(); _uart_k20_baud_rate_set(uart, dev_cfg->sys_clk_freq, dev_data->baud_rate); /* 1 start bit, 8 data bits, no parity, 1 stop bit */ c1.value = 0; uart->c1 = c1; /* enable Rx and Tx with interrupts disabled */ c2.value = 0; c2.field.rx_enable = 1; c2.field.tx_enable = 1; uart->c2 = c2; /* restore interrupt state */ irq_unlock(old_level); dev->driver_api = &uart_k20_driver_api; return DEV_OK; }
/** * @brief Initialize UART channel * * This routine is called to reset the chip in a quiescent state. * It is assumed that this function is called only once per UART. * * @param dev UART device struct * * @return 0 */ static int uart_cmsdk_apb_init(struct device *dev) { volatile struct uart_cmsdk_apb *uart = UART_STRUCT(dev); #ifdef CONFIG_UART_INTERRUPT_DRIVEN const struct uart_device_config * const dev_cfg = DEV_CFG(dev); #endif #ifdef CONFIG_CLOCK_CONTROL /* Enable clock for subsystem */ struct device *clk = device_get_binding(CONFIG_ARM_CLOCK_CONTROL_DEV_NAME); struct uart_cmsdk_apb_dev_data * const data = DEV_DATA(dev); #ifdef CONFIG_SOC_SERIES_BEETLE clock_control_on(clk, (clock_control_subsys_t *) &data->uart_cc_as); clock_control_on(clk, (clock_control_subsys_t *) &data->uart_cc_ss); clock_control_on(clk, (clock_control_subsys_t *) &data->uart_cc_dss); #endif /* CONFIG_SOC_SERIES_BEETLE */ #endif /* CONFIG_CLOCK_CONTROL */ /* Set baud rate */ baudrate_set(dev); /* Enable receiver and transmitter */ uart->ctrl = UART_RX_EN | UART_TX_EN; #ifdef CONFIG_UART_INTERRUPT_DRIVEN dev_cfg->irq_config_func(dev); #endif return 0; }
static int uart_stm32_irq_is_pending(struct device *dev) { USART_TypeDef *UartInstance = UART_STRUCT(dev); return ((LL_USART_IsActiveFlag_RXNE(UartInstance) && LL_USART_IsEnabledIT_RXNE(UartInstance)) || (LL_USART_IsActiveFlag_TC(UartInstance) && LL_USART_IsEnabledIT_TC(UartInstance))); }
/** * @brief Initialize UART channel * * This routine is called to reset the chip in a quiescent state. * It is assumed that this function is called only once per UART. * * @param dev UART device struct * * @return 0 on success */ static int uart_nrf5_init(struct device *dev) { volatile struct _uart *uart = UART_STRUCT(dev); struct device *gpio_dev; gpio_dev = device_get_binding(CONFIG_GPIO_NRF5_P0_DEV_NAME); (void) gpio_pin_configure(gpio_dev, CONFIG_UART_NRF5_GPIO_TX_PIN, (GPIO_DIR_OUT | GPIO_PUD_PULL_UP)); (void) gpio_pin_configure(gpio_dev, CONFIG_UART_NRF5_GPIO_RX_PIN, (GPIO_DIR_IN)); uart->PSELTXD = CONFIG_UART_NRF5_GPIO_TX_PIN; uart->PSELRXD = CONFIG_UART_NRF5_GPIO_RX_PIN; #ifdef CONFIG_UART_NRF5_FLOW_CONTROL (void) gpio_pin_configure(gpio_dev, CONFIG_UART_NRF5_GPIO_RTS_PIN, (GPIO_DIR_OUT | GPIO_PUD_PULL_UP)); (void) gpio_pin_configure(gpio_dev, CONFIG_UART_NRF5_GPIO_CTS_PIN, (GPIO_DIR_IN)); uart->PSELRTS = CONFIG_UART_NRF5_GPIO_RTS_PIN; uart->PSELCTS = CONFIG_UART_NRF5_GPIO_CTS_PIN; uart->CONFIG = (UART_CONFIG_HWFC_Enabled << UART_CONFIG_HWFC_Pos); #endif /* CONFIG_UART_NRF5_FLOW_CONTROL */ DEV_DATA(dev)->baud_rate = CONFIG_UART_NRF5_BAUD_RATE; DEV_CFG(dev)->sys_clk_freq = CONFIG_UART_NRF5_CLK_FREQ; /* Set baud rate */ baudrate_set(dev, DEV_DATA(dev)->baud_rate, DEV_CFG(dev)->sys_clk_freq); /* Enable receiver and transmitter */ uart->ENABLE = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos); uart->EVENTS_TXDRDY = 0; uart->EVENTS_RXDRDY = 0; uart->TASKS_STARTTX = 1; uart->TASKS_STARTRX = 1; dev->driver_api = &uart_nrf5_driver_api; #ifdef CONFIG_UART_INTERRUPT_DRIVEN DEV_CFG(dev)->irq_config_func(dev); #endif return 0; }
/** * @brief Disable error interrupt * * @param dev UART device struct * * @return N/A */ static void uart_k20_irq_err_disable(struct device *dev) { volatile struct K20_UART *uart = UART_STRUCT(dev); union C3 c3 = uart->c3; c3.field.parity_err_int_en = 0; c3.field.frame_err_int_en = 0; c3.field.noise_err_int_en = 0; c3.field.overrun_err_int_en = 0; uart->c3 = c3; }
/** * @brief Read data from FIFO * * @param dev UART device struct * @param rx_data Pointer to data container * @param size Container size in bytes * * @return number of bytes read */ static int uart_k20_fifo_read(struct device *dev, uint8_t *rx_data, const int size) { volatile struct K20_UART *uart = UART_STRUCT(dev); uint8_t num_rx = 0; while ((size - num_rx > 0) && (uart->s1.field.rx_data_full != 0)) { rx_data[num_rx++] = uart->d; } return num_rx; }
static void uart_stm32_lpuart_set_baud_rate(struct device *dev, u32_t clock_rate, u32_t baud_rate) { USART_TypeDef *UartInstance = UART_STRUCT(dev); LL_LPUART_SetBaudRate(UartInstance, clock_rate, #ifdef USART_PRESC_PRESCALER LL_USART_PRESCALER_DIV1, #endif baud_rate); }
/** * @brief Fill FIFO with data * * @param dev UART device struct * @param tx_data Data to transmit * @param len Number of bytes to send * * @return number of bytes sent */ static int uart_k20_fifo_fill(struct device *dev, const uint8_t *tx_data, int len) { volatile struct K20_UART *uart = UART_STRUCT(dev); uint8_t num_tx = 0; while ((len - num_tx > 0) && (uart->s1.field.tx_data_empty == 1)) { uart->d = tx_data[num_tx++]; } return num_tx; }
/** * @brief Poll the device for input. * * @param dev UART device struct * @param c Pointer to character * * @return 0 if a character arrived, -1 if the input buffer if empty. */ static int uart_k20_poll_in(struct device *dev, unsigned char *c) { volatile struct K20_UART *uart = UART_STRUCT(dev); if (uart->s1.field.rx_data_full == 0) return (-1); /* got a character */ *c = uart->d; return 0; }
/** * @brief Read data from FIFO * * @param dev UART device struct * @param rx_data Pointer to data container * @param size Container size in bytes * * @return the number of characters that have been read */ static int uart_cmsdk_apb_fifo_read(struct device *dev, u8_t *rx_data, const int size) { volatile struct uart_cmsdk_apb *uart = UART_STRUCT(dev); /* No hardware FIFO present */ if (size && uart->state & UART_RX_BF) { *rx_data = (unsigned char)uart->data; return 1; } return 0; }
/** * @brief Fill FIFO with data * * @param dev UART device struct * @param tx_data Data to transmit * @param len Number of bytes to send * * @return the number of characters that have been read */ static int uart_cmsdk_apb_fifo_fill(struct device *dev, const u8_t *tx_data, int len) { volatile struct uart_cmsdk_apb *uart = UART_STRUCT(dev); /* No hardware FIFO present */ if (len && !(uart->state & UART_TX_BF)) { uart->data = *tx_data; return 1; } return 0; }
static void uart_stm32_poll_out(struct device *dev, unsigned char c) { USART_TypeDef *UartInstance = UART_STRUCT(dev); /* Wait for TXE flag to be raised */ while (!LL_USART_IsActiveFlag_TXE(UartInstance)) ; LL_USART_ClearFlag_TC(UartInstance); LL_USART_TransmitData8(UartInstance, (u8_t)c); }
/** * @brief Output a character in polled mode. * * Checks if the transmitter is empty. If empty, a character is written to * the data register. * * @param dev UART device struct * @param c Character to send */ static void uart_cmsdk_apb_poll_out(struct device *dev, unsigned char c) { volatile struct uart_cmsdk_apb *uart = UART_STRUCT(dev); /* Wait for transmitter to be ready */ while (uart->state & UART_TX_BF) { ; /* Wait */ } /* Send a character */ uart->data = (u32_t)c; }
/** * @brief Output a character in polled mode. * * Checks if the transmitter is empty. If empty, a character is written to * the data register. * * If the hardware flow control is enabled then the handshake signal CTS has to * be asserted in order to send a character. * * @param dev UART device struct * @param c Character to send * * @return sent character */ static unsigned char uart_k20_poll_out(struct device *dev, unsigned char c) { volatile struct K20_UART *uart = UART_STRUCT(dev); /* wait for transmitter to ready to accept a character */ while (uart->s1.field.tx_data_empty == 0) ; uart->d = c; return c; }
/** * @brief Initialize UART channel * * This routine is called to reset the chip in a quiescent state. * It is assumed that this function is called only once per UART. * * @param dev UART device struct * * @return 0 */ static int uart_stm32_init(struct device *dev) { const struct uart_stm32_config *config = DEV_CFG(dev); struct uart_stm32_data *data = DEV_DATA(dev); USART_TypeDef *UartInstance = UART_STRUCT(dev); __uart_stm32_get_clock(dev); /* enable clock */ if (clock_control_on(data->clock, (clock_control_subsys_t *)&config->pclken) != 0) { return -EIO; } LL_USART_Disable(UartInstance); /* TX/RX direction */ LL_USART_SetTransferDirection(UartInstance, LL_USART_DIRECTION_TX_RX); /* 8 data bit, 1 start bit, 1 stop bit, no parity */ LL_USART_ConfigCharacter(UartInstance, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1); if (config->hw_flow_control) { uart_stm32_set_hwctrl(dev, LL_USART_HWCONTROL_RTS_CTS); } /* Set the default baudrate */ uart_stm32_set_baudrate(dev, data->baud_rate); LL_USART_Enable(UartInstance); #ifdef USART_ISR_TEACK /* Wait until TEACK flag is set */ while (!(LL_USART_IsActiveFlag_TEACK(UartInstance))) ; #endif /* !USART_ISR_TEACK */ #ifdef USART_ISR_REACK /* Wait until REACK flag is set */ while (!(LL_USART_IsActiveFlag_REACK(UartInstance))) ; #endif /* !USART_ISR_REACK */ #ifdef CONFIG_UART_INTERRUPT_DRIVEN config->uconf.irq_config_func(dev); #endif return 0; }
/** * @brief Interrupt service routine. * * Calls the callback function, if exists. * * @param arg argument to interrupt service routine. * * @return N/A */ void uart_cmsdk_apb_isr(void *arg) { struct device *dev = arg; volatile struct uart_cmsdk_apb *uart = UART_STRUCT(dev); struct uart_cmsdk_apb_dev_data *data = DEV_DATA(dev); /* Clear pending interrupts */ uart->intclear = UART_RX_IN | UART_TX_IN; /* Verify if the callback has been registered */ if (data->irq_cb) { data->irq_cb(dev); } }
static int uart_cmsdk_apb_poll_in(struct device *dev, unsigned char *c) { volatile struct uart_cmsdk_apb *uart = UART_STRUCT(dev); /* If the receiver is not ready returns -1 */ if (!(uart->state & UART_RX_BF)) { return -1; } /* got a character */ *c = (unsigned char)uart->data; return 0; }
static inline u32_t uart_stm32_get_databits(struct device *dev) { USART_TypeDef *UartInstance = UART_STRUCT(dev); #ifdef CONFIG_LPUART_1 if (IS_LPUART_INSTANCE(UartInstance)) { return LL_LPUART_GetDataWidth(UartInstance); } else { return LL_USART_GetDataWidth(UartInstance); } #else return LL_USART_GetDataWidth(UartInstance); #endif /* CONFIG_LPUART_1 */ }
static inline void uart_stm32_set_parity(struct device *dev, u32_t parity) { USART_TypeDef *UartInstance = UART_STRUCT(dev); #ifdef CONFIG_LPUART_1 if (IS_LPUART_INSTANCE(UartInstance)) { LL_LPUART_SetParity(UartInstance, parity); } else { LL_USART_SetParity(UartInstance, parity); } #else LL_USART_SetParity(UartInstance, parity); #endif /* CONFIG_LPUART_1 */ }
static inline void uart_stm32_set_databits(struct device *dev, u32_t databits) { USART_TypeDef *UartInstance = UART_STRUCT(dev); #ifdef CONFIG_LPUART_1 if (IS_LPUART_INSTANCE(UartInstance)) { LL_LPUART_SetDataWidth(UartInstance, databits); } else { LL_USART_SetDataWidth(UartInstance, databits); } #else LL_USART_SetDataWidth(UartInstance, databits); #endif /* CONFIG_LPUART_1 */ }
/** * @brief Enable TX interrupt * * @param dev UART device struct * * @return N/A */ static void uart_cmsdk_apb_irq_tx_enable(struct device *dev) { unsigned int key; UART_STRUCT(dev)->ctrl |= UART_TX_IN_EN; /* The expectation is that TX is a level interrupt, active for as * long as TX buffer is empty. But in CMSDK UART, it appears to be * edge interrupt, firing on a state change of TX buffer. So, we * need to "prime" it here by calling ISR directly, to get interrupt * processing going. */ key = irq_lock(); uart_cmsdk_apb_isr(dev); irq_unlock(key); }
static void uart_stm32_irq_err_disable(struct device *dev) { USART_TypeDef *UartInstance = UART_STRUCT(dev); /* Disable FE, ORE interruptions */ LL_USART_DisableIT_ERROR(UartInstance); #if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT) /* Disable Line break detection */ if (IS_UART_LIN_INSTANCE(UartInstance)) { LL_USART_DisableIT_LBD(UartInstance); } #endif /* Disable parity error interruption */ LL_USART_DisableIT_PE(UartInstance); }
/** Interrupt driven FIFO fill function */ static int uart_nrf5_fifo_fill(struct device *dev, const uint8_t *tx_data, int len) { volatile struct _uart *uart = UART_STRUCT(dev); uint8_t num_tx = 0; while ((len - num_tx > 0) && uart->EVENTS_TXDRDY) { /* Clear the interrupt */ uart->EVENTS_TXDRDY = 0; /* Send a character */ uart->TXD = (uint8_t)tx_data[num_tx++]; } return (int)num_tx; }
/** Interrupt driven FIFO read function */ static int uart_nrf5_fifo_read(struct device *dev, uint8_t *rx_data, const int size) { volatile struct _uart *uart = UART_STRUCT(dev); uint8_t num_rx = 0; while ((size - num_rx > 0) && uart->EVENTS_RXDRDY) { /* Clear the interrupt */ uart->EVENTS_RXDRDY = 0; /* Receive a character */ rx_data[num_rx++] = (uint8_t)uart->RXD; } return num_rx; }
/** * @brief Set the baud rate * * This routine set the given baud rate for the UART. * * @param dev UART device struct * * @return N/A */ static void baudrate_set(struct device *dev) { volatile struct uart_cmsdk_apb *uart = UART_STRUCT(dev); const struct uart_device_config * const dev_cfg = DEV_CFG(dev); struct uart_cmsdk_apb_dev_data *const dev_data = DEV_DATA(dev); /* * If baudrate and/or sys_clk_freq are 0 the configuration remains * unchanged. It can be useful in case that Zephyr it is run via * a bootloader that brings up the serial and sets the baudrate. */ if ((dev_data->baud_rate != 0) && (dev_cfg->sys_clk_freq != 0)) { /* calculate baud rate divisor */ uart->bauddiv = (dev_cfg->sys_clk_freq / dev_data->baud_rate); } }
static int uart_stm32_fifo_fill(struct device *dev, const u8_t *tx_data, int size) { USART_TypeDef *UartInstance = UART_STRUCT(dev); u8_t num_tx = 0U; while ((size - num_tx > 0) && LL_USART_IsActiveFlag_TXE(UartInstance)) { /* TXE flag will be cleared with byte write to DR|RDR register */ /* Send a character (8bit , parity none) */ LL_USART_TransmitData8(UartInstance, tx_data[num_tx++]); } return num_tx; }
static int uart_nrf5_poll_in(struct device *dev, unsigned char *c) { volatile struct _uart *uart = UART_STRUCT(dev); if (!uart->EVENTS_RXDRDY) { return -1; } /* Clear the interrupt */ uart->EVENTS_RXDRDY = 0; /* got a character */ *c = (unsigned char)uart->RXD; return 0; }
/** * @brief Output a character in polled mode. * * Checks if the transmitter is empty. If empty, a character is written to * the data register. * * @param dev UART device struct * @param c Character to send * * @return Sent character */ static unsigned char uart_nrf5_poll_out(struct device *dev, unsigned char c) { volatile struct _uart *uart = UART_STRUCT(dev); /* send a character */ uart->TXD = (uint8_t)c; /* Wait for transmitter to be ready */ while (!uart->EVENTS_TXDRDY) { } uart->EVENTS_TXDRDY = 0; return c; }