|
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 (...) (24 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
|
|
|
|