多任务下与UART FIFO有关的问题
附加程序: 这些代码是由我基于TI uart.c驱动程序库编写的。多任务下与UART FIFO有关的问题
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传输有关的错误。
这是我对我的程序的描述: 该程序基于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.当我把读取和发送到一个线程时,数据非常好,没有这个bug。 2.我在我的UART驱动程序中设置计数,发现发送的数量是正确的,这里发送是将字节放入TX FIFO。但是,在Excel中,我通过JAVA UART程序读取数据,错过了。并且JAVA UART程序应该可以,因为当我使用单线程测试时它运行良好。 3.调试时CCS不会产生内存泄漏错误。
所以我想,在多线程环境下,我将UART字节放入之后,某些东西停止了我的UART TX FIFO传输。但是我无法找到我的代码中哪里出错,它们都似乎是正确的。
另一个合理的原因可能是改变我的指针在中断,在链接的图片“pCurrentWrite”指针。但该指针只能由UART驱动程序访问,并且在中断完成之前,下一个UART写入无法进入。
我在链接中包含了部分代码,我想表明数据已放入TX FIFO中,并且发送计数正确。
我不能包含所有代码,我不认为有人想检查这些长代码。没有运行它,很难找出哪里出错。
所以,我只想描述我遇到的情况,看看有没有人有过类似的bug。也许有人知道多线程环境下UART FIFO的问题。如果能够帮助的人希望看到代码,我们可以进一步联系。
谢谢(我的新帐户不能包含图片的是,图片下面链接)
尽管包括使用旗语的,我会建议进一步reading on mutual exclusion and shared resources.
的解决方案是过于复杂,这将有助于更好地抽象和简化代码。
注意:你的should not cast the result of malloc。
UART_Handle = (UART_HANDLE)malloc(sizeof(UART_STATE));
我很感谢你的回答。我会查找那些,看看有什么不对。 – DoubleFred
提示:没有人会在没有看到任何代码的情况下阅读这段文字。 –
没有任何代码,就不可能说出你的bug。但只是猜测;你需要在你的任务之间进行某种同步。你说你有一个FIFO。这必须受到一些同步原语的保护。据我所知,FreeRTOS拥有互斥量,用它来保护你的FIFO。 – user1048576
感谢您的称赞,我现在会发布一些代码。但他们会以链接形式。 @ user1048576,我使用的是UART的硬件FIFO,我没有创建FIFO,并且FIFO由来自uart.c驱动程序文件的API调用处理。而且,我还可以为这种FIFO添加保护吗?感谢您的建议。 – DoubleFred