Other Parts Discussed in Thread: SYSBIOS
Hi I have a problem with a code that i'm writting for the TI AM3359ICE and i can't figure why it's not working so I'm asking for your help. I gave the code in attachement. My problem is that i have 3 slaves and when i want to read the inputs of the third (last) slave it's always written 0 but it's ok when I read/write outputs. At first i thought it was a problem with the 'printf' function so i tried something like that :
from this
rt_printf(" %2.2x", *(ec_slave[1].inputs /*+ j*/));
rt_printf(" %2.2x", *(ec_slave[2].inputs /*+ j*/));
rt_printf(" %2.2x", *(ec_slave[3].inputs /*+ j*/));
to
rt_printf(" %2.2x", *(ec_slave[1].inputs /*+ j*/));
rt_printf(" %2.2x", *(ec_slave[3].inputs /*+ j*/));
rt_printf(" %2.2x", *(ec_slave[2].inputs /*+ j*/));
it didn't work after i think it was a problem of the board itself so i inverted the second with the third and vice-versa it didn't work to. So now i don't know what to do can you help me please
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <sched.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <pthread.h>
#include <math.h>
#include <sys/mman.h>
#include <native/task.h>
#include "ethercattype.h"
#include "nicdrv.h"
#include "ethercatbase.h"
#include "ethercatmain.h"
#include "ethercatcoe.h"
#include "ethercatconfig.h"
#include "ethercatdc.h"
#include "ethercatprint.h"
#define TI_AM3359ICE 1
#define EC_TIMEOUTMON 50
int expectedWKC;
boolean inOP,needlf;
boolean blink=0;
ec_ODlistt ODlist;
ec_OElistt OElist;
char IOmap[128];
char hstr[1024];
char* dtype2string(uint16 dtype)
{
switch(dtype)
{
case ECT_BOOLEAN:
rt_printf(hstr, "BOOLEAN");
break;
case ECT_INTEGER8:
rt_printf(hstr, "INTEGER8");
break;
case ECT_INTEGER16:
rt_printf(hstr, "INTEGER16");
break;
case ECT_INTEGER32:
rt_printf(hstr, "INTEGER32");
break;
case ECT_INTEGER24:
rt_printf(hstr, "INTEGER24");
break;
case ECT_INTEGER64:
rt_printf(hstr, "INTEGER64");
break;
case ECT_UNSIGNED8:
rt_printf(hstr, "UNSIGNED8");
break;
case ECT_UNSIGNED16:
rt_printf(hstr, "UNSIGNED16");
break;
case ECT_UNSIGNED32:
rt_printf(hstr, "UNSIGNED32");
break;
case ECT_UNSIGNED24:
rt_printf(hstr, "UNSIGNED24");
break;
case ECT_UNSIGNED64:
rt_printf(hstr, "UNSIGNED64");
break;
case ECT_REAL32:
rt_printf(hstr, "REAL32");
break;
case ECT_REAL64:
rt_printf(hstr, "REAL64");
break;
case ECT_BIT1:
rt_printf(hstr, "BIT1");
break;
case ECT_BIT2:
rt_printf(hstr, "BIT2");
break;
case ECT_BIT3:
rt_printf(hstr, "BIT3");
break;
case ECT_BIT4:
rt_printf(hstr, "BIT4");
break;
case ECT_BIT5:
rt_printf(hstr, "BIT5");
break;
case ECT_BIT6:
rt_printf(hstr, "BIT6");
break;
case ECT_BIT7:
rt_printf(hstr, "BIT7");
break;
case ECT_BIT8:
rt_printf(hstr, "BIT8");
break;
case ECT_VISIBLE_STRING:
rt_printf(hstr, "VISIBLE_STRING");
break;
case ECT_OCTET_STRING:
rt_printf(hstr, "OCTET_STRING");
break;
default:
rt_printf(hstr, "Type 0x%4.4X", dtype);
}
return hstr;
}
int si_PDOassign(uint16 slave, uint16 PDOassign, int mapoffset, int bitoffset)
{
uint16 idxloop, nidx, subidxloop, rdat, idx, subidx;
uint8 subcnt;
int wkc, bsize = 0, rdl;
int32 rdat2;
uint8 bitlen, obj_subidx;
uint16 obj_idx;
int abs_offset, abs_bit;
rdl = sizeof(rdat); rdat = 0;
/* read PDO assign subindex 0 ( = number of PDO's) */
wkc = ec_SDOread(slave, PDOassign, 0x00, FALSE, &rdl, &rdat, EC_TIMEOUTRXM);
rdat = etohs(rdat);
/* positive result from slave ? */
if ((wkc > 0) && (rdat > 0))
{
/* number of available sub indexes */
nidx = rdat;
bsize = 0;
/* read all PDO's */
for (idxloop = 1; idxloop <= nidx; idxloop++)
{
rdl = sizeof(rdat); rdat = 0;
/* read PDO assign */
wkc = ec_SDOread(slave, PDOassign, (uint8)idxloop, FALSE, &rdl, &rdat, EC_TIMEOUTRXM);
/* result is index of PDO */
idx = etohl(rdat);
if (idx > 0)
{
rdl = sizeof(subcnt); subcnt = 0;
/* read number of subindexes of PDO */
wkc = ec_SDOread(slave,idx, 0x00, FALSE, &rdl, &subcnt, EC_TIMEOUTRXM);
subidx = subcnt;
/* for each subindex */
for (subidxloop = 1; subidxloop <= subidx; subidxloop++)
{
rdl = sizeof(rdat2); rdat2 = 0;
/* read SDO that is mapped in PDO */
wkc = ec_SDOread(slave, idx, (uint8)subidxloop, FALSE, &rdl, &rdat2, EC_TIMEOUTRXM);
rdat2 = etohl(rdat2);
/* extract bitlength of SDO */
bitlen = LO_BYTE(rdat2);
bsize += bitlen;
obj_idx = (uint16)(rdat2 >> 16);
obj_subidx = (uint8)((rdat2 >> 8) & 0x000000ff);
abs_offset = mapoffset + (bitoffset / 8);
abs_bit = bitoffset % 8;
ODlist.Slave = slave;
ODlist.Index[0] = obj_idx;
OElist.Entries = 0;
wkc = 0;
/* read object entry from dictionary if not a filler (0x0000:0x00) */
if(obj_idx || obj_subidx)
wkc = ec_readOEsingle(0, obj_subidx, &ODlist, &OElist);
rt_printf(" [0x%4.4X.%1d] 0x%4.4X:0x%2.2X 0x%2.2X", abs_offset, abs_bit, obj_idx, obj_subidx, bitlen);
if((wkc > 0) && OElist.Entries)
{
rt_printf(" %-12s %s\n", dtype2string(OElist.DataType[obj_subidx]), OElist.Name[obj_subidx]);
}
else
rt_printf("\n");
bitoffset += bitlen;
};
};
};
};
/* return total found bitlength (PDO) */
return bsize;
}
int si_map_sdo(int slave)
{
int wkc, rdl;
int retVal = 0;
uint8 nSM, iSM, tSM;
int Tsize, outputs_bo, inputs_bo;
uint8 SMt_bug_add;
rt_printf("PDO mapping according to CoE :\n");
SMt_bug_add = 0;
outputs_bo = 0;
inputs_bo = 0;
rdl = sizeof(nSM); nSM = 0;
/* read SyncManager Communication Type object count */
wkc = ec_SDOread(slave, ECT_SDO_SMCOMMTYPE, 0x00, FALSE, &rdl, &nSM, EC_TIMEOUTRXM);
/* positive result from slave ? */
if ((wkc > 0) && (nSM > 2))
{
/* make nSM equal to number of defined SM */
nSM--;
/* limit to maximum number of SM defined, if true the slave can't be configured */
if (nSM > EC_MAXSM)
nSM = EC_MAXSM;
/* iterate for every SM type defined */
for (iSM = 2 ; iSM <= nSM ; iSM++)
{
rdl = sizeof(tSM); tSM = 0;
/* read SyncManager Communication Type */
wkc = ec_SDOread(slave, ECT_SDO_SMCOMMTYPE, iSM + 1, FALSE, &rdl, &tSM, EC_TIMEOUTRXM);
if (wkc > 0)
{
if((iSM == 2) && (tSM == 2)) // SM2 has type 2 == mailbox out, this is a bug in the slave!
{
SMt_bug_add = 1; // try to correct, this works if the types are 0 1 2 3 and should be 1 2 3 4
rt_printf("Activated SM type workaround, possible incorrect mapping.\n");
}
if(tSM)
tSM += SMt_bug_add; // only add if SMt > 0
if (tSM == 3) // outputs
{
/* read the assign RXPDO */
rt_printf(" SM%1d outputs\n addr b index: sub bitl data_type name\n", iSM);
Tsize = si_PDOassign(slave, ECT_SDO_PDOASSIGN + iSM, (int)(ec_slave[slave].outputs - (uint8 *)&IOmap[0]), outputs_bo );
outputs_bo += Tsize;
}
if (tSM == 4) // inputs
{
/* read the assign TXPDO */
rt_printf(" SM%1d inputs\n addr b index: sub bitl data_type name\n", iSM);
Tsize = si_PDOassign(slave, ECT_SDO_PDOASSIGN + iSM, (int)(ec_slave[slave].inputs - (uint8 *)&IOmap[0]), inputs_bo );
inputs_bo += Tsize;
}
}
}
}
/* found some I/O bits ? */
if ((outputs_bo > 0) || (inputs_bo > 0))
retVal = 1;
return retVal;
}
static void task(void *arg)
{
int led_display = 0;
int oloop, iloop,wkc_count,cnt,IOmap_size ;
int chk = 40;
int i,j,k=0;
int wkc;
//initialize ethernet interface
if (ec_init("eth0"))
//Searching slaves
if ( ec_config_init(FALSE) > 0 )
{
rt_printf("%d Slaves found and configured.\n",ec_slavecount);
//Map all PDOs from slaves to IOmap
IOmap_size=ec_config_map(&IOmap);
//Locate DC slaves, measure propagation delays.
ec_configdc();
ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 4);
//Save the number of Output bytes in oloop
oloop = ec_slave[0].Obytes;
if ((oloop == 0) && (ec_slave[0].Obits > 0)) oloop = 1;
if (oloop > 8) oloop = 8;
//Save the number of Input bytes in iloop
iloop = ec_slave[0].Ibytes;
if ((iloop == 0) && (ec_slave[0].Ibits > 0)) iloop = 1;
if (iloop > 8) iloop = 8;
//Check what protocol is running on the slave
for(cnt=1;cnt<=ec_slavecount;cnt++)
{
if (ec_slave[cnt].mbx_proto & 0x04)
si_map_sdo(cnt);
}
//expected wkc
expectedWKC = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC; //how to configure range addrass of eatch board
//Request operational state for slaves
ec_slave[0].state = EC_STATE_OPERATIONAL;
ec_send_processdata();
ec_receive_processdata(EC_TIMEOUTRET);
ec_writestate(0);
chk = 40;
/* wait for all slaves to reach OPERATIONAL state */
do
{
ec_send_processdata();
ec_receive_processdata(EC_TIMEOUTRET);
ec_statecheck(0, EC_STATE_OPERATIONAL, 50000);
}while (chk-- && (ec_slave[0].state != EC_STATE_OPERATIONAL));
//If slaves reached operational state
if (ec_slave[0].state == EC_STATE_OPERATIONAL )
{
rt_printf("Operational state reached for all slaves.\n");
wkc_count = 0;
inOP = TRUE;
/* cyclic loop */
/*The I/O size are both 32 bit = array of 4 bytes but just the byte array is used by the board */
for(i = 1; i <= 10000; i++) //
{
ec_send_processdata(); //sent all only one package
if (led_display == 256)
led_display=0;
wkc = ec_receive_processdata(EC_TIMEOUTRET); //how u know this command read only three board? how u set?
if(1/*wkc >= expectedWKC*/)
{
rt_printf("Processdata cycle %4d, WKC %d , O:", i, wkc);
//Write the value of I/O
//for(k=1;k<4;k++)
/*for(j = 0 ; j < oloop; j++)
{*/
rt_printf(" %2.2x", *(ec_slave[1].outputs /*+ j*/)); //if i have board
rt_printf(" %2.2x", *(ec_slave[2].outputs /*+ j*/));
rt_printf(" %2.2x", *(ec_slave[3].outputs /*+ j*/));
//Why + j ?
*(ec_slave[1].outputs ) =led_display*1;
*(ec_slave[2].outputs ) =led_display*2;
*(ec_slave[3].outputs ) =led_display*4;
led_display++;
/*}*/
//Print the value of inputs
rt_printf(" I:");
/*for(j = 0 ; j < iloop; j++)
{*/
rt_printf(" %2.2x", *(ec_slave[1].inputs /*+ j*/));
rt_printf(" %2.2x", *(ec_slave[3].inputs /*+ j*/));
rt_printf(" %2.2x", *(ec_slave[2].inputs /*+ j*/));
/*}*/
rt_printf(" T:%lld\r",ec_DCtime);
needlf = TRUE;
}
usleep(10);
}
inOP = FALSE;
}
//else if slaves havn't reached operational states
else
{
rt_printf("Not all slaves reached operational state.\n");
ec_readstate();
for(i = 1; i<=ec_slavecount ; i++)
{
if(ec_slave[i].state != EC_STATE_OPERATIONAL)
{
rt_printf("Slave %d State=0x%2.2x StatusCode=0x%4.4x : %s\n",i, ec_slave[i].state, ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
}
}
}
rt_printf("\nRequest init state for all slaves\n");
ec_slave[0].state = EC_STATE_INIT;
/* request INIT state for all slaves */
ec_writestate(0);
}
else
{
rt_printf("No slaves found!\n");
}
return 0;
}
int main (void)
{
RT_TASK task_desc;
rt_print_auto_init(1);
/* disable memory swap */
mlockall( MCL_CURRENT | MCL_FUTURE );
if (rt_task_spawn( &task_desc, /* task descriptor */
"my task", /* name */
0 /* 0 = default stack size */,
99 /* priority */,
T_JOINABLE, /* needed to call rt_task_join after */
&task, /* entry point (function pointer) */
NULL /* function argument */ )!=0)
{
rt_printf("rt_task_spawn error\n");
return 1;
}
/* wait for task function termination */
rt_task_join(&task_desc);
return 0;
}