/* * Copyright (c) CompanyNameMagicTag 2012-2019. All rights reserved. * Description: Adjust the directory structure to prepare for compiling the SDK. uart.c code * Author: CompanyName * Create: 2012-07-14 */ #include "uart.h" #include "los_event.h" #include "string.h" #include "soc_mdm_uart.h" #include "los_hwi.h" #include "uart_drv.h" #include #include #include static uart_driver_data_t g_uart_0 = { .num = UART0, .phys_base = EXT_UART0_REG_BASE, .irq_num = Uart0_IRQn, .rx_transfer = TD_NULL, .tx_transfer = TD_NULL, .rx_recv = uart_write_circ_buf, .tx_send = uart_read_circ_buf, .flags = UART_FLG_RD_BLOCK | UART_FLG_WD_BLOCK, .count = 0, .state = UART_STATE_NOT_OPENED, .ops = &g_uart_driver_uops, .attr = UART0_ATTR_DEFAULT, }; static uart_driver_data_t g_uart_1 = { .num = UART1, .phys_base = EXT_UART1_REG_BASE, .irq_num = Uart1_IRQn, .rx_transfer = TD_NULL, .tx_transfer = TD_NULL, .rx_recv = uart_write_circ_buf, .tx_send = uart_read_circ_buf, .flags = UART_FLG_RD_BLOCK | UART_FLG_WD_BLOCK, .count = 0, .state = UART_STATE_NOT_OPENED, .ops = &g_uart_driver_uops, .attr = UART_ATTR_DEFAULT, }; uart_driver_data_t *g_udd_g[UART_NUM] = { &g_uart_0, &g_uart_1 }; EXT_PRV td_bool check_commit_to_sleep(td_u32 uart_index) { uart_driver_data_t *udd = TD_NULL; udd = (uart_driver_data_t *)g_udd_g[uart_index]; if (udd->state == UART_STATE_USEABLE) { if (uart_rx_fifo_num(udd) != 0) { return TD_FALSE; } } return TD_TRUE; } __init uart_driver_data_t *uart_open(int uart_index, uart_mode mode) { unsigned int ret; uart_driver_data_t *udd = TD_NULL; /* Compare with UART_232, not direct use != , Convenient to modify only the lower boundary */ if (uart_index < 0 || uart_index >= UART_NUM || mode < UART_232 || mode > UART_232) { return TD_NULL; } udd = (uart_driver_data_t *)g_udd_g[uart_index]; if (udd->state == UART_STATE_NOT_OPENED) { ext_lowpower_check_id check_; ret = uart_init_circ_buf(udd, CONFIG_RX_BUF_SIZE, CONFIG_TX_BUF_SIZE); if (ret != EXT_ERR_SUCCESS) { uart_set_err_no(UART_ERR_INIT_CIRC_FAILED); return TD_NULL; } ret = LOS_EventInit(&udd->uart_event); if (ret != EXT_ERR_SUCCESS) { uart_deinit_circ_buf(udd); return TD_NULL; } udd->type = mode; if (!udd->ops->startup || udd->ops->startup(udd)) { uart_deinit_circ_buf(udd); uart_set_err_no(UART_ERR_START_FAILED); return TD_NULL; } check_.deep = TD_TRUE; check_.light = TD_TRUE; if (uart_index == 0) { check_.id = EXT_LOWPOWER_ID_UART0; } else { check_.id = EXT_LOWPOWER_ID_UART1; } uapi_lowpower_register_checkfunc(check_, check_commit_to_sleep, (unsigned int)uart_index); udd->state = UART_STATE_USEABLE; } else { if (mode != udd->type) { if (udd->ops->startup != TD_NULL) { udd->type = mode; udd->ops->startup(udd); } } } return udd; } unsigned int uart_read(uart_driver_data_t *udd, char *buf, size_t count) { int len; if (udd == TD_NULL || udd->rx_transfer == TD_NULL) { return EXT_ERR_FAILURE; } if ((buf == TD_NULL) || (count == 0)) { uart_set_err_no(UART_ERR_PARA_INVALID); return EXT_ERR_FAILURE; } if (udd->state != UART_STATE_USEABLE) { uart_set_err_no(UART_ERR_NOT_OPENED); return EXT_ERR_FAILURE; } do { len = uart_read_circ_buf(udd->rx_transfer, buf, count); #ifdef UART_DEBUG_INFO udd->uart_stat_info.read_circ_cnt += (unsigned int)len; #endif if (len == 0) { if (udd->flags & UART_FLG_RD_BLOCK) { (void)LOS_EventRead(&udd->uart_event, UART_RD_EVENT, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); } else { break; } } } while (len == 0); return (td_u32)len; } unsigned int uart_write(uart_driver_data_t *udd, const char *buf, size_t count) { int len = 0; int left; /* if uart is not in useable, report error */ if (udd == TD_NULL || udd->tx_transfer == TD_NULL) { return EXT_ERR_FAILURE; } if ((buf == TD_NULL) || (count == 0)) { uart_set_err_no(UART_ERR_PARA_INVALID); return EXT_ERR_FAILURE; } left = (int)count; if (udd->state != UART_STATE_USEABLE) { uart_set_err_no(UART_ERR_NOT_OPENED); return EXT_ERR_FAILURE; } #ifdef UART_CIRC_BUF_ENABLE do { len += uart_write_circ_buf(udd->tx_transfer, (char *)&buf[len], (unsigned int)left); if (len < (int)count) { left = (int)count - len; if (udd->flags & UART_FLG_WD_BLOCK) { uart_tx_interrupt_enable(udd); (void)LOS_EventRead(&udd->uart_event, UART_WD_EVENT, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); } else { break; } } else { break; } } while (left > 0); uart_tx_interrupt_enable(udd); #else if (udd->ops->start_tx) { len = udd->ops->start_tx(udd, buf, count); } #endif #ifdef UART_DEBUG_INFO udd->uart_stat_info.write_circ_cnt += (unsigned int)len; #endif return (td_u32)len; } __init bool uart_attr_valued(EXT_CONST uart_attr_t *attr) { if (attr && (attr->baudrate <= CONFIG_MAX_BAUDRATE) && (attr->baudrate > 0) && attr->data_bits <= 8 && attr->data_bits >= 5 && /* Data bit 8bit or 5bit */ (attr->parity == PARITY_NONE || attr->parity == PARITY_ODD || attr->parity == PARITY_EVEN) && (attr->stop_bits == STOP_BIT_1 || attr->stop_bits == STOP_BIT_1P5 || attr->stop_bits == STOP_BIT_2)) { return TD_TRUE; } return TD_FALSE; } #define set_err_code(type) \ do { \ uart_set_err_no(type); \ ret = EXT_ERR_FAILURE; \ } while (0) __init unsigned int uart_ioctl(uart_driver_data_t *udd, int cmd, unsigned long arg) { uart_attr_t *attr = TD_NULL; unsigned int ret = EXT_ERR_SUCCESS; if (udd->state != UART_STATE_USEABLE) { uart_set_err_no(UART_ERR_NOT_OPENED); return EXT_ERR_FAILURE; } switch (cmd) { case UART_CFG_SET_ATTR: attr = (uart_attr_t *)(uintptr_t)arg; if (uart_attr_valued(attr) == TD_TRUE) { (td_void)memcpy_s(&udd->attr, sizeof(udd->attr), attr, sizeof(uart_attr_t)); if ((udd->ops == TD_NULL) || (udd->ops->ioctl == TD_NULL) || udd->ops->ioctl(udd)) { set_err_code(UART_ERR_IOCTL_FAILED); } } else { set_err_code(UART_ERR_PARA_INVALID); } break; case UART_CFG_RD_BLOCK: if (arg == UART_RD_BLOCK) { udd->flags |= UART_FLG_RD_BLOCK; } else if (arg == UART_RD_NONBLOCK) { udd->flags &= ~UART_FLG_RD_BLOCK; (void)LOS_EventWrite(&udd->uart_event, UART_RD_EVENT); } break; case UART_CFG_WD_BLOCK: if (arg == UART_WD_BLOCK) { udd->flags |= UART_FLG_WD_BLOCK; } else if (arg == UART_WD_NONBLOCK) { udd->flags &= ~UART_FLG_WD_BLOCK; (void)LOS_EventWrite(&udd->uart_event, UART_WD_EVENT); } break; case UART_CFG_GET_ATTR: if (memcpy_s((uart_attr_t *)(uintptr_t)arg, sizeof(uart_attr_t), &udd->attr, sizeof(udd->attr)) != EOK) { break; } break; default: set_err_code(UART_ERR_PARA_INVALID); break; } return ret; } __init unsigned int uart_close(uart_driver_data_t *udd) { if (udd == TD_NULL) { return EXT_ERR_INVALID_PARAMETER; } if (udd->state != UART_STATE_USEABLE) { uart_set_err_no(UART_ERR_NOT_OPENED); return EXT_ERR_FAILURE; } uart_tf_interrupt_disable(udd); uart_rx_interrupt_disable(udd); uart_tx_interrupt_disable(udd); return EXT_ERR_SUCCESS; }