We have a standard PCI can card, and are developing in the following environment:
Software written in VC++ Version6,
running under NT4.0,
Port configured as 'CAN0',
using extended arbitration IDs.
We create one network interface object, and, depending on the test configuration, four CAN response objects.
The problems are :-
1) if the network interface object (nio) is configured as 'start on open'= TRUE then the other objects fail to initialise. If the other objects aren't started, the nio works perfectly though.
2) If the nio is configured not to start on open, the other objects will initialise successfully (obviously not a lot of use though).
Any attempt to call ncAction trying to start any of the objects will however fail with a status of 0xBFF62002, which is CanErrDriver.
Below is a stripped down set of events as to how we start our card.
AttrIdList[0] = NC_ATTR_BAUD_RATE;
AttrValueList[0] = 125000; //BaudRate;
AttrIdList[1] = NC_ATTR_START_ON_OPEN;
if( Response_Enabled == 0 )
{
AttrValueList[1] = NC_TRUE;
NotificationStates = (NC_ST_READ_AVAIL |
NC_ST_ERROR | NC_ST_WARNING | NC_ST_STOPPED);
}
else
{
AttrValueList[1] = NC_FALSE;
// don't look for stopped state else it
// will interrupt continuously.
NotificationStates =
(NC_ST_READ_AVAIL | NC_ST_ERROR |
NC_ST_WARNING);
}
AttrIdList[2] = NC_ATTR_READ_Q_LEN;
AttrValueList[2] = 50; //500;
AttrIdList[3] = NC_ATTR_WRITE_Q_LEN;
AttrValueList[3] = 20;
AttrIdList[4] = NC_ATTR_CAN_COMP_STD;
AttrValueList[4] = 0;
AttrIdList[5] = NC_ATTR_CAN_MASK_STD;
AttrValueList[5] = 0; // NC_CAN_MASK_STD_DONTCARE;
AttrIdList[6] = NC_ATTR_CAN_COMP_XTD;
AttrValueList[6] = 0;
AttrIdList[7] = NC_ATTR_CAN_MASK_XTD;
AttrValueList[7] = 0; // NC_CAN_MASK_XTD_DONTCARE;
// Configure the CAN Network Interface Object
Status = ncConfig(szCanObject, 8, AttrIdList,
AttrValueList);
CheckStatus(Status, "ncConfig");
CCanObject* pCanObject = new CCanObject;
pCanObject->m_phObject = new (NCTYPE_OBJH);
ASSERT (pCanObject->m_phObject != NULL);
Status = ncOpenObject(szCanObject,
pCanObject->m_phObject);
CheckStatus(Status, "ncOpenObject");
if (Status == 0) // object was
// successfully created
{
// add the CAN object to the list,
// indexed by name
m_CanObjectMap.SetAt(strObjectName,
pCanObject);
// create a string to identify the Notification
pCanObject->m_pszObjectName = new char[strObjectName.GetLength() + 1];
strcpy(pCanObject->m_pszObjectName, strObjectName);
// Create the notification used to store incoming frames.
// CanCallback will be called whenever a frame is available,
// a background error occurs, or no frame is received for 30 seconds.
// We pass a pointer to the global Queue data structure to the
// callback's RefData parameter.
Status = ncCreateNotification(
*(pCanObject->m_phObject),
NotificationStates,
NC_DURATION_INFINITE, //CAN_TIMEOUT
pCanObject->m_pszObjectName,
CanCallback); // name of callback fn
// check callback was installed
CheckStatus(Status, "ncCreateNotification");
******
at this point we kick off a timer for 200 msecs, and then carry on when the timer expires.
This allows the card to get itself settled.
******
This consists of checking configuration, and doing the following code for each of the response objects.
The things that change are the object names, the arbitration IDs, and the response data.
AttrIdList[0] = NC_ATTR_COMM_TYPE;
AttrValueList[0] = NC_CAN_COMM_TX_RESP_ONLY;
//failed bff62002 if objects set to 'start on open'
// All of the following are here as a result of testing.
// The setting above is the one that should eventually be used.
// Finally resolved by not using start-on-open above.
// AttrValueList[0] = NC_CAN_COMM_RX_UNSOL; //worked
// AttrValueList[0] = NC_CAN_COMM_RX_PERIODIC; //failed bff62005
// AttrValueList[0] = NC_CAN_COMM_RX_BY_CALL; //worked
/// AttrValueList[0] = NC_CAN_COMM_TX_PERIODIC; //worked - crashed with unhandled exception on closure though
// AttrValueList[0] = NC_CAN_COMM_TX_BY_CALL; //worked
// AttrValueList[0] = NC_CAN_COMM_TX_WAVEFORM; //worked - crashed with unhandled exception on closure though
// Specify watchdog timer period
AttrIdList[1] = NC_ATTR_BKD_PERIOD;
AttrValueList[1] = 1000;
// respond with DLC
AttrIdList[2] = NC_ATTR_BKD_READ_SIZE;
AttrValueList[2] = 0;
AttrIdList[3] = NC_ATTR_BKD_WRITE_SIZE;
AttrValueList[3] = DataLengthCode; // normally 3
AttrIdList[4] = NC_ATTR_CAN_TX_RESPONSE;
AttrValueList[4] = NC_TRUE;
/* This attribute is ignored for CAN Objects which transmit data. */
AttrIdList[5] = NC_ATTR_RX_CHANGES_ONLY;
AttrValueList[5] = NC_TRUE;
// maximum number of frames to hold in read queue
AttrIdList[6] = NC_ATTR_READ_Q_LEN;
AttrValueList[6] = 0;
// The write queue length is set to zero (queuing disabled).
// This means that for each request, the most recent data written
// using ncWrite will be transmitted in a Data Frame.
AttrIdList[7] = NC_ATTR_WRITE_Q_LEN;
AttrValueList[7] = 0;
// build the CAN object name
sprintf(szCanName, "%s::XTD0x%08lx", CanBus, ArbitrationId );
//*******
//*arbitration IDs normally used are
//*0x19008000,
//*0x19008001,
//*0x19008002
//*******
// configure the CAN object
Status = ncConfig(szCanName, ATTR_LIST_LEN, AttrIdList, AttrValueList);
// check for errors
CheckStatus(Status, szTemp);
// Open the transmitting CAN Object. The object starts up, but it
// will wait for the first call to ncWrite before it transmits a Data
// Frame.
CCanObject* pCanObject = new CCanObject;
pCanObject->m_phObject = new (NCTYPE_OBJH);
ASSERT (pCanObject->m_phObject != NULL);
Status = ncOpenObject(szCanName,
pCanObject->m_phObject);
CheckStatus(Status, szTemp);
if (Status == 0) // CAN object created successfully
{
// Store CAN bus information into object
pCanObject->m_strCanBusName = CanBus;
pCanObject->m_strCanName.Format("%s", szCanName);
pCanObject->m_ArbitrationID = ArbitrationId;
// add the CAN object to the list, indexed by name
// put data into output buffer
for (int i = 0; i < DataLengthCode; i++)
Transmit.Data[i] = DefaultData[i];
// setup CAN object output buffer
Status= ncWrite(*(pCanObject->m_phObject),
sizeof(Transmit), &Transmit);
CheckStatus(Status, "ncWrite");
// create a string to identify the Notification
pCanObject->m_pszObjectName = new char
[strObjectName.GetLength() + 1];
strcpy(pCanObject->m_pszObjectName,
strObjectName);
Status = ncCreateNotification(
*(pCanObject->m_phObject),
NC_ST_WRITE_SUCCESS,
NC_DURATION_INFINITE,
pCanObject->m_pszObjectName,
NotificationCallback);
// check callback was installed
CheckStatus(Status, "ncCreateNotification");
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
So, Any ideas what we're doing wrong ??
The cards were new in December 2001.
Software driver version installed is Version 1.5.1
It makes little difference which card we use, as we have many cards at this site in various pieces of test equipment, and I have tried at least 6 !
Things are beginning to get a little depserate here =:-/
Regards,
John Webster.