Hi all,

we are trying to develop an application using xddp protocol. We use as base, 
the xddp-label exaample that compiles and run perfectly in our system 
(Xenomai-2.6.3 with Linux 3.8.13).

Our app is different from the xddp example because we have encapsulated the 
realtime thread in a task, that it's in a library. We can run the task,called 
from another part, and it rus.

Our task create two sockets, one to receive from the NRT and another to send. 
Yes, I know that we could do it in just one socket, but by design we must do 
it in the way.

Our main problem is when the RT task try to open the socket, the ipc
device isn't created. The error that appears is:"socket: Address family not
supported by protocol". I attach the real-time task code below.

The xddp works, because the examples works. We have several /dev/rtpX and when 
we run the example the /proc/xenomai/registry/rtipc/xddp/xddp-label is 
created. 

Someone could give us some idea about what are we doing wrong?

Thanks in advance.


Leopold

-----------------------------------------------------------

 RT_TASK task;

void ec_create_rt_thread(int cycleTime)
{
    rt_task_create (&task, "Send PDO", 8192, 99, 0);
    rt_task_set_periodic (&task, TM_NOW, cycleTime);
    rt_task_start (&task, &ec_rt_thread, NULL);
}
void ec_delete_rt_thread()
{
     rt_task_delete(&task);
}

void ec_rt_thread(void *unused)
{
   struct rtipc_port_label plabel_in, plabel_out;
   struct sockaddr_ipc saddr_in, saddr_out;

   struct timespec ts;
   struct timeval tv;
   socklen_t addrlen;

   int ret_in, ret_out, s_input, s_output, nRet;
   int inputSize = 0, outputSize = 0;

   int i;
   for( i = 1; i <= ec_slavecount; i++)
   {
      inputSize = inputSize + ec_slave[i].Ibytes;
      outputSize = outputSize + ec_slave[i].Obytes;
   }

   char * rtinputbuf = (char*) calloc(inputSize,sizeof(char));
   char * rtoutputbuf = (char*) calloc(outputSize,sizeof(char));

   /*need to put a lot of stuff to create
    * two sockets: one to receive data from nonrt part
    * and another to send data to the nonrt part
    * use same option as the xenomai xddp-label example
    *
    * the output part came from the NRT part to the RT world
    * the input part came from the RT part to the NRT world
    *
    *
    * Get a datagram socket to bind to the RT endpoint. Each
    * endpoint is represented by a port number within the XDDP
    * protocol namespace.
    **/
    s_output = socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_XDDP);
    s_input = socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_XDDP);


    if (s_output < 0) {
      perror("socket");
      printf("socket");
    }
    if (s_input < 0) {
      perror("socket");
      printf("socket");
    }

    /*
     * Set a port label. This name will be registered when
     * binding, in addition to the port number (if given).
     */
    strcpy(plabel_out.label, XDDP_PORT_OUTPUT);
    ret_out = setsockopt(s_output, SOL_XDDP, XDDP_LABEL, &plabel_out,
sizeof(plabel_out));
    if (ret_out)
    {
      perror("setsockopt");
      printf("setsockopt");
    }


    /*
     * Set the socket timeout; it will apply when attempting to
     * connect to a labeled port, and to recvfrom() calls. The
     * following setup tells the XDDP driver to wait for at most
     * one second until a socket is bound to a port using the same
     * label, or return with a timeout error.
     */
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    ret_in = setsockopt(s_input, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    if (ret_in)
    {
      perror("setsockopt");
      printf("setsockopt");
    }
    /*
     * Set a port label. This name will be used to find the peer
     * when connecting, instead of the port number.
     */
    strcpy(plabel_in.label, XDDP_PORT_INPUT);
    ret_in = setsockopt(s_input, SOL_XDDP, XDDP_LABEL,&plabel_in,
sizeof(plabel_in));
    if (ret_in)
    {
      perror("setsockopt");
      printf("setsockopt");
    }
    /*
     * Bind the socket to the port, to setup a proxy to channel
     * traffic to/from the Linux domain. Assign that port a label,
     * so that peers may use a descriptive information to locate
     * it. For instance, the pseudo-device matching our RT
     * endpoint will appear as
     * /proc/xenomai/registry/rtipc/xddp/<XDDP_PORT_LABEL> in the
     * Linux domain, once the socket is bound.
     *
     * saddr.sipc_port specifies the port number to use. If -1 is
     * passed, the XDDP driver will auto-select an idle port.
     */

    /*
     * Output!!!!!
     * from NRT to RT
     */
    memset(&saddr_out, 0, sizeof(saddr_out));
    saddr_out.sipc_family = AF_RTIPC;
    saddr_out.sipc_port = -1;
    ret_out = bind(s_output, (struct sockaddr *)&saddr_out,
sizeof(saddr_out));
    if (ret_out)
    {
      perror("bind");
      printf("bind");
    }

    /*
     * Input!!!!!
     * from RT to NRT
     */

    memset(&saddr_in, 0, sizeof(saddr_in));
    saddr_in.sipc_family = AF_RTIPC;
    saddr_in.sipc_port = -1; /* Tell XDDP to search by label. */
    ret_in = connect(s_input, (struct sockaddr *)&saddr_in,
sizeof(saddr_in));
    if (ret_in)
    {
      perror("connect");
      printf("connect");
    }
    /*
     * We succeeded in making the port our default destination
     * address by using its label, but we don't know its actual
     * port number yet. Use getpeername() to retrieve it.
     */
    addrlen = sizeof(saddr_in);
    ret_in = getpeername(s_input, (struct sockaddr *)&saddr_in, &addrlen);
    if (ret_in || addrlen != sizeof(saddr_in))
    {
      perror("getpeername");
      printf("getpeername");
    }
    //rt_printf("%s: NRT peer is reading from /dev/rtp%d\n",
 __FUNCTION__, saddr_in.sipc_port);


       for (;;) {
          /* Get packets relayed by the regular thread */
          ret_out = recvfrom(s_output, rtoutputbuf, outputSize, 0, NULL, 0);
          if (ret_out <= 0)
          {
            perror("recvfrom");
            printf("recievefrom");
             //nothing to do, no new data transferred
             //rt_printf("%s: \"%.*s\" relayed by peer\n", __function__,
ret, buf);
          }

          else{
             //received some data from the buffer
             //traffic that data from
             //rtoutputbuf to ec_slave[i].output
             //copiar del outputbuf als ec_slave, tenint en compte el
OBytes de cada slave
             int offSet = 0;
     int i;
             for ( i = 1; i<=ec_slavecount; i++)
{
    memcpy (ec_slave[i].outputs, rtoutputbuf + offSet, ec_slave[i].Obytes);
    offSet = offSet + ec_slave[i].Obytes;
}

          }
          nRet=ec_send_processdata();
          //make some check of sending data
          nRet=ec_receive_processdata(EC_TIMEOUTRET);

          //now, we need to transmit the data outside
          //from ec_slave[i].inputs
          //build rtinputbuf
    int offSet = 0;
    int i;
    for (i = 1; i<=ec_slavecount; i++)
    {
memcpy (rtinputbuf + offSet ,ec_slave[i].inputs, ec_slave[i].Ibytes);
offSet = offSet + ec_slave[i].Ibytes;
    }

          ret_in = sendto(s_input, rtinputbuf, inputSize, 0, NULL, 0);
          if(ret_in != inputSize)
          {
            perror("sendto");
            printf("sendto");
          }

          rt_task_wait_period(NULL);
       }

}


-- 
--
Linux User 152692
Catalonia
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: 
<http://www.xenomai.org/pipermail/xenomai/attachments/20140206/a78dfa42/attachment.sig>
_______________________________________________
Xenomai mailing list
Xenomai@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai

Reply via email to