N32905裸机C开发,在串口偶尔数据帧丢失调试日志

项目是基于32905处理器LCD串口屏,裸机跑C代码。主要是通过串口接收指令,然后按照指令将相应的数据或素材显示到LCD屏上,实现一个串口屏功能。

在串口使用过程中总是偶尔出现数据帧丢失,具体表现:
  1、串口进入中断处理函数后,偶尔在中断处理函数中读FSR状态寄存器,u32Count = (inpw(REG_UART_FSR+u32UartPort) & Rx_Pointer) >> 8; 得到FIFO中的可读数据数量为0,为什么可读数据数量为0会进入中断
2、使能超时寄存器UA_TOR,    超时进入中断,偶尔也会出现在  u32Count = (inpw(REG_UART_FSR+u32UartPort) & Rx_Pointer) >> 8; 得到FIFO中的可读数据数量为0。

串口初始化:

static char pi8UartBuf[MAX_RECV_NUM];    //串口数据接收缓存buffer

static VOID uart0_init(VOID)
{
    WB_UART_T uart;
    UINT32 u32ExtFreq;

    memset(pi8UartBuf, 0, MAX_RECV_NUM);
    u32ExtFreq = sysGetExternalClock();

    sysUartPort0(0);
    uart.uiFreq = u32ExtFreq*1000;
    uart.uiBaudrate = 115200;
    uart.uiDataBits = WB_DATA_BITS_8;
    uart.uiStopBits = WB_STOP_BITS_1;
    uart.uiParity = WB_PARITY_NONE;
    uart.uiRxTriggerLevel = LEVEL_8_BYTES;
    sysInitializeUART0(&uart);

    sysUart0EnableInt(UART_INT_NONE);

    sysUart0Installcallback(0, uartdatavalid_handler);
    sysUart0Installcallback(1, uartdatatimeout_handler);
    sysUart0EnableInt(UART_INT_RDA);
    sysUart0EnableInt(UART_INT_RDTO);
    sysSetLocalInterrupt(ENABLE_IRQ);
    sysSetLocalInterrupt(ENABLE_FIQ);   //使能快中断 
    //注:将串口0中断优先级设置为快中断,必须比定时器中断优先级高,\
    //     否则用于刷新显存数据的定时器中断会导致串口数据频繁的丢失 
} 

串口驱动层代码

static PFN_SYS_UART_CALLBACK (pfnUartIntHandlerTable)[2][2]={0};

INT32 sysInitializeUART0(WB_UART_T *uart)
{
    /* Enable UART multi-function pins*/
    //outpw(REG_PINFUN, inpw(REG_PINFUN) | 0x80);
    //outpw(REG_GPAFUN, inpw(REG_GPAFUN) | 0x00F00000);	//Normal UART pin function 
    static BOOL bIsResetFIFO = FALSE;
    /* Check the supplied parity */
    if ((uart->uiParity != WB_PARITY_NONE) &&
        (uart->uiParity != WB_PARITY_EVEN) &&
        (uart->uiParity != WB_PARITY_ODD))

        /* The supplied parity is not valid */
            return WB_INVALID_PARITY;

    /* Check the supplied number of data bits */
    else if ((uart->uiDataBits != WB_DATA_BITS_5) &&
            (uart->uiDataBits != WB_DATA_BITS_6) &&
            (uart->uiDataBits != WB_DATA_BITS_7) &&
            (uart->uiDataBits != WB_DATA_BITS_8))

            /* The supplied data bits value is not valid */
            return WB_INVALID_DATA_BITS;

    /* Check the supplied number of stop bits */
    else if ((uart->uiStopBits != WB_STOP_BITS_1) &&
            (uart->uiStopBits != WB_STOP_BITS_2))

            /* The supplied stop bits value is not valid */
            return WB_INVALID_STOP_BITS;

    /* Verify the baud rate is within acceptable range */
    else if (uart->uiBaudrate < 1200)
            /* The baud rate is out of range */
            return WB_INVALID_BAUD;

    /* Reset the TX/RX FIFOs */
    if(bIsResetFIFO==FALSE)
    {
        outpw(REG_UART_FCR+u32UartPort, 0x07);
        bIsResetFIFO=TRUE;
    }
    /* Setup reference clock */
    _sys_uUARTClockRate = uart->uiFreq;

    /* Setup baud rate */
    sysSetBaudRate(uart->uiBaudrate);

    /* Set the modem control register. Set DTR, RTS to output to LOW,
        and set INT output pin to normal operating mode */ 
    //outpb(UART_MCR, (WB_DTR_Low | WB_RTS_Low | WB_MODEM_En)); 

    /* Setup parity, data bits, and stop bits */
    outpw(REG_UART_LCR+u32UartPort,(uart->uiParity | uart->uiDataBits | uart->uiStopBits));

    /* Timeout if more than ??? bits xfer time */
    outpw(REG_UART_TOR+u32UartPort, 0x80+0x20);

    /* Setup Fifo trigger level and enable FIFO */
    outpw(REG_UART_FCR+u32UartPort, (uart->uiRxTriggerLevel << 4) | 0x02);

    /* Enable HUART interrupt Only (Receive Data Available Interrupt & RX Time out Interrupt) */

    /* Timeout if more than ??? bits xfer time */
    outpw(REG_UART_TOR+u32UartPort, 0x7F);

    // hook UART interrupt service routine
    if (u32UartPort)
    {//==1 NORMAL UART
        _sys_uUartTxHead = _sys_uUartTxTail = NULL;
        sysInstallISR(IRQ_LEVEL_1, IRQ_UART, (PVOID)sysUart0ISR);
        sysEnableInterrupt(IRQ_UART);		
    }
    else
    {//==0 High SPEED
        _sys_uUartTxHead = _sys_uUartTxTail = NULL;
        sysInstallISR(FIQ_LEVEL_0, IRQ_HUART, (PVOID)sysUart0ISR);
        sysEnableInterrupt(IRQ_HUART);
    }
    _sys_bIsUARTInitial = TRUE;

    return Successful;
}
void sysUart0Installcallback(UINT32 u32IntType, PFN_SYS_UART_CALLBACK pfnCallback)
{
    if(u32IntType>1)
        return;
    if(u32IntType == 0)
    {
        pfnUartIntHandlerTable[i32UsedPort][0] = (PFN_SYS_UART_CALLBACK)(pfnCallback);
    }
    else if(u32IntType == 1)
    {
        pfnUartIntHandlerTable[i32UsedPort][1] = (PFN_SYS_UART_CALLBACK)(pfnCallback);
    }
}
static void uartdatatimeout_handler(UINT8* buf, UINT32 u32Len)
{
    UINT32 len;
    if((g_u32Idx + u32Len) > MAX_RECV_NUM) 
    {
        len =MAX_RECV_NUM-g_u32Idx;
        memcpy(&(pi8UartBuf[g_u32Idx]), buf, len);
        g_u32Idx=0;
        memcpy(&(pi8UartBuf[g_u32Idx]), &buf[len], u32Len-len);
        g_u32Idx =g_u32Idx+u32Len-len;
    }
    else
    {
        memcpy(&(pi8UartBuf[g_u32Idx]), buf, u32Len);
        g_u32Idx = g_u32Idx+u32Len; 
        if(g_u32Idx>=MAX_RECV_NUM)
        {
            g_u32Idx=0;
        }
    }
}

串口中断服务

static VOID sysUart0ISR()  //中断服务程序
{
    UINT32 volatile u32EnableInt,i;
    UINT32 volatile u32Count = 0;
    u32EnableInt = inpb(REG_UART_ISR + u32UartPort) & inpb(REG_UART_IER + u32UartPort);
    if (u32EnableInt & THRE_IF)
    {// buffer empty
        if (_sys_uUartTxHead == _sys_uUartTxTail) 
        {
            //Disable interrupt if no any request!  
            outpb((REG_UART_IER+u32UartPort), inp32(REG_UART_IER+u32UartPort) & (~THRE_IEN));
        }
        else
        {
            //Transmit data 
            for (i=0; i<8; i++)
            {
                #ifdef __HW_SIM__
 
                #else 
                    outpb(REG_UART_THR+u32UartPort, _sys_ucUartTxBuf[_sys_uUartTxHead]);
                #endif 
                _sys_uUartTxHead = sysTxBufReadNextOne();
                if (_sys_uUartTxHead == _sys_uUartTxTail) // buffer empty
                    break;
            }
        }
    }
    if(u32EnableInt & RDA_IF)
    {	

        while((inpw(REG_UART_FSR+u32UartPort) & Rx_Pointer))			
        {	
            uart_rx[rx_cnt++] = (inpb(REG_UART_RBR+u32UartPort));		
        }			
    }
    u32EnableInt = inpb(REG_UART_ISR + u32UartPort) & inpb(REG_UART_IER + u32UartPort);
    if(u32EnableInt & Tout_IF)//接收状态分析
    {

        while((inpw(REG_UART_FSR+u32UartPort) & Rx_Pointer) )			
        {	
            uart_rx[rx_cnt++] = (inpb(REG_UART_RBR+u32UartPort));		
        }
    }
    pfnUartIntHandlerTable[i32UsedPort][0](&(uart_rx[0]), rx_cnt);
    rx_cnt=0;
} 

经过时间跟踪调试,发现自己掉进粪坑里面了,产生丢帧问题并不是串口驱动引起的,原因是被其他模块定时器中断影响了

Guess you like

Origin blog.csdn.net/ggggyj/article/details/84527141