Colibri VF61 IT 256
Win CE6
I am outputting log data to UARTB on a Colibri VF61. Because the parameters may change, I open the port with CreateFile() before each WriteFile() and CloseHandle() afterwards. This appears to allocate a block of memory about every three or four writes, eventually returning an OUT_OF_MEMORY error (14) when calling CreateFile(). I have written a test program which writes every 100 milliseconds to cause the error quicker.
The code below is from the Windows MFC TestCOMleak:
// ChildView.cpp : implementation of the CChildView class
//
#include “stdafx.h”
#include “TestCOMleak.h”
#include “ChildView.h”
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CChildView
CChildView::CChildView()
{
m_bTimerStarted = FALSE;
m_hPort = INVALID_HANDLE_VALUE;
}
CChildView::~CChildView()
{
KillTimer(1);
CloseRS232Port();
}
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
ON_WM_TIMER()
END_MESSAGE_MAP()
// CChildView message handlers
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CWnd::PreCreateWindow(cs))
return FALSE;
cs.style &= ~WS_BORDER;
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL);
return TRUE;
}
void CChildView::OnPaint()
{
CPaintDC dc(this); // device context for painting
if ( !m_bTimerStarted )
{
OpenRS232Port();
SetTimer(1, 100, NULL);
m_bTimerStarted = TRUE;
}
}
HRESULT CChildView::OpenRS232Port()
{
static DCB dcb;
static COMMTIMEOUTS cto;
BOOL bConnected;
DWORD dwError;
TCHAR szPort[8] = _T(“COM2:”);
CloseRS232Port();
bConnected = FALSE;
m_hPort= CreateFile(szPort,
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (m_hPort != INVALID_HANDLE_VALUE)
{
dcb.DCBlength = sizeof(DCB);
GetCommState(m_hPort, &dcb);
dcb.BaudRate = CBR_19200;
dcb.fParity = FALSE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
dcb.fTXContinueOnXoff = FALSE;
dcb.fOutX = FALSE; // Dont use XON/XOFF
dcb.fInX = FALSE; // Dont use XON/XOFF
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fAbortOnError = FALSE;
dcb.fDummy2 = FALSE;
// dcb.wReserved = 0;
// dcb.XonLim = 0;
// dcb.XoffLim = 0;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
// dcb.XonChar = 0;
// dcb.XoffChar = 0;
// dcb.ErrorChar = 0;
// dcb.EofChar = 0;
// dcb.EvtChar = 0;
// dcb.wReserved1 = 0;
if (SetCommState(m_hPort, &dcb))
{
// Disable read and write timeouts.
cto.ReadIntervalTimeout = 0;
cto.ReadTotalTimeoutMultiplier = 0;
cto.ReadTotalTimeoutConstant =0;
cto.WriteTotalTimeoutMultiplier = 0;
cto.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(m_hPort, &cto);
}
else
{
DWORD dwError = GetLastError();
ATLTRACE(_T("Error setting I/O Port.\n"));
}
bConnected = TRUE;
}
else
{
dwError = GetLastError();
ATLTRACE(_T("Failed to open %s\n"), szPort);
}
return S_OK;
}
void CChildView::CloseRS232Port()
{
if ( m_hPort != INVALID_HANDLE_VALUE )
{
BOOL bRes = CloseHandle(m_hPort);
if (!bRes)
{
DWORD dwError = GetLastError();
ATLTRACE(_T(“CloseRS232Port error: %ld\n”), dwError);
}
m_hPort = INVALID_HANDLE_VALUE;
}
}
void CChildView::OnTimer(UINT_PTR nIDEvent)
{
static DWORD dwStartAvailMem = 0;
static DWORD dwLastAvailMem = 0;
MEMORYSTATUS ms;
DWORD dwCount = 0;
char szLog[128] = “\nBW0329,805,PAEC/A,0,2.63,151.66,0.00,0.00,5.84,79,9fe\r”;
OpenRS232Port();
if ( m_hPort != INVALID_HANDLE_VALUE )
{
BOOL bRes = WriteFile(m_hPort, szLog, strlen(szLog), &dwCount, NULL);
Sleep(4*CBR_115200/CBR_19200); // other operations truncate/break transmission! Must add delay for baud under 115,200.
if ( !bRes )
{
TCHAR szMessage[256];
DWORD dwError = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, dwError, LANG_USER_DEFAULT, szMessage, 256, NULL);
ATLTRACE(_T("COM: Write Error\n%s"), szMessage);
}
}
CloseRS232Port();
GlobalMemoryStatus(&ms);
if ( dwStartAvailMem == 0 )
dwStartAvailMem = ms.dwAvailPhys;
if ( ms.dwAvailPhys != dwLastAvailMem )
{
long lTotal = (long)dwStartAvailMem - (long)ms.dwAvailPhys;
long lNew = (dwLastAvailMem > 0) ? (long)dwLastAvailMem - (long)ms.dwAvailPhys : 0;
ATLTRACE(_T("Total Blocks: %d\tNew Blocks: %d\n"), lTotal/4096, lNew/4096);
if ( lNew < (-4096 * 2) )
ATLTRACE(_T("Memory freed.\n"));
dwLastAvailMem = ms.dwAvailPhys;
}
CWnd::OnTimer(nIDEvent);
}