2015-02-10 48 views
0

我一直在用C++編寫一個串行端口應用程序,它可以通過虛擬串行端口處理雙向通信到我爲ARM寫的藍牙堆棧微處理器。一些非固定數量的寫入後,串行端口導致死鎖(C++)

我相當肯定的嵌入式方面很好,因爲在另一個主要從微處理器接收數據的應用程序中不會導致崩潰。在這個應用程序中,我使用一個簡單的協議將二進制數據從C++串口應用程序發送到64字節的微處理器,以控制何時停止發送等等。

我處理這兩個應用程序的方式非常相似,所以我想知道當我發送數據而不是接收它時導致問題時是否有區別。

代碼編寫和調試在Visual Studio 2010中

有一件事我發現真是難得的是,這個應用程序使用一個USB轉串口線連接但在虛擬COM端口僵局!同時調試處理器似乎沒有任何問題,所以可能會導致這個問題?

編輯

Hacving看着更深的坑偏偏執行調用堆棧:

[email protected]()+ 0×15字節

它基本上進入像這樣:

Initialis E:

brate = CBR_112500; 
com_name[0]='C'; 
com_name[1]='O'; 
com_name[2]='M'; 
com_name[3]=com_name[4]=com_name[5]=com_name[6]=0; 


printf("Select COM Port: "); 
scanf("%s", &com_name[3]); 

if (Connect(com_name,brate)!=SLCONNECT_OK) 
{ 
    printf("\t\t\t\t....Could not open to port, exiting\r\n"); 
} 

連接:

在這裏,我本來創建第二個線程來處理讀取,但決定也許是死鎖的原因。然後我刪除線程並同步運行所有內容,但仍然存在相同的問題。

int Connect(const char *portname,int baudrate) 
{ 

    DCB dev_cont_block; 

    if (port_h != INVALID_HANDLE_VALUE) 
    { 
     return(SLCONNECT_ALREADY_CONNECTED); 
    } 

    if(strlen(portname)>4) // if COM10 or above use \\.\COM10 
    { 
     char *longportname; 
     int i; 
     longportname = (char *) malloc(strlen(portname)+5); 
     if(longportname != NULL) 
     { 
      longportname[0] = '\\'; 
      longportname[1] = '\\'; 
      longportname[2] = '.'; 
      longportname[3] = '\\'; 
      for(i=0;i<strlen(portname);i++) 
       longportname[4+i]=portname[i]; 
      longportname[4+i] = 0; 

      port_h = CreateFile(longportname, GENERIC_READ | GENERIC_WRITE ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); 
      delete(longportname); 
     } 
     else 
      return(SLCONNECT_CONNECT_FAILED); 
    } 
    else 
     port_h = CreateFile(portname, GENERIC_READ | GENERIC_WRITE ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); 

    if (port_h==INVALID_HANDLE_VALUE) 
    { 
     return(SLCONNECT_CONNECT_FAILED); 
    } 

    if (GetCommState(port_h,&dev_cont_block)) 
    { 
     dev_cont_block.BaudRate = baudrate; 
     dev_cont_block.ByteSize = 8; 
     dev_cont_block.StopBits = ONESTOPBIT; 
     dev_cont_block.fParity = FALSE; 
     dev_cont_block.Parity = NOPARITY; 
     dev_cont_block.fOutxCtsFlow = TRUE; 
     dev_cont_block.fOutxDsrFlow = FALSE; 
     dev_cont_block.fRtsControl = RTS_CONTROL_DISABLE; 

     if (!SetCommState(port_h, &dev_cont_block)) return(SLCONNECT_SETUP_PORT_FAILED); 
    } 
    else return(SLCONNECT_SETUP_PORT_FAILED); 

    PurgeComm(port_h,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); 
    keepLooping=1; 
    ///_beginthread(Watcher,0,this); 
    //WatcherThread = (HANDLE)_beginthreadex(NULL, 0, Watcher, this, 0, NULL); 



    return(SLCONNECT_OK); 
} 

主要應用

我在這裏等待用戶命令啓動,將其發送到uprocessor,等待響應,送包,等待響應等,直到完整的二進制文件被髮送。

我在這裏省略了一些不相關的部分,比如我如何處理文件的結尾等等。

sendbuf[0] = 'x'; // The 'x' is just a placeholder 
sendbuf[1] = 'x'; 
sendbuf[2] = 'x'; 
sendbuf[3] = 'x'; 
sendbuf[4] = 'x'; 
sendbuf[5] = 'x'; 
sendbuf[6] = 'x'; 
sendbuf[7] = 'x'; 


printf("Press 1 to begin Upgrade\r\n"); 


if(_getch() == '1') 
{ 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    Send('x'); 
    if(Send('x') == SLSEND_OK) 
    { 
     printf("=> Note 'Set Firmware Mode'"); 
    } 
} 

while(1) 
{ 


while(true) 
{ 
    ClearCommError(port_h,&l_dwErrors, &l_ComStat); 
    if(l_ComStat.cbInQue) 
    { 
     ReadFile(port_h, &data, 1, &Received, NULL); 
     if(Received == 1) 
     { 
      Received = DllRxD(DataBuffer,64, data); 
      if(Received > 0) 
      { 
       if (DataBuffer[0] == 'x') //Note received 
       { 
        printf("\n\r=> Note "); 
        if(DataBuffer[3] == 'x' && DataBuffer[4] == 'x') 
        { 

         if(DataBuffer[5] == 'x') 
         { 
          if(DataBuffer[6] == 0x00) 
          { 
           printf("'Firmware Packet Received Sucessfully'"); 
           result = 1; 
           break; 

          } 
          else 
          { 
           printf("'Error In Packet Message [0x0%d]'",(unsigned int)DataBuffer[6]); 
           result = -1; 
           break; 

          } 
         } 
        } 
        if(DataBuffer[3] =='x' && DataBuffer[4] == 'x') 
        { 
         if(DataBuffer[5] == 'x') 
         { 
          printf("Mode has changed to: Firmware Upgrade Mode"); 
          result = 2; 
          break; 
         } 

        } 
       } 
       else 
       { 
        printf("=> ERRROR 'Unexpected Message'"); 
        result = -2; 
        break; 
       } 
      } 
     } 
    } 
}//while(true) 

    if(result == 1 || result == 2) 
    { 

     UpdateCRC('x', &crc); 
     UpdateCRC('x', &crc); 
     UpdateCRC('x', &crc); 
     UpdateCRC('x', &crc); 
     UpdateCRC('x', &crc); 
     UpdateCRC('x', &crc); 
     UpdateCRC('x', &crc); 
     UpdateCRC('x', &crc); 

     for (i = 0; i < 64; i++) 
     { 
      fread(&Packet[i],1,1,pFile); 
      if(feof(pFile)) 
       Packet[i] = 0xFF; 

      if(Packet[i] == 'x') 
      { 
       UpdateCRC(Packet[i],&crc); 
       UpdateCRC(Packet[i],&crc); 

      } 
      else 
       UpdateCRC(Packet[i],&crc); 
     } 

     UpdateCRC('x', &crc); 
     UpdateCRC('x', &crc); 


     Send(x); //framing 
     Send(x); 
     Send('x'); 
     Send('x'); 
     Send('x'); 
     Send('x'); 
     Send('x'); 
     Send('x'); 

     for (i = 0; i < 64; i++) 
     { 
      if(Packet[i] == 'x') 
      { 
       Send(Packet[i]); **//this set of sends is where i receive the deadlock error message, it's not always the same place it happens though** 
       Send(Packet[i]); 
      } 
      else 

       Send(Packet[i]); 
     } 

     Send('x'); 
     Send('x'); 
     Send((crc >> 8)); 
     if(Send((crc & 0xFF)) == SLSEND_OK) 
     { 
      printf("\n\r\t\t\t\t....Packet Sent (%u Bytes Total)",counter*64); 
     } 

發送

這是實際的發送功能

int Send(unsigned char sdata) 
{ 
    unsigned long bytesWritten=0; 
    unsigned int rtn; 

    **//This is where the program stops in the source code i can view** 
    //Error received is "this is the next statement to execute when this thread returns from it's current function" 
    rtn = WriteFile(port_h,&sdata,1,&bytesWritten,NULL); 

    if (rtn) 
     return(SLSEND_OK); 
    else 
     return(SLSEND_UNKNOWN_ERROR); 
} 

回答

0

林沒有專家,都在這。但是我在serialports上玩過一段時間..

林不知道如果我可能會失去一些東西,當我讀你的代碼,但我不知道如果你設置寫或讀的超時。

此外,您如何處理數據終端就緒線?我有各種奇怪的事情發生,由於這..

+0

我已經開始處理超時現在和數據終端就緒線,我已經嘗試啓用和禁用它(我使用沒有真正的硬件線,因爲它遍佈藍牙),仍然有相同的死鎖。 「這是線程從當前函數返回時要執行的下一個語句」位於我稱之爲writefile的行上 – 2015-02-11 10:34:21

0

dev_cont_block.fOutxCtsFlow = TRUE;

塊引用 fOutxCtsFlow 如果此部件是TRUE時,CTS(清除以發送)信號被輸出流量控制監視。如果此成員爲TRUE且CTS已關閉,則輸出將暫停,直到CTS再次發送。