To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.robotics.rcx.legosOpen lugnet.robotics.rcx.legos in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / RCX / legOS / 1318
1317  |  1319
Subject: 
Re: solaris + legOS
Newsgroups: 
lugnet.robotics.rcx.legos
Date: 
Fri, 28 Jul 2000 14:25:56 GMT
Viewed: 
4742 times
  
YEAH! It works! And there was great rejoicing! :-)

This version sucsefully d/led the helloworld.lx, and it ran perfectly.
Thank you much!

I'm curious, what all did you change? I saw you did a cool thing to make
the getopt_long work...  (btw, it gave a small warning saying that option_index
was unused in the main function.)
That should be applied to convert.c also, although you may have to do
something with optind to make it work.

Thanks again!

Ryan

> > ... well.. i know that... i tried using that one before.  Like you said, it
> > doesn't work.
> 
> Could you please try the appended version of loader.c?
> 
> Eddie C. Dost
> ecd@skynet.be
> --
> 
> /*! \file   loader.c
>     \brief  legOS task downloading
>     \author Markus L. Noga <markus@noga.de>
> */
> 
> /*
>  *  The contents of this file are subject to the Mozilla Public License
>  *  Version 1.0 (the "License"); you may not use this file except in
>  *  compliance with the License. You may obtain a copy of the License at
>  *  http://www.mozilla.org/MPL/
>  *
>  *  Software distributed under the License is distributed on an "AS IS"
>  *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
>  *  License for the specific language governing rights and limitations
>  *  under the License.
>  *
>  *  The Original Code is legOS code, released October 2, 1999.
>  *
>  *  The Initial Developer of the Original Code is Markus L. Noga.
>  *  Portions created by Markus L. Noga are Copyright (C) 1999
>  *  Markus L. Noga. All Rights Reserved.
>  *
>  *  Contributor(s): everyone discussing LNP at LUGNET
>  */
> 
> /*  2000.05.01
>  *
>  *  Modifications to the original loader.c file for LegOS 0.2.2 include:
>  *
>  *  Paolo Masetti's patches to eliminate "Invalid Argument" error and
>  *  to get rid of several compiler warnings:
>  *     <paolo.masetti@itlug.org>
>  *     http://www.lugnet.com/robotics/rcx/legos/?n=619
>  *
>  *  Markus L. Noga's solution to Cygwin's failure to define the O_ASYNC symbol:
>  *     <markus@noga.de>
>  *     http://www.lugnet.com/robotics/rcx/legos/?n=439
>  *
>  *  Paolo Masetti's adaptation for definitive porting to Win32. No more errors in
>  *  serial communication and conditional compile for Winnt (cygnwin).
>  *  Several addition to dll option to better support user. Execute dll without
>  *  arguments to get help.
>  *     <paolo.masetti@itlug.org>
>  */
> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>
> #include <fcntl.h>
> #include <sys/time.h>
> #include <sys/types.h>
> #include <signal.h>
> #include <errno.h>
> 
> #if defined(_WIN32)
>   #include <windows.h>
> #endif
> 
> #include <sys/lnp.h>
> #include <sys/lnp-logical.h>
> 
> #include "rcxtty.h"
> #include "keepalive.h"
> #include <lx.h>
> 
> #define MAX_DATA_CHUNK 0xf8     //!< maximum data bytes/packet for boot protocol
> #define XMIT_RETRIES   5        //!< number of packet transmit retries
> #define REPLY_TIMEOUT  750000   //!< timeout for reply
> #define BYTE_TIME      (1000*LNP_BYTE_TIME) //!< time to transmit a byte.
> 
> #define DEFAULT_DEST  0
> #define DEFAULT_PROGRAM 0
> #define DEFAULT_SRCPORT 0
> #define DEFAULT_PRIORITY 10
> 
> typedef enum {
>   CMDacknowledge,     //!< 1:
>   CMDdelete,       //!< 1+ 1: b[nr]
>   CMDcreate,       //!< 1+12: b[nr] s[textsize] s[datasize] s[bsssize] s[stacksize] s[start] b[prio]
>   CMDoffsets,       //!< 1+ 7: b[nr] s[text] s[data] s[bss]
>   CMDdata,         //!< 1+>3: b[nr] s[offset] array[data]
>   CMDrun,           //!< 1+ 1: b[nr]
>   CMDirmode, //!< 1+ 1: b[0=near/1=far]
>   CMDlast           //!< ?
> } packet_cmd_t;
> 
> #if defined(__sun__) && defined(__svr4__)
> #define _SOLARIS 1
> #endif
> 
> #if !defined(_SOLARIS)
> #include <getopt.h>
> 
> static const struct option long_options[]={
>   {"rcxaddr",required_argument,0,'r'},
>   {"program",required_argument,0,'p'},
>   {"srcport",required_argument,0,'s'},
>   {"tty",    required_argument,0,'t'},
>   {"irmode", required_argument,0,'i'},
>   {"execute",no_argument      ,0,'e'},
>   {"verbose",no_argument      ,0,'v'},
>   {0        ,0                ,0,0  }
> };
> 
> #else // _SOLARIS
> 
> #define getopt_long(ac, av, opt, lopt, lidx) (getopt((ac), (av), (opt)))
> 
> #endif // _SOLARIS
> 
> volatile int receivedAck=0;
> 
> volatile unsigned short relocate_to=0;
> 
> unsigned int  rcxaddr = DEFAULT_DEST,
>               prog    = DEFAULT_PROGRAM,
>               srcport = DEFAULT_SRCPORT,
>    irmode  = -1;
> 
> int run_flag=0;
> int verbose_flag=0;
> 
> void io_handler(void);
> 
> /*! blocking I/R write.
>  *! return number of bytes written, or negative for error.
>  */
> int lnp_logical_write(const void *data, size_t length) {
> 
> // With Win32 we are using Blocking Write by default
> #if !defined(_WIN32)
>   fd_set fds;
> 
>   // wait for transmission
>   //
>   do {
>     FD_ZERO(&fds);
>     FD_SET(rcxFD(),&fds);
>   } while(select(rcxFD()+1,NULL,&fds,NULL,NULL)<1);
> #endif
> 
>   // transmit
>   //
>   keepaliveRenew();
> 
>   return mywrite(rcxFD(), data, length)!=length;
> }
> 
> //! send a LNP layer 0 packet of given length
> /*! \return 0 on success.
> */
> int lnp_assured_write(const unsigned char *data, unsigned char length,
>                       unsigned char dest, unsigned char srcport) {
>   int i;
>   struct timeval timeout,now;
>   unsigned long total,elapsed;
> 
>   for(i=0; i<XMIT_RETRIES; i++) {
>     receivedAck=0;
> 
>     lnp_addressing_write(data,length,dest,srcport);
> 
>     gettimeofday(&timeout,0);
>     total=REPLY_TIMEOUT+length*BYTE_TIME;
>     elapsed=0;
> 
>     do {
> #if defined(_WIN32)
>       io_handler();
> #else
>       struct timeval tv;
>       fd_set fds;
> 
>       FD_ZERO(&fds);
>       FD_SET(rcxFD(), &fds);
> 
>       tv.tv_sec = (total - elapsed) / 1000000;
>       tv.tv_usec = (total - elapsed) % 1000000;
>       select(rcxFD() + 1, &fds, NULL, NULL, &tv);
>       if (FD_ISSET(rcxFD(), &fds))
>  io_handler();
> #endif
> 
>       gettimeofday(&now,0);
>       elapsed=1000000*(now.tv_sec  - timeout.tv_sec ) +
>                now.tv_usec - timeout.tv_usec;
> 
>     } while((!receivedAck) && (elapsed < total));
> 
>     if(i || !receivedAck)
>       if(verbose_flag)
>         fprintf(stderr,"try %d: ack:%d\n",i,receivedAck);
> 
>     if(receivedAck)
>       return 0;
>    }
> 
>   return -1;
> }
> 
> void io_handler(void) {
> 
>     static struct timeval last={0,0};
>     struct timeval now;
>     unsigned long diff;
> 
>     unsigned char buffer[256];
> #if defined(_WIN32)
>     DWORD len;
>     int i;
> #else
>     int len,i;
> #endif
> 
>     gettimeofday(&now,0);
>     diff= 1000000*now .tv_sec + now .tv_usec -
>  (1000000*last.tv_sec + last.tv_usec);
> 
>     if(diff> 10000*LNP_BYTE_TIMEOUT) {
>       if(verbose_flag)
>         fprintf(stderr,"\n#time %lu ",diff);
>       lnp_integrity_reset();
>     }
> #if defined(_WIN32)
>     ReadFile(rcxFD(), buffer, sizeof(buffer), &len, NULL);
> #else
>     len=read(rcxFD(),buffer,sizeof(buffer));
> #endif
>     for(i=0; i<len; i++) {
>       if(verbose_flag)
>         fprintf(stderr,"%02x ",buffer[i]);
>       lnp_integrity_byte(buffer[i]);
>     }
>     gettimeofday(&last,0);
> }
> 
> void LNPinit(const char *tty) {
>   struct timeval timeout,now;
>   long diff;
> 
> #if !defined(_WIN32)
>   unsigned char buffer[256];
> #endif
> 
>   // initialize RCX communications
>   //
>   if (verbose_flag) fputs("opening tty...\n", stderr);
> #ifdef LNP_FAST
>   rcxInit(tty, 1);
> #else
>   rcxInit(tty, 0);
> #endif
> 
>   if (rcxFD() == BADFILE) {
>     myperror("opening tty");
>     exit(1);
>   }
>   keepaliveInit();
> 
>   // wait for IR to settle
>   //
>   gettimeofday(&timeout,0);
>   do {
>     usleep(100000);
>     gettimeofday(&now,0);
>     diff=1000000*(now.tv_sec  - timeout.tv_sec ) +
>            now.tv_usec - timeout.tv_usec;
> 
>   } while(diff < 100000);
> #if defined(_WIN32)
>   PurgeComm(rcxFD(), PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
> #else
>   read(rcxFD(),buffer,256);
> #endif
> }
> 
> void ahandler(const unsigned char *data,unsigned char len,unsigned char src) {
>   if(*data==CMDacknowledge) {
>     receivedAck=1;
>     if(len==8) {
>       // offset packet
>       //
>       relocate_to=(data[2]<<8)|data[3];
>     }
>   }
> }
> 
> void lnp_download(const lx_t *lx) {
>   unsigned char buffer[256+3];
> 
>   size_t i,chunkSize,totalSize=lx->text_size+lx->data_size;
> 
>   if(verbose_flag)
>     fputs("\ndata ",stderr);
> 
>   buffer[0]=CMDdata;
>   buffer[1]=prog;
> 
>   for(i=0; i<totalSize; i+=chunkSize) {
>     chunkSize=totalSize-i;
>     if(chunkSize>MAX_DATA_CHUNK)
>       chunkSize=MAX_DATA_CHUNK;
> 
>     buffer[2]= i >> 8;
>     buffer[3]= i &  0xff;
>     memcpy(buffer+4,lx->text + i,chunkSize);
>     if(lnp_assured_write(buffer,chunkSize+4,rcxaddr,srcport)) {
>       fputs("error downloading program\n",stderr);
>       exit(-1);
>     }
>   }
> }
> 
> int main(int argc, char **argv) {
>   lx_t lx;        // the legOS executable
>   char *filename;
>   int opt,option_index;
> 
>   unsigned char buffer[256+3]="";
>   char *tty=NULL;
> 
>   while((opt=getopt_long(argc, argv, "r:p:s:t:i:ev",
>                         (struct option *)long_options, &option_index) )!=-1) {
>     switch(opt) {
>       case 'e':
>    run_flag=1;
>         break;
>       case 'r':
>    sscanf(optarg,"%x",&rcxaddr);
>         break;
>       case 'p':
>    sscanf(optarg,"%x",&prog);
>         break;
>       case 's':
>    sscanf(optarg,"%x",&srcport);
>         break;
>       case 't':
>    sscanf(optarg,"%s",buffer);
>         break;
>       case 'i':
>    sscanf(optarg,"%x",&irmode);
>         break;
>       case 'v':
>    verbose_flag=1;
>    break;
>     }
>   }
> 
>   // load executable
>   //
>   if(argc-optind<1) {
>     char *usage_string =
>  "  -p<prognum>  , --program=<prognum>   set destination program to <prognum>\n"
>  "  -r<rcxadress>, --rcxaddr=<rcxadress> set RCX address to <rcxaddress>\n"
>  "  -s<srcadress>, --srcport=<srcadress> set RCX sourceport to <srcaddress>\n"
>  "  -t<comport>  , --tty=<comport>       set IR Tower com port <comport>\n"
>  "  -i<0/1>      , --irmode=<0/1>        set IR mode near(0)/far(1) on RCX\n"
>  "  -e           , --execute             execute program after download\n"
>  "  -v           , --verbose             verbose mode\n"
>  "\n"
>  "Default com port can be set using environment variable RCXTTY.\n"
>  "Eg:\tset RCXTTY=COM2\n"
>  "\n"
>  ;
> 
>  fprintf(stderr, "usage: %s [options] file.lx\n", argv[0]);
>  fprintf(stderr, usage_string);
> 
>     return -1;
>   }
>   filename=argv[optind++];
>   if(lx_read(&lx,filename)) {
>     fprintf(stderr,"unable to load legOS executable from %s.\n",filename);
>     return -1;
>   }
> 
>   // Moved tty device setting for a new option on command line
>   if (buffer[0]) tty=buffer;
>   if (!tty) tty = getenv(TTY_VARIABLE);
>   if (!tty) tty = DEFAULTTTY;
> 
>   LNPinit(tty);
> 
>   if (verbose_flag)
>     fputs("\nLNP Initialized...\n",stderr);
> 
>   lnp_addressing_set_handler(0,ahandler);
> 
>   if(verbose_flag)
>     fprintf(stderr,"loader hostaddr=%02x hostmask=%02x portmask=%02x\n",
>             LNP_HOSTADDR & 0x00ff,LNP_HOSTMASK & 0x00ff, LNP_PORTMASK & 0x00ff);
> 
>   // Set IR mode
>   if (irmode != -1) {
>     buffer[0]=CMDirmode;
>     buffer[1]=irmode;
>     if(lnp_assured_write(buffer,2,rcxaddr,srcport)) {
>       fputs("error setting IR mode to far\n",stderr);
>       return -1;
>     }
>   }
> 
>   if(verbose_flag)
>     fputs("\ndelete",stderr);
>   buffer[0]=CMDdelete;
>   buffer[1]=prog; //       prog 0
>   if(lnp_assured_write(buffer,2,rcxaddr,srcport)) {
>     fputs("error deleting program\n",stderr);
>     return -1;
>   }
> 
>   if(verbose_flag)
>     fputs("\ncreate ",stderr);
>   buffer[ 0]=CMDcreate;
>   buffer[ 1]=prog; //       prog 0
>   buffer[ 2]=lx.text_size>>8;
>   buffer[ 3]=lx.text_size & 0xff;
>   buffer[ 4]=lx.data_size>>8;
>   buffer[ 5]=lx.data_size & 0xff;
>   buffer[ 6]=lx.bss_size>>8;
>   buffer[ 7]=lx.bss_size & 0xff;
>   buffer[ 8]=lx.stack_size>>8;
>   buffer[ 9]=lx.stack_size & 0xff;
>   buffer[10]=lx.offset >> 8;  // start offset from text segment
>   buffer[11]=lx.offset & 0xff;
>   buffer[12]=DEFAULT_PRIORITY;
>   if(lnp_assured_write(buffer,13,rcxaddr,srcport)) {
>     fputs("error creating program\n",stderr);
>     return -1;
>   }
> 
>   // relocation target address in relocate_to
>   //
>   lx_relocate(&lx,relocate_to);
> 
>   lnp_download(&lx);
> 
>   if (run_flag) {
>     if(verbose_flag)
>       fputs("\nrun ",stderr);
>     buffer[0]=CMDrun;
>     buffer[1]=prog; //       prog 0
>     if(lnp_assured_write(buffer,2,rcxaddr,srcport)) {
>       fputs("error running program\n",stderr);
>       return -1;
>     }
>   }
> 
>   return 0;
> }


--
Ryan VanderBijl                        http://www.calvin.edu/~rvbijl39

(Frodo:) "I don't want to answer a string of questions while I am
eating. I want to think!" "Good heavens!" said Pippin. "At breakfast?"



Message has 1 Reply:
  Re: solaris + legOS
 
Hi, Can you send me the full loader.c and any other changes that was done to get it to compile under Solaris?  I am in the process of re-writing most of dll to be easier to read (getting rid of a lot of the ifdefs, renaming functions, etc), but (...) (26 years ago, 28-Jul-00, to lugnet.robotics.rcx.legos)

3 Messages in This Thread:

Entire Thread on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact
    

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR