2022-11-10 22:22:48 +08:00
|
|
|
|
/*
|
|
|
|
|
* 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
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* Date: 2021-11-02 14:53:42
|
2022-11-10 22:22:48 +08:00
|
|
|
|
* LastEditTime: 2022-02-18 09:06:30
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* Description: This file is for uart irq functions
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*
|
|
|
|
|
* Modify History:
|
|
|
|
|
* Ver Who Date Changes
|
|
|
|
|
* ----- ------ -------- --------------------------------------
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* 1.0 huanghe 2021/11/2 first commit
|
|
|
|
|
* 1.1 liushengming 2022/02/18 fix bugs
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************** 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);
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-02 13:27:09 +08:00
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011InterruptClear
|
|
|
|
|
* @msg: This function clears all interrupt state.
|
|
|
|
|
* @param uart_p is a pointer to the uart instance
|
|
|
|
|
*/
|
|
|
|
|
void FPl011InterruptClearAll(FPl011 *uart_p)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(uart_p != NULL);
|
|
|
|
|
|
|
|
|
|
if (FUART_READREG32(uart_p->config.base_address, FPL011RIS_OFFSET))
|
|
|
|
|
{
|
|
|
|
|
FUART_WRITEREG32(uart_p->config.base_address, FPL011ICR_OFFSET, 0xFFFFFFFF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-10 22:22:48 +08:00
|
|
|
|
/**
|
|
|
|
|
* @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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|