我一直在用C ++编写一个串口应用程序,它可以处理通过虚拟串口到我为Arm微处理器编写的蓝牙堆栈的双向通信。
嵌入式方面我很确定很好,因为在另一个主要从微处理器接收数据的应用程序中,永远不会导致崩溃。在这个应用程序中,我将C ++串行端口应用程序中的二进制数据以64字节块的形式发送到微处理器,并使用简单的协议来控制何时停止发送等等。
我处理这两个应用程序的方式非常相似,所以我想知道当我发送数据而不是接收导致问题时是否存在差异。
代码在Visual Studio 2010中编写和调试。
我发现一件非常不寻常的事情是这个应用程序可以使用USB到串行有线连接但在虚拟COM端口上死锁!同时调试上位处理器那边似乎没有任何问题,那么可能导致这个问题呢?
修改
Hacving深入研究了挂起发生的callstack:
ntdll.dll!_ZwWriteFile@36()+ 0x15 bytes
它基本上是这样的:
初始化:
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);
}
主要应用
这里我等待用户命令启动,将其发送到上位处理器,等待响应,发送包,等待响应等,直到发送完整的二进制文件。
我在这里省略了一些不相关的部分,比如我如何处理文件的结尾等等。
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 :(得分:0)
我根本不是专家。但是我在串行端口玩了一下..
我不确定在阅读您的代码时我是否可能遗漏了某些内容,但我不知道您是否设置了写入或读取的超时时间。
另外,您如何处理数据终端就绪线?由于这个原因,我发生了各种奇怪的事情。
答案 1 :(得分:0)
dev_cont_block.fOutxCtsFlow = TRUE;
块引用 fOutxCtsFlow 如果该成员为TRUE,则监视CTS(清除发送)信号以进行输出流控制。如果此成员为TRUE且CTS已关闭,则输出将暂停,直到再次发送CTS。