This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3359ICE SOEM

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;
}