本文介绍了与多任务下的UART FIFO有关的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

附加程序:这些代码由我根据TI uart.c驱动程序库编写.

Program attached: Those codes are written by me based on the TI uart.c driver library.

        while(1){
        //check if message on Queue -> read or check UART input
        if(uxQueueMessagesWaiting( UART_TASKQ ) != 0){ //may have bugs

        // deQueue
        xQueueReceive( UART_TASKQ, &UARTTaskHandle, 0x0A );
        //do the task's mission using the data in the stucture(put by control 
        task)
        //Print out the input data.

        //**********debugging data
/*
        testPointer = UARTTaskHandle->dataBuffer;
        testAmount = UARTTaskHandle->dataSize;

        while(testAmount){
            if(*testPointer != 1){
                error = error + 1;
            }
            if(*(testPointer + 1) != 2){
                error = error + 1;
            }
            if(*(testPointer + 2) != 3){
                            error = error + 1;
                        }
            if(*(testPointer + 3) != 4){
                            error = error + 1;
                        }
            if(*(testPointer + 4) != 5){
                            error = error + 1;
                        }
            if(*(testPointer + 5) != 6){
                            error = error + 1;
                        }
            if(*(testPointer + 6) != 7){
                            error = error + 1;
                        }
            if(*(testPointer + 7) != 8){
                            error = error + 1;
                        }

            testPointer = testPointer + 8;
            testAmount = testAmount - 8;
        }
*/

        if(UART_write(UART_Handle, UARTTaskHandle->dataBuffer, UARTTaskHandle->dataSize, 0xff ) >= 0){
        UARTwriteCount = UARTwriteCount + 1;
        }

        //let control task take new command
        //free allocated memory
        free(UARTTaskHandle->dataBuffer);
        free(UARTTaskHandle); // free memory space

//(above is code using UART)


//here are UART driver code:


     unsigned long UARTStatus(unsigned long ulBase){
    ASSERT(UARTBaseValid(ulBase));
    return(HWREG(ulBase + UART_O_FR));
}
//*****************************************
//UART_ISR
//Interrupt service routine for
//the UART read and write process
//*****************************************
void UART_ISR(){


    //read FIFO full or read time out
    if(UARTIntStatus(UART_Handle->UART_PORT,false) & (UART_INT_RX | UART_INT_RT)){
        UARTIntClear(UART_Handle->UART_PORT, UART_INT_RX | UART_INT_RT);    //clear INT flag

        while (!(UARTStatus(UART_Handle->UART_PORT) & UART_FR_RXFE)){
            //data reading
            *UART_Handle->pCurrentRead = UARTCharGet(UART_Handle->UART_PORT); //read autoly clear INT
            UART_Handle->pCurrentRead++;
            UART_Handle->ReadLength--;

            //adjust code here:
            if(UART_Handle->ReadLength == 0){
                break;
            }
        }

        //check if read certain bytes finished
        if(UART_Handle->ReadLength == 0){
            memcpy(UART_Handle->dataput, UART_Handle->pReadBuf,UART_Handle->ReadLengthcpy); // copy data back
            xSemaphoreGiveFromISR( UART_Handle->UARTRead_Semaphore, &xHigherPriorityTaskWoken );// release semaphore
            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );//forcing context exchange
        }

    }

    //send FIFO empty
    if(UARTIntStatus(UART_Handle->UART_PORT,false) & UART_INT_TX){

        UARTIntClear(UART_Handle->UART_PORT, UART_INT_TX);  //clear INT flag

        if(UART_Handle->WriteLength == BUFFEMPTY){

            UART_Handle->UART_SendComplete = true;

            xSemaphoreGiveFromISR( UART_Handle->UARTWrite_Semaphore, &xHigherPriorityTaskWoken );// release semaphore
            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );//forcing context exchange
        }

            //putting data into send FIFO
                if(UART_Handle->WriteLength > FIFOMAX){
                    for( Cindex = 0 ; Cindex < FIFOMAX ;){
                        if(UARTCharPutNonBlocking(UART_Handle->UART_PORT, *(UART_Handle->pCurrentWrite))){//write autoly clear INT
                            (UART_Handle->pCurrentWrite) = (UART_Handle->pCurrentWrite) + 1;
                            (UART_Handle->WriteLength) = (UART_Handle->WriteLength) - 1;
                            Cindex = Cindex + 1;
                            UART_Handle->sentCount = UART_Handle->sentCount + 1;
                        }
                    }
                }else{
                    templength = UART_Handle->WriteLength;
                    for( Cindex = 0; Cindex < templength ;){
                        if(UARTCharPutNonBlocking(UART_Handle->UART_PORT, *(UART_Handle->pCurrentWrite))){//write autoly clear INT
                            (UART_Handle->pCurrentWrite) = (UART_Handle->pCurrentWrite) + 1;
                            (UART_Handle->WriteLength) = (UART_Handle->WriteLength) - 1;
                            Cindex = Cindex + 1;
                            UART_Handle->sentCount = UART_Handle->sentCount + 1;
                        }
                    }
                }

    }

}

//*****************************************
//UART_write
//write certain length of data to UART port
//*****************************************
int32_t UART_write( UART_STATE *UART_Handle, uint8_t *pData, uint32_t length, uint32_t time_out ){


    while(!UART_Handle->UART_SendComplete); //debugging purpose
    UART_Handle->UART_SendComplete = false;//debugging purpose

    UART_Handle->WriteLength = length;

    if(UART_Handle->WriteLength <= UART_Handle->WriteBufSize){

        UARTIntClear(UART_Handle->UART_PORT, UART_INT_TX);  //clear INT flag

        memcpy(UART_Handle->pWriteBuf,pData,UART_Handle->WriteLength); //copy data into writebuff
        UART_Handle->pCurrentWrite = UART_Handle->pWriteBuf;
        //putting data into send FIFO
        if(UART_Handle->WriteLength > FIFOMAX){
            // if
            for( Cindex = 0 ; Cindex < FIFOMAX ;){
                if(UARTCharPutNonBlocking(UART_Handle->UART_PORT, *(UART_Handle->pCurrentWrite))){//write autoly clear INT
                    (UART_Handle->pCurrentWrite) = (UART_Handle->pCurrentWrite) + 1;
                    (UART_Handle->WriteLength) = (UART_Handle->WriteLength) - 1;
                    Cindex = Cindex + 1;
                    UART_Handle->sentCount = UART_Handle->sentCount + 1;
                }
            }
        }else{
            for( Cindex = 0 ; Cindex < FIFOMAX ;){
                if(UARTCharPutNonBlocking(UART_Handle->UART_PORT, *(UART_Handle->pCurrentWrite))){//write autoly clear INT
                    (UART_Handle->pCurrentWrite) = (UART_Handle->pCurrentWrite) + 1;
                    (UART_Handle->WriteLength) = (UART_Handle->WriteLength) - 1;
                    Cindex = Cindex + 1;
                    UART_Handle->sentCount = UART_Handle->sentCount + 1;
                }
            }
        }

        //start sending
        UARTEnable(UART_Handle->UART_PORT);

        if(UART_Handle->UARTWrite_Semaphore != NULL ) {
            if(xSemaphoreTake(UART_Handle->UARTWrite_Semaphore, time_out/(portTICK_PERIOD_MS) ) == pdTRUE){
                reValue = WRITESUCCESS; //wait return till write complete

            }else{
                reValue = WRITETIMEOUT; // timeout (ms)

                 }
        }else{
            while(1); //no Semaphore
             }

        return reValue;

    }else{
        return FAILURE; //wrong length
    }

}

//*****************************************
//UART_read
//read certain length of data from UART port
//*****************************************
int32_t UART_read(UART_STATE *UART_Handle, uint8_t *pData, uint32_t length, uint32_t time_out){



    //later added part
    UARTDisable(UART_Handle->UART_PORT);    //clearUART
    UARTFIFOEnable(UART_Handle->UART_PORT);
    //

    UART_Handle->ReadLength = length;   // set readlength
    UART_Handle->ReadLengthcpy = length;

    if(UART_Handle->ReadLength <= UART_Handle->ReadBufSize){

        UARTIntClear(UART_Handle->UART_PORT, UART_INT_RX | UART_INT_RT);    //clear INT flag
        UART_Handle->dataput = pData; //store the destination buffer address
        UART_Handle->pCurrentRead = UART_Handle->pReadBuf; //set current read

        UARTEnable(UART_Handle->UART_PORT); //start receiving

        //suspend before read ISR finish whole process
        if(UART_Handle->UARTRead_Semaphore != NULL ) {
                    if(xSemaphoreTake(UART_Handle->UARTRead_Semaphore, time_out/(portTICK_PERIOD_MS) ) == pdTRUE){
                        reValue = READSUCCESS; //wait return till write complete
                    }else{
                        reValue = READTIMEOUT; // timeout (ms)
                         }
                }else{
                    while(1); //no Semaphore
                     }

                return reValue;

    }else{
        return FAILURE; //wrong length
    }
}

//*****************************************
//UART_open
//open UART for certain port and bandrate
//*****************************************
UART_HANDLE UART_open(uint32_t UART_port, uint32_t UART_portperiph, uint32_t UART_baudrate){

    //initialize structure
    UART_Handle = (UART_HANDLE)malloc(sizeof(UART_STATE));

    UART_Handle->ReadBufSize = UARTBUFFERSIZE;
    UART_Handle->WriteBufSize = UARTBUFFERSIZE;
    UART_Handle->UART_PORT = UART_port;
    UART_Handle->UART_PORTPERIPH = UART_portperiph;
    UART_Handle->UART_BRATE = UART_baudrate;
    UART_Handle->pWriteBuf = (uint8_t*)malloc(UART_Handle->WriteBufSize * sizeof(uint8_t));
    UART_Handle->pReadBuf = (uint8_t*)malloc(UART_Handle->ReadBufSize * sizeof(uint8_t));
    UART_Handle->pCurrentWrite = UART_Handle->pWriteBuf;
    UART_Handle->pCurrentRead = UART_Handle->pReadBuf;
    UART_Handle->UARTWrite_Semaphore = NULL;
    UART_Handle->UARTRead_Semaphore = NULL;
    UART_Handle->UARTprotect_Semaphore = NULL;
    UART_Handle->UART_SendComplete = true;

    UART_Handle->sentCount = 0;//debugging purpose

    vSemaphoreCreateBinary( UART_Handle->UARTWrite_Semaphore ); //semaphore create
    vSemaphoreCreateBinary( UART_Handle->UARTRead_Semaphore ); //semaphore create
//  vSemaphoreCreateBinary( UART_Handle->UARTprotect_Semaphore ); //debugging purpose
    xSemaphoreTake( UART_Handle->UARTRead_Semaphore, portMAX_DELAY );   //semaphore take
    xSemaphoreTake( UART_Handle->UARTWrite_Semaphore, portMAX_DELAY );  //semaphore take

    // Enable Peripheral Clocks
    MAP_PRCMPeripheralClkEnable(UART_Handle->UART_PORTPERIPH, PRCM_RUN_MODE_CLK);

    // Configure PIN_55 for UART0 UART0_TX
    MAP_PinTypeUART(PIN_55, PIN_MODE_3);

    // Configure PIN_57 for UART0 UART0_RX
    MAP_PinTypeUART(PIN_57, PIN_MODE_3);

    // configuration, 8 bits length data width, 1 stop bit, no parity check
    UARTConfigSetExpClk(UART_Handle->UART_PORT,PRCMPeripheralClockGet(  UART_Handle->UART_PORTPERIPH),
            UART_Handle->UART_BRATE, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
             UART_CONFIG_PAR_NONE));

    // disable UART since function above contained UARTenable
    UARTDisable(UART_Handle->UART_PORT);

    UARTIntEnable(UART_Handle->UART_PORT, UART_INT_TX | UART_INT_RX | UART_INT_RT); // enable interrupt for send and receive and receive timeout
    UARTIntRegister(UART_Handle->UART_PORT, UART_ISR);  //hook ISR
    UARTFIFOEnable(UART_Handle->UART_PORT); //enable FIFO for send and receive
    UARTFIFOLevelSet(UART_Handle->UART_PORT, UART_FIFO_TX1_8, UART_FIFO_RX4_8); //Interrupt occur when 7 bytes send from FIFO or read in FIFO


    return UART_Handle;
}

我长时间在处理多线程错误.经过多次测试,我知道该错误最有可能与UART FIFO传输有关.

I am dealing with a multi-thread bug for long time. After many test, I aware that the bug most possibly related to the UART FIFO transmitting.

这是我对程序的描述:该程序基于Free-RTOS.它有两个并行运行的线程.I2C驱动程序正在从传感器读取一个线程.另一个是通过UART驱动程序将数据从读取任务发送到计算机.我有一个多任务框架,可以将数据从读取任务传输到发送任务.我有一个计时器文件来控制实时测量.我的I2C驱动程序和UART驱动程序都是基于中断的.

Here is my description of my program:The program is based on Free-RTOS. It has two threads running in parallel. one thread is reading from sensor by I2C driver. another is sending data from the reading task to the computer by UART driver. I have a multi-task frame to transfer data from reading task to sending task. I have a timer file to control real time measuring. My I2C driver and UART driver are all interrupt based.

问题描述:我的数据读取仅持续2分钟.之后,我的数据转移了.在进行测试时,我阻止了I2C驱动程序,仅将恒定数据"1 2 3 4 5 6 7 8"放入I2C读取缓冲区,并将其传输到发送任务以进行UART发送. 2分钟后,我读出的数据将变为"8 1 2 3 4 5 6 7",并且在第一次更改后,随后的更改很快发生,即"7 8 1 2 3 4 5 6",并一直持续到计时结束.这是我数据的一个通道的图,从8开始并不断变化

Problem description: My data reading is good only for 2 mins. after that, my data shift. When do testing, I blocked the I2C driver, only put constant data "1 2 3 4 5 6 7 8" into the I2C read buffer, and transfer them to sending task to do UART send. And after 2 mins, my data read out will become "8 1 2 3 4 5 6 7" and after the first change, later changes happen quickly, "7 8 1 2 3 4 5 6" and continue till the end of timing. this is plot of one channel of my data, begin with 8 and changing

我已经为程序设置了许多测试,并且我确定我的多任务框架(从读取任务到发送任务的传输数据)不会更改数据.重要观察:1.当我将读取并发送到一个线程中时,数据非常好,没有此错误.2.我在UART驱动程序中设置了计数,发现发送的数量是正确的,这里的发送是将字节放入TX FIFO.但是,在Excel中,我通过JAVA UART程序读取,数据丢失.而且JAVA UART程序应该可以,因为当我使用单线程测试时它可以很好地工作.3.调试时CCS不会出现内存泄漏错误.

I set many test to my program already, and I am sure my multi-task frame (trans data from reading task to sending task) don't alter the data.Important observations: 1.when I put read and send into one thread, the data is very good, without this bug.2.I set counting in my UART driver, found that the amount of sending is correct, here the sending is putting bytes into the TX FIFO. However, in the Excel, I read by a JAVA UART program, data missed. And JAVA UART program should be ok, since it works well when I use the single thread testing. 3. no memory leak error pump up by CCS while debugging.

所以我想在多线程环境下,在我将字节放入其中之后,某些东西停止了我的UART TX FIFO传输.但是我找不到我的代码中哪里出了问题,它们似乎都是正确的.

So I am thinking, under the multi-thread environment, something stopped my UART TX FIFO transmit after I put bytes into that. But I can't find out where is wrong in my codes, they all seems correct.

另一个合理的原因可能是我的指针在中断中有所改变,在链接的图片中为"pCurrentWrite"指针.但是该指针只能由UART驱动程序访问,并且在中断完成之前,下一次UART写操作就无法进入.

And another reasonable reason can be something altered my pointer in the interrupt, in linked picture the "pCurrentWrite" pointer. But that pointer only accessed by UART driver, and before the interrupt finished, the next UART write can't enter.

我在链接中包含部分代码,在这里我想证明数据已放入TX FIFO中,并且发送计数正确.

I include partial code in the link, where I want to show that the data is put into the TX FIFO, and the send count is correct.

我不能包含所有代码,我认为没有人想检查这些长代码.而且如果不运行它,很难找出哪里出了问题.

I can't include all codes, I don't think anyone want to check those long codes. and without running it, it's hard to find out where is wrong.

所以,我只想描述我遇到的情况,看看以前是否有人遇到过类似的错误.也许有人知道多线程环境下的UART FIFO问题.如果有需要帮助的人想要查看代码,我们可以进行进一步的联系.

So, I just want to describe the situation i met, and see if someone had similar bug before. And maybe someone know the problem of UART FIFO under multi-thread environment. If someone who can help do want to see the code, we can do further contact.

谢谢(我的新帐户尚不能包含图片,下面的图片已链接)

thanks (My new account can't include picture yet, picture linked below)

此代码是发送中断中我的UART驱动程序的一部分.我使用PutCharNonBlocking放置字节,因为如果成功则返回1,如果FIFO已满则返回0,因此通过这种方式,我确保程序会将我的所有数据发送到FIFO中,事实证明这是事实,所有数据都已放入进入TX FIFO

推荐答案

尽管您已经包括了信号灯的使用,但我还是建议您进一步阅读互斥和共享资源.

Although you have included the use of semaphores, I would suggest further reading on mutual exclusion and shared resources.

该解决方案过于复杂,因此有必要更好地抽象您的代码并进行简化.

The solution is overly complex and it would be pertinent to better abstract your code and simplify.

注意:您不应该转换malloc的结果.

UART_Handle = (UART_HANDLE)malloc(sizeof(UART_STATE));

这篇关于与多任务下的UART FIFO有关的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-24 16:48