Send timeout is set to 10 ms. Without timeout PLC can be blocked by CAN driver: if CAN bus is not connected to controller CAN driver never returns and therfore PLC application halts. This is a temporary solution.
/*
This file is part of CanFestival, a library implementing CanOpen Stack.
Copyright (C): Edouard TISSERANT and Francis DUPIN
See COPYING file for copyrights details.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Master.h"
#include "Slave.h"
#include "TestMasterSlave.h"
#include "can_driver.h"
extern s_BOARD MasterBoard;
/*****************************************************************************/
void TestMaster_heartbeatError(CO_Data* d, UNS8 heartbeatID)
{
eprintf("TestMaster_heartbeatError %d\n", heartbeatID);
}
/********************************************************
* ConfigureSlaveNode is responsible to
* - setup master RPDO 1 to receive TPDO 1 from id 2
* - setup master RPDO 2 to receive TPDO 2 from id 2
********************************************************/
void TestMaster_initialisation(CO_Data* d)
{
UNS32 PDO1_COBID = 0x0182;
UNS32 PDO2_COBID = 0x0282;
UNS8 size = sizeof(UNS32);
// UNS32 SINC_cicle=0;
// UNS8 data_type = 0;
eprintf("TestMaster_initialisation\n");
/*****************************************
* Define RPDOs to match slave ID=2 TPDOs*
*****************************************/
writeLocalDict( &TestMaster_Data, /*CO_Data* d*/
0x1400, /*UNS16 index*/
0x01, /*UNS8 subind*/
&PDO1_COBID, /*void * pSourceData,*/
&size, /* UNS8 * pExpectedSize*/
RW); /* UNS8 checkAccess */
writeLocalDict( &TestMaster_Data, /*CO_Data* d*/
0x1401, /*UNS16 index*/
0x01, /*UNS8 subind*/
&PDO2_COBID, /*void * pSourceData,*/
&size, /* UNS8 * pExpectedSize*/
RW); /* UNS8 checkAccess */
}
// Step counts number of times ConfigureSlaveNode is called
static int init_step = 0;
/*Froward declaration*/
static void ConfigureSlaveNode(CO_Data* d, UNS8 nodeId);
/**/
static void CheckSDOAndContinue(CO_Data* d, UNS8 nodeId)
{
UNS32 abortCode;
if(getWriteResultNetworkDict (d, nodeId, &abortCode) != SDO_FINISHED)
eprintf("Master : Failed in initializing slave %2.2x, step %d, AbortCode :%4.4x \n", nodeId, init_step, abortCode);
/* Finalise last SDO transfer with this node */
closeSDOtransfer(&TestMaster_Data, nodeId, SDO_CLIENT);
ConfigureSlaveNode(d, nodeId);
}
/********************************************************
* ConfigureSlaveNode is responsible to
* - setup slave TPDO 1 transmit type
* - setup slave TPDO 2 transmit type
* - switch to operational mode
* - send NMT to slave
********************************************************
* This an example of :
* Network Dictionary Access (SDO) with Callback
* Slave node state change request (NMT)
********************************************************
* This is called first by TestMaster_post_SlaveBootup
* then it called again each time a SDO exchange is
* finished.
********************************************************/
static void ConfigureSlaveNode(CO_Data* d, UNS8 nodeId)
{
/* Master configure heartbeat producer time at 1000 ms
* for slave node-id 0x02 by DCF concise */
UNS8 Transmission_Type = 0x01;
// UNS32 abortCode;
UNS8 res;
eprintf("Master : ConfigureSlaveNode %2.2x\n", nodeId);
switch(++init_step){
case 1: /*First step : setup Slave's TPDO 1 to be transmitted on SYNC*/
eprintf("Master : set slave %2.2x TPDO 1 transmit type\n", nodeId);
res = writeNetworkDictCallBack (d, /*CO_Data* d*/
nodeId, /*UNS8 nodeId*/
0x1800, /*UNS16 index*/
0x02, /*UNS8 subindex*/
1, /*UNS8 count*/
0, /*UNS8 dataType*/
&Transmission_Type,/*void *data*/
CheckSDOAndContinue); /*SDOCallback_t Callback*/
break;
case 2: /*Second step*/
eprintf("Master : set slave %2.2x TPDO 2 transmit type\n", nodeId);
writeNetworkDictCallBack (d, /*CO_Data* d*/
nodeId, /*UNS8 nodeId*/
0x1801, /*UNS16 index*/
0x02, /*UNS16 index*/
1, /*UNS8 count*/
0, /*UNS8 dataType*/
&Transmission_Type,/*void *data*/
CheckSDOAndContinue); /*SDOCallback_t Callback*/
break;
case 3:
/****************************** START *******************************/
/* Put the master in operational mode */
setState(d, Operational);
/* Ask slave node to go in operational mode */
masterSendNMTstateChange (d, nodeId, NMT_Start_Node);
}
}
void TestMaster_preOperational(CO_Data* d)
{
eprintf("TestMaster_preOperational\n");
}
void TestMaster_operational(CO_Data* d)
{
eprintf("TestMaster_operational\n");
}
void TestMaster_stopped(CO_Data* d)
{
eprintf("TestMaster_stopped\n");
}
void TestMaster_post_sync(CO_Data* d)
{
eprintf("TestMaster_post_sync\n");
eprintf("Master: %d %d %d %d %d %d %d %d %d %x %x %d %d\n",
MasterMap1,
MasterMap2,
MasterMap3,
MasterMap4,
MasterMap5,
MasterMap6,
MasterMap7,
MasterMap8,
MasterMap9,
MasterMap10,
MasterMap11,
MasterMap12,
MasterMap13);
}
void TestMaster_post_emcy(CO_Data* d, UNS8 nodeID, UNS16 errCode, UNS8 errReg)
{
eprintf("Master received EMCY message. Node: %2.2x ErrorCode: %4.4x ErrorRegister: %2.2x\n", nodeID, errCode, errReg);
}
char query_result = 0;
char waiting_answer = 0;
static void CheckSDO(CO_Data* d, UNS8 nodeId)
{
UNS32 abortCode;
if(getWriteResultNetworkDict (d, nodeId, &abortCode) != SDO_FINISHED)
eprintf("Master : Failed in changing Slave's transmit type AbortCode :%4.4x \n", abortCode);
/* Finalise last SDO transfer with this node */
closeSDOtransfer(&TestMaster_Data, nodeId, SDO_CLIENT);
}
static int MasterSyncCount = 0;
void TestMaster_post_TPDO(CO_Data* d)
{
eprintf("TestMaster_post_TPDO MasterSyncCount = %d \n", MasterSyncCount);
//
// {
// char zero = 0;
// if(MasterMap4 > 0x80){
// writeNetworkDict (
// &TestMaster_Data,
// TestSlave_Data->bDeviceNodeId,
// 0x2002,
// 0x00,
// 1,
// 0,
// &zero);
// }
// }
#if 0
if(waiting_answer){
UNS32 abortCode;
UNS8 size = 1;
switch(getReadResultNetworkDict (
&TestMaster_Data,
0x02,
&query_result,
&size,
&abortCode))
{
case SDO_FINISHED:
/* Do something with result here !!*/
eprintf("Got SDO answer (0x2002, 0x00), %d %d\n",query_result,size);
case SDO_ABORTED_RCV:
case SDO_ABORTED_INTERNAL:
case SDO_RESET:
waiting_answer = 0;
closeSDOtransfer(
&TestMaster_Data,
0x02,
SDO_CLIENT);
break;
case SDO_DOWNLOAD_IN_PROGRESS:
case SDO_UPLOAD_IN_PROGRESS:
break;
}
}else if(MasterSyncCount % 10 == 0){
readNetworkDict (
&TestMaster_Data,
0x02,
0x2002,
0x00,
0);
waiting_answer = 1;
}
#endif
if(MasterSyncCount % 17 == 0){
eprintf("Master : Ask RTR PDO (0x1402)\n");
sendPDOrequest(&TestMaster_Data, 0x1402 );
sendPDOrequest(&TestMaster_Data, 0x1403 );
}
if(MasterSyncCount % 50 == 0){
eprintf("Master : Change slave's transmit type to 0xFF\n");
UNS8 transmitiontype = 0xFF;
writeNetworkDictCallBack (&TestMaster_Data, /*CO_Data* d*/
2, /*UNS8 nodeId*/
0x1802, /*UNS16 index*/
0x02, /*UNS16 index*/
1, /*UNS8 count*/
0, /*UNS8 dataType*/
&transmitiontype,/*void *data*/
CheckSDO); /*SDOCallback_t Callback*/
}
if(MasterSyncCount % 50 == 25){
eprintf("Master : Change slave's transmit type to 0x00\n");
UNS8 transmitiontype = 0x00;
writeNetworkDictCallBack (&TestMaster_Data, /*CO_Data* d*/
2, /*UNS8 nodeId*/
0x1802, /*UNS16 index*/
0x02, /*UNS16 index*/
1, /*UNS8 count*/
0, /*UNS8 dataType*/
&transmitiontype,/*void *data*/
CheckSDO); /*SDOCallback_t Callback*/
}
MasterSyncCount++;
}
void TestMaster_post_SlaveBootup(CO_Data* d, UNS8 nodeid)
{
eprintf("TestMaster_post_SlaveBootup %x\n", nodeid);
ConfigureSlaveNode(d, nodeid);
}