2017-10-13 8 views
-1

プログラム添付: これらのコードは、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に基づいています。 2つのスレッドが並行して実行されます。 I2Cドライバによって1つのスレッドがセンサーから読み取り中です。別のものは、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.読み込みと送信を1つのスレッドにすると、このバグがなくてもデータは非常に良好です。 2.私のUARTドライバでカウントを設定し、送信量が正しいことがわかりました。ここで送信はTX FIFOにバイトを入れています。しかし、Excelでは、私は、JAVA UARTプログラムによって読み込まれたデータを見逃しました。そして、私はシングルスレッドのテストを使用するときにうまく動作するので、Java UARTプログラムはOKである必要があります。 3.デバッグ中にCCSによるメモリリークエラーが発生しません。

私は、マルチスレッド環境下で、バイトを入れた後で何かが私のUART TX FIFO送信を停止したと考えています。しかし、私のコードでどこが間違っているかを知ることはできません。

もう一つの合理的な理由は、何か私のポインタは、割り込みの中で、リンクされた画像では "pCurrentWrite"ポインタを変更することができます。しかし、そのポインタはUARTドライバによってのみアクセスされ、割り込みが終了する前に、次のUART書き込みは入力できません。

リンクに部分コードが含まれています。ここで、データがTX FIFOに格納されていることを示し、送信カウントが正しいことを示します。

私はすべてのコードを含めることはできません、私は誰もそれらの長いコードをチェックしたいとは思わない。それを実行することなく、どこが間違っているかを知ることは困難です。

私は会った状況を説明し、誰かが以前に同様のバグを持っていたかどうかを確認したいと思います。そして、マルチスレッド環境下で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

+1

ヒント:誰もこの壁にコードを見ずにこの壁を読むことはできません。 –

+1

コードがなくても、あなたのバグについては何も言えません。しかし、ちょうど推測。あなたの仕事の間に何らかの種類の同期が必要です。あなたはFIFOを持っていると言います。それは何らかの同期プリミティブによって保護されなければならない。 FreeRTOSは私が覚えている限りミューテックスを持っています。それを使ってFIFOを保護します。 – user1048576

+0

ありがとうございます。今すぐコードを投稿します。しかし、彼らはリンクの形になります。 @ user1048576、私はUARTのハードウェアFIFOを使用していますが、私はFIFOを作成していないし、FIFOはuart.cドライバファイルからのAPI呼び出しによって認識されます。そして、この種のFIFOにも保護機能を追加できますか?アドバイスありがとう。 – DoubleFred

答えて

0

あなたがセマフォの使用が含まれているが、私はさらにreading on mutual exclusion and shared resources.

を示唆しているソリューションであります過度に複雑であり、コードをより抽象的にして単純化することが適切です。

注:お客様はshould not cast the result of mallocです。

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

私はあなたの答えをありがとう。私はそれらを見上げて、何が間違っているか見てみましょう。 – DoubleFred