gpt4 book ai didi

c - 多任务下与UART FIFO相关的Bug

转载 作者:行者123 更新时间:2023-11-30 19:32:43 24 4
gpt4 key购买 nike

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

        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;
}

我长期以来一直在处理多线程错误。经过多次测试,我发现这个bug很可能与UART FIFO传输有关。

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

问题描述:我的数据读取只能持续 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”并继续直到计时结束。 this is plot of one channel of my data, begin with 8 and changing

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

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

另一个合理的原因可能是中断中我的指针发生了变化,在链接图片中是“pCurrentWrite”指针。但该指针只能由UART驱动程序访问,在中断完成之前,下一次UART写入无法进入。

我在链接中包含了部分代码,我想在其中显示数据已放入 TX FIFO,并且发送计数是正确的。

我无法包含所有代码,我认为没有人想检查那些长代码。而且如果不运行它,就很难找出问题所在。

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

谢谢(我的新帐户还不能包含图片,图片链接如下)

This code is part of my UART driver, in the sending interrupt. I use the PutCharNonBlocking to put byte, since it return 1 if success, return 0 if FIFO full, so in this way I make sure the program will send all my data into the FIFO, which turn out to be true, all data was put into the TX FIFO

最佳答案

虽然您已经包含了信号量的使用,但我会进一步建议 reading on mutual exclusion and shared resources.

该解决方案过于复杂,需要更好地抽象代码并简化。

注意:你 should not cast the result of malloc .

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

关于c - 多任务下与UART FIFO相关的Bug,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46737663/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com