/* * Copyright : (C) 2022 Phytium Information Technology, Inc. * All Rights Reserved. * * This program is OPEN SOURCE software: you can redistribute it and/or modify it * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, * either version 1.0 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 Phytium Public License for more details. * * * FilePath: fpl011_intr.c * Date: 2021-11-02 14:53:42 * LastEditTime: 2022-02-18 09:06:30 * Description:  This file is for uart irq functions * * Modify History: * Ver   Who        Date         Changes * ----- ------     --------    -------------------------------------- * 1.0 huanghe 2021/11/2 first commit * 1.1 liushengming 2022/02/18 fix bugs */ /***************************** Include Files *********************************/ #include "fpl011.h" /************************** Constant Definitions *****************************/ /**************************** Type Definitions *******************************/ /***************** Macros (Inline Functions) Definitions *********************/ /************************** Variable Definitions *****************************/ /************************** Function Prototypes ******************************/ /*****************************************************************************/ extern u32 FPl011SendBuffer(FPl011 *uart_p); extern u32 FPl011ReceiveBuffer(FPl011 *uart_p); static void FPl011ReceiveErrorHandler(FPl011 *uart_p, u32 InterruptStatus); static void FPl011ReceiveDataHandler(FPl011 *uart_p); static void FPl011ReceiveTimeoutHandler(FPl011 *uart_p); static void FPl011SendDataHandler(FPl011 *uart_p, u32 InterruptStatus); /** * @name: FPl011GetInterruptMask * @msg: 此函数获取所有串口中断的mask。 * @param uart_p * @return mask */ /** * @name: FPl011GetInterruptMask * @msg: This function gets the interrupt mask. * @param uart_p is a pointer to the uart instance * @return {*} */ u32 FPl011GetInterruptMask(FPl011 *uart_p) { FASSERT(uart_p != NULL); return FUART_READREG32(uart_p->config.base_address, FPL011IMSC_OFFSET); } /** * @name: FPl011SetInterruptMask * @msg: This function sets the interrupt mask. * @param uart_p is a pointer to the uart instance * @param mask contains the interrupts to be enabled or disabled. * A '1' enables an interrupt, and a '0' disables. */ void FPl011SetInterruptMask(FPl011 *uart_p, u32 mask) { u32 temp_mask = mask; FASSERT(uart_p != NULL); temp_mask &= FPL011IMSC_ALLM; FUART_WRITEREG32(uart_p->config.base_address, FPL011IMSC_OFFSET, temp_mask); } /** * @name: FPl011SetHandler * @msg: This function sets the handler that will be called when an event (interrupt) * occurs that needs application's attention. * @param uart_p is a pointer to the uart instance * @param fun_p is the pointer to the callback function. * @param args is the upper layer callback reference passed back * when the callback function is invoked. * @return {*} */ void FPl011SetHandler(FPl011 *uart_p, FPl011EventHandler fun_p, void *args) { FASSERT(uart_p != NULL); FASSERT(fun_p != NULL); FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY); uart_p->handler = fun_p; uart_p->args = args; } /** * @name: FPl011InterruptHandler * @msg: This function is the interrupt handler for the driver. * It must be connected to an interrupt system by the application such that it * can be called when an interrupt occurs. * @param vector Irq num ,Don't need attention . * @param param contains a pointer to the driver instance */ void FPl011InterruptHandler(s32 vector, void *param) { FPl011 *uart_p = (FPl011 *)param; u32 reg_value = 0; FASSERT(uart_p != NULL); FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY); reg_value = FUART_READREG32(uart_p->config.base_address, FPL011IMSC_OFFSET); reg_value &= FUART_READREG32(uart_p->config.base_address, FPL011MIS_OFFSET); if ((reg_value & ((u32)FPL011MIS_RXMIS)) != (u32)0) { /* Received data interrupt */ FPl011ReceiveDataHandler(uart_p); } if ((reg_value & ((u32)FPL011MIS_TXMIS)) != (u32)0) { /* Transmit data interrupt */ FPl011SendDataHandler(uart_p, reg_value); } if (((reg_value) & ((u32)FPL011MIS_OEMIS | (u32)FPL011MIS_BEMIS | (u32)FPL011MIS_PEMIS | (u32)FPL011MIS_FEMIS)) != (u32)0) { /* Received Error Status interrupt */ FPl011ReceiveErrorHandler(uart_p, reg_value); } if ((reg_value & ((u32)FPL011MIS_RTMIS)) != (u32)0) { /* Received Timeout interrupt */ FPl011ReceiveTimeoutHandler(uart_p); } if (((reg_value) & ((u32)FPL011MIS_DSRMMIS | (u32)FPL011MIS_DCDMMIS | (u32)FPL011MIS_CTSMMIS | (u32)FPL011MIS_RIMMIS)) != (u32)0) { /* Modem status interrupt */ } /* Clear the interrupt status. */ FUART_WRITEREG32(uart_p->config.base_address, FPL011ICR_OFFSET, reg_value); } static void FPl011ReceiveErrorHandler(FPl011 *uart_p, u32 InterruptStatus) { uart_p->rxbs_error = 0; if (((InterruptStatus) & ((u32)FPL011MIS_OEMIS | (u32)FPL011MIS_BEMIS | (u32)FPL011MIS_PEMIS | (u32)FPL011MIS_FEMIS)) != 0) { uart_p->rxbs_error = 1; } (void)FPl011ReceiveBuffer(uart_p); if (0 == uart_p->rxbs_error) { if (uart_p->handler) { uart_p->handler(uart_p->args, FPL011_EVENT_RECV_ERROR, uart_p->receive_buffer.requested_bytes - uart_p->receive_buffer.remaining_bytes); } } } /** * @name: FPl011ReceiveDataHandler * @msg: * @param {*} * @return {*} */ static void FPl011ReceiveDataHandler(FPl011 *uart_p) { if ((u32)0 != uart_p->receive_buffer.remaining_bytes) { (void)FPl011ReceiveBuffer(uart_p); } if ((u32)0 == uart_p->receive_buffer.remaining_bytes) { if (uart_p->handler) { uart_p->handler(uart_p->args, FPL011_EVENT_RECV_DATA, uart_p->receive_buffer.requested_bytes - uart_p->receive_buffer.remaining_bytes); } } } static void FPl011ReceiveTimeoutHandler(FPl011 *uart_p) { u32 event; if ((u32)0 != uart_p->receive_buffer.remaining_bytes) { (void)FPl011ReceiveBuffer(uart_p); } if ((u32)0 == uart_p->receive_buffer.remaining_bytes) { event = FPL011_EVENT_RECV_TOUT; } else { event = FPL011_EVENT_RECV_DATA; } if (uart_p->handler) { uart_p->handler(uart_p->args, event, uart_p->receive_buffer.requested_bytes - uart_p->receive_buffer.remaining_bytes); } } static void FPl011SendDataHandler(FPl011 *uart_p, u32 InterruptStatus) { FPl011SendBuffer(uart_p); if (uart_p->send_buffer.remaining_bytes == (u32)0) { if (uart_p->handler) { uart_p->handler(uart_p->args, FPL011_EVENT_SENT_DATA, uart_p->send_buffer.requested_bytes); } } }