#include "ameba_soc.h" #include "k_api.h" #include "board.h" #include "device.h" #include "gpio_api.h" #include "aos/hal/uart.h" #include "device.h" #include "serial_api.h" #include "gpio_api.h" #include "diag.h" #define RX_BUFFER_LENGTH 128 typedef struct{ u8 id; PinName tx; PinName rx; PinName rts; PinName cts; }uart_s; typedef struct{ u32 length; u8 *rxbuffer; }uart_buffer; static uart_buffer uart_rxbuffer[5]; /*the pin used for uart, you can change the pin as pinmux table, 0 means not use*/ static uart_s uart_obj[5]={ {2, PA_7, PA_8, 0, 0}, //log uart {0, PA_18, PA_19, PA_17, PA_18}, //km4 uart {1, PA_2, PA_4, PA_0, PB_31}, //bt uart {3, PA_12, PA_13, PA_14, PA_15}, //km0 uart {3, PB_1, PB_2, 0, 0} }; #define UART_TX PB_1 #define UART_RX PB_2 // serial_t uart_obj_t; #define EVENT_RX_READY ((uint32_t)1 << 0) #if (RHINO_CONFIG_CPU_NUM > 1) static aos_spinlock_t uart0_lock = { KRHINO_SPINLOCK_FREE_VAL, }; #else static aos_spinlock_t uart0_lock; #endif static aos_event_t uart0_event; static uint8_t uart0_rx_buf[RX_BUFFER_LENGTH]; static size_t uart0_rx_buf_head = 0; static size_t uart0_rx_buf_tail = 0; #define uart0_rx_buf_count() \ ((RX_BUFFER_LENGTH + uart0_rx_buf_head - uart0_rx_buf_tail) & \ (RX_BUFFER_LENGTH - 1)) #define uart0_rx_buf_space() \ (RX_BUFFER_LENGTH - 1 - uart0_rx_buf_count()) size_t uart0_rx_buffer_produce(const void *buf, size_t count) { size_t c = 0; size_t old_count; aos_irqsave_t flags; flags = aos_spin_lock_irqsave(&uart0_lock); old_count = uart0_rx_buf_count(); while (c < count && uart0_rx_buf_space() > 0) { uart0_rx_buf[uart0_rx_buf_head++] = ((const uint8_t *)buf)[c++]; uart0_rx_buf_head &= RX_BUFFER_LENGTH - 1; } if (old_count == 0 && c > 0) aos_event_set(&uart0_event, EVENT_RX_READY, AOS_EVENT_OR); aos_spin_unlock_irqrestore(&uart0_lock, flags); return c; } static size_t uart0_rx_buffer_consume(void *buf, size_t count) { size_t c = 0; aos_irqsave_t flags; flags = aos_spin_lock_irqsave(&uart0_lock); while (c < count && uart0_rx_buf_count() > 0) { ((uint8_t *)buf)[c++] = uart0_rx_buf[uart0_rx_buf_tail++]; uart0_rx_buf_tail &= RX_BUFFER_LENGTH - 1; } if (uart0_rx_buf_count() == 0) aos_event_set(&uart0_event, ~EVENT_RX_READY, AOS_EVENT_AND); aos_spin_unlock_irqrestore(&uart0_lock, flags); return c; } int g_uart_init = 0; static int32_t uart_irq(void *data) { volatile u8 reg_iir; u8 int_id; u32 reg_val; uint8_t rx_char; UART_TypeDef * uart_dev; uart_dev_t* uart = (uart_dev_t*) data; u8 num = uart_obj[uart->port].id; uart_dev = UART_DEV_TABLE[num].UARTx; reg_iir = UART_IntStatus(uart_dev); if ((reg_iir & RUART_IIR_INT_PEND) != 0) { /* No pending IRQ */ return 0; } int_id = (reg_iir & RUART_IIR_INT_ID) >> 1; switch (int_id) { case RUART_RECEIVER_DATA_AVAILABLE: case RUART_TIME_OUT_INDICATION: { if (UART_Readable(uart_dev)) { if(uart_rxbuffer[uart->port].lengthport].rxbuffer + uart_rxbuffer[uart->port].length)); uart_rxbuffer[uart->port].length++; } else { DBG_8195A("UART BUFFER SIZE OVERFLOW!!!!!!!\n"); } } } break; case RUART_RECEIVE_LINE_STATUS: reg_val = (UART_LineStatusGet(uart_dev)); DBG_8195A("data_uart_irq: LSR %08x interrupt\n", reg_val); break; default: DBG_8195A("data_uart_irq: Unknown interrupt type %d\n", int_id); break; } return 0; } /** * Initialises a UART interface * * * @param[in] uart the interface which should be initialised * * @return 0 : on success, EIO : if an error occurred with any step */ int32_t hal_uart_init(uart_dev_t *uart) { if(uart->port != 0){ u8 num = uart_obj[uart->port].id; UART_InitTypeDef UARTStruct; UART_TypeDef *uart_dev; uart_dev = UART_DEV_TABLE[num].UARTx; uart_rxbuffer[uart->port].length=0; uart_rxbuffer[uart->port].rxbuffer = aos_malloc(RX_BUFFER_LENGTH); /*set pin*/ if(uart_obj[uart->port].tx){ Pinmux_Config(uart_obj[uart->port].tx, PINMUX_FUNCTION_UART); PAD_PullCtrl(uart_obj[uart->port].tx, GPIO_PuPd_UP); } if(uart_obj[uart->port].rx){ Pinmux_Config(uart_obj[uart->port].rx, PINMUX_FUNCTION_UART); PAD_PullCtrl(uart_obj[uart->port].rx, GPIO_PuPd_UP); } if(uart->config.flow_control == FLOW_CONTROL_CTS){ if(uart_obj[uart->port].cts){ Pinmux_Config(uart_obj[uart->port].cts, PINMUX_FUNCTION_UART_RTSCTS); } }else if(uart->config.flow_control == FLOW_CONTROL_RTS){ if(uart_obj[uart->port].rts){ Pinmux_Config(uart_obj[uart->port].rts, PINMUX_FUNCTION_UART_RTSCTS); } }else if(uart->config.flow_control == FLOW_CONTROL_CTS_RTS){ if(uart_obj[uart->port].cts){ Pinmux_Config(uart_obj[uart->port].cts, PINMUX_FUNCTION_UART_RTSCTS); } if(uart_obj[uart->port].rts){ Pinmux_Config(uart_obj[uart->port].rts, PINMUX_FUNCTION_UART_RTSCTS); } } UART_StructInit(&UARTStruct); if(uart->config.data_width == DATA_WIDTH_7BIT) UARTStruct.WordLen = RUART_WLS_7BITS; else if(uart->config.data_width == DATA_WIDTH_8BIT) UARTStruct.WordLen = RUART_WLS_8BITS; else DBG_8195A("UNSUPPORTED DATA LENGTH\n"); if(uart->config.stop_bits == STOP_BITS_1) UARTStruct.StopBit = RUART_STOP_BIT_1; else if(uart->config.stop_bits == STOP_BITS_2) UARTStruct.StopBit = RUART_STOP_BIT_2; else DBG_8195A("UNSUPPORTED STOP BIT\n"); if(uart->config.parity ==NO_PARITY){ UARTStruct.Parity = RUART_PARITY_DISABLE; }else if(uart->config.parity == ODD_PARITY){ UARTStruct.Parity = RUART_PARITY_ENABLE; UARTStruct.ParityType = RUART_ODD_PARITY; }else if(uart->config.parity == EVEN_PARITY){ UARTStruct.Parity = RUART_PARITY_ENABLE; UARTStruct.ParityType = RUART_EVEN_PARITY; }else{ DBG_8195A("UNSUPPORTED PARITY TYPE\n"); } if(uart->config.flow_control == FLOW_CONTROL_DISABLED){ UARTStruct.FlowControl = DISABLE; }else{ UARTStruct.FlowControl = ENABLE; } UART_Init(uart_dev, &UARTStruct); UART_SetBaud(uart_dev, uart->config.baud_rate); InterruptRegister((IRQ_FUN)uart_irq, UART_DEV_TABLE[num].IrqNum, (uint32_t)uart, 5); InterruptEn( UART_DEV_TABLE[num].IrqNum, 5); UART_INTConfig(uart_dev, RUART_IER_ERBI | RUART_IER_ETOI | RUART_IER_ELSI, ENABLE); UART_RxCmd(uart_dev, ENABLE); return 0; }else{ /* serial_init(&uart_obj_t, UART_TX, UART_RX); serial_baud(&uart_obj_t, 115200); serial_format(&uart_obj_t, 8, ParityNone, 1); serial_irq_handler(&uart_obj_t, uart_irq, (uint32_t)&uart_obj_t); serial_irq_set(&uart_obj_t, RxIrq, 1);*/ g_uart_init = 1; aos_event_new(&uart0_event, 0); #ifdef AMEBAD_TODO LOGUART_SetBaud_FromFlash(); #endif shell_init_rom(0, 0); shell_init_ram(); ipc_table_init(); /* Register Log Uart Callback function */ extern VOID shell_uart_irq_rom(VOID * Data); InterruptRegister((IRQ_FUN) shell_uart_irq_rom, UART_LOG_IRQ, (u32)NULL, 10); InterruptEn(UART_LOG_IRQ_LP,10); return 0; } } /** * Transmit data on a UART interface * * @param[in] uart the UART interface * @param[in] data pointer to the start of data * @param[in] size number of bytes to transmit * @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER * if you want to wait forever * * @return 0 : on success, EIO : if an error occurred with any step */ int32_t hal_uart_send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout) { if(uart->port != 0){ u8 num = uart_obj[uart->port].id; UART_TypeDef *uart_dev; uart_dev = UART_DEV_TABLE[num].UARTx; UART_SendDataTO(uart_dev, (uint8_t *)data, size, 1000); return 0; }else{ int i; char * cdata = (char *)data; for(i = 0; i < size; i++) { DiagPutChar(*cdata++); } return 0; } } /** * Receive data on a UART interface * * @param[in] uart the UART interface * @param[out] data pointer to the buffer which will store incoming data * @param[in] expect_size number of bytes to receive * @param[out] recv_size number of bytes received * @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER * if you want to wait forever * * @return 0 : on success, EIO : if an error occurred with any step */ int32_t hal_uart_recv_II(uart_dev_t *uart, void *data, uint32_t expect_size, uint32_t *recv_size, uint32_t timeout) { if(uart->port != 0){ u8 num = uart_obj[uart->port].id; UART_TypeDef *uart_dev; uart_dev = UART_DEV_TABLE[num].UARTx; if((uart_rxbuffer[uart->port].length) <= expect_size){ _memcpy(data, uart_rxbuffer[uart->port].rxbuffer, uart_rxbuffer[uart->port].length); *recv_size = uart_rxbuffer[uart->port].length; uart_rxbuffer[uart->port].length = 0; }else{ _memcpy(data, uart_rxbuffer[uart->port].rxbuffer, expect_size); _memcpy(uart_rxbuffer[uart->port].rxbuffer,uart_rxbuffer[uart->port].rxbuffer+expect_size, uart_rxbuffer[uart->port].length-expect_size); *recv_size = expect_size; uart_rxbuffer[uart->port].length -= expect_size; } return 0; }else{ uint32_t c = 0; if (data == NULL || expect_size == 0) { return -1; } while (1) { aos_status_t r; uint32_t val; c += uart0_rx_buffer_consume(&((uint8_t *)data)[c], expect_size - c); if (c > 0) break; if (timeout == 0) break; r = aos_event_get(&uart0_event, EVENT_RX_READY, AOS_EVENT_OR, &val, timeout); if (r) break; } if (recv_size) { *recv_size = c; } return c > 0 ? 0 : -1; } } /** * Deinitialises a UART interface * * @param[in] uart the interface which should be deinitialised * * @return 0 : on success, EIO : if an error occurred with any step */ int32_t hal_uart_finalize(uart_dev_t *uart) { if(uart->port != 0){ u8 num = uart_obj[uart->port].id; UART_DeInit( UART_DEV_TABLE[num].UARTx); InterruptDis(UART_DEV_TABLE[num].IrqNum); InterruptUnRegister(UART_DEV_TABLE[num].IrqNum); aos_free(uart_rxbuffer[uart->port].rxbuffer); return 0; }else{ if(g_uart_init == 0) { return 0; } uart0_rx_buf_head = 0; uart0_rx_buf_tail = 0; aos_event_free(&uart0_event); g_uart_init = 0; return 0; } } int hal_uart_rx_sem_take(int uart_id, int timeout) { uint32_t val; if (uart_id != 0) return -EINVAL; return aos_event_get(&uart0_event, EVENT_RX_READY, AOS_EVENT_OR, &val, timeout); } int hal_uart_rx_sem_give(int uart_id) { if (uart_id != 0) return -EINVAL; aos_event_set(&uart0_event, EVENT_RX_READY, AOS_EVENT_OR); return 0; }