Shop OBEX P1 Docs P2 Docs Learn Events
New user having problems - Page 4 — Parallax Forums

New user having problems

124»

Comments

  • jazzedjazzed Posts: 11,803
    edited 2012-02-10 10:43
    Rsadeika wrote: »
    The program below compiles, and loads correctly. What I expect to see is "Hello, World!" being displayed on the screen, there is nothing.

    Works for me. Did you change your msleep() to look like this?
    /*
     * pthread safe wait for number of ms
     */
    void msleep(int ms)
    {
        usleep(ms*1000);
    }
    
  • ersmithersmith Posts: 6,099
    edited 2012-02-10 10:59
    Remember that in XMM and XMMC modes pthreads are cooperative and all run on the same cog. So you have to give up the processor to other threads in your while loop. sleep() and usleep() will do that; your msleep() from misc.h will not.

    Eric
  • RsadeikaRsadeika Posts: 3,837
    edited 2012-02-10 11:01
    I edited the previous post, just make sure it absolutely clear that the while() is empty. Yes, the msleep() function is exactly how you have it. In fact if you put an 'msleep(500);' in the while loop, the program works as expected.

    Ray
  • jazzedjazzed Posts: 11,803
    edited 2012-02-10 11:09
    Rsadeika wrote: »
    I edited the previous post, just make sure it absolutely clear that the while() is empty. Yes, the msleep() function is exactly how you have it. In fact if you put an 'msleep(500);' in the while loop, the program works as expected.

    Ray

    Hmm. Well I don't know what to say now.
    I see "Hello World" on my terminal when I comment the while() as you mentioned.

    Here's what I did connected to my C3:
    C:\Users\Steve\Documents\side\rsadieka>propeller-elf-gcc -Os -o raypthread raypthread.c -lpthread
    
    
    C:\Users\Steve\Documents\side\rsadieka>propeller-load -r -t raypthread
    Propeller Version 1 on COM8
    Writing 13480 bytes to Propeller RAM.
    Verifying ... Download OK!
    [ Entering terminal mode. Type ESC or Control-C to exit. ]
    Hello, World!
    Hello, World!
    Hello, World!
    
    
    C:\Users\Steve\Documents\side\rsadieka>cat raypthread.c
    /*
     * Ray threads1.c
     */
    #include <stdio.h>
    #include <propeller.h>
    #include <unistd.h>
    #include <pthread.h>
    
    
    /*
     * Set a pin high without affecting other pins.
     * param WCpin = pin number to set high.
     */
    void high(int WCpin)
    {
        unsigned int bits = 1 << WCpin;
        DIRA |= bits;
        OUTA |= bits;
    }
    
    
    /*
     * Set a pin low without affecting other pins.
     * param WCpin = pin number to set low.
     */
    void low(int WCpin)
    {
        unsigned int mask = 1 << WCpin;
        DIRA |= mask;
        OUTA &= ~mask;
    }
    
    
    /*
     * pthread safe wait for number of ms
     */
    void msleep(int ms)
    {
        usleep(ms*1000);
    }
    
    
    void *do_toggle(void *argv)
    {
        pthread_set_affinity_thiscog_np();
    
    
        while(1)
        {
    /*
            high(15);
            msleep(100);
            low(15);
            msleep(100);
    */
        }
    }
    
    
    int main (int argc,  char* argv[])
    {
        pthread_t thr;
        pthread_create(&thr, NULL, do_toggle, NULL);
        while(1)
        {
            printf("Hello, World!\n");
            sleep(2);
        }
        return 0;
    }
    C:\Users\Steve\Documents\side\rsadieka>
    
    
    
  • RsadeikaRsadeika Posts: 3,837
    edited 2012-02-10 11:40
    Well, I give up on this one, as long as I keep something in the while(), it works for me.

    I just did a program that uses two pthreads in a program, working with two LEDs, that worked as expected. I guess as long as I keep the pthreads to 8 or less, than I should not run into any problems.

    I think what I will do now is use separate cogs to do the on/off of LEDs. The example that I am looking at uses LMM, is there an example for doing it in XMM, and XMMC, or is that not possible?

    Ray
  • jazzedjazzed Posts: 11,803
    edited 2012-02-10 11:46
    Oops. I missed the xmm part of your commands. That also fails for me.

    The problem I think is that since this is cooperative multitasking and pthreads only run in one COG for XMM and XMMC, the main hello thread never gets the chance to run after starting the new thread.

    This is called CPU hogging. You must "yield" control of the processor via a call to sleep(), usleep() via msleep(), or some other yield call to give all threads a chance to run. In LMM it doesn't matter because threads can run on more than one COG.

    Sorry I missed the XMM factor.
    --Steve
  • RsadeikaRsadeika Posts: 3,837
    edited 2012-02-10 13:38
    Below, I am trying to get an LED to on/off in its own cog, and in the main cog do the standard "Hello, World!". The program below compiles and loads, I get the main() to work as expected, but the do_toggle only does one on/off.

    I guess what I need are the proper propeller-elf-gcc and propeller-load commands, and any other pertinent information.

    Ray

    /*
    * mcogs1.c
    */
    
    #include <stdio.h>
    #include <sys/thread.h>
    #include <propeller.h>
    #include "misc.h"
    
    #define STACK_SIZE 16
    
    static int cog1_stack[STACK_SIZE];
    static _thread_state_t thread_data;
    
    volatile unsigned int wait_time;
    volatile unsigned int pins;
    
    void do_toggle(void *arg __attribute__((unused)))
    {
    	unsigned int nextcnt;
    	
    	nextcnt = _CNT + wait_time;
    	
    	while(1)
    	{
    		high(21);
    		msleep(1000);
    		low(21);
    		msleep(1000);
    		
    		nextcnt = __builtin_propeller_waitcnt(nextcnt, wait_time);
        }
    }
    
    #define MIN_GAP 400000
    
    void main (int argc, char* argv[])
    {
    	int n;
    	
    	n = _start_cog_thread(cog1_stack + STACK_SIZE, do_toggle, NULL, &thread_data);
    	while(1)
    	{
    		printf("Hello, World!\n");
    		waitMS(2000);
    		
    		wait_time = wait_time >> 1;
    		if (wait_time < MIN_GAP)
    		wait_time = _clkfreq;
        }
    }
    
  • jazzedjazzed Posts: 11,803
    edited 2012-02-11 10:18
    Hi Ray,

    The problem with your program is in knowing how short a time you can wait without causing the waitcnt to miss the target which can cause a "CNT miss" and 1 minute+ delay for blinking the LED. The original MIN_GAP will cause a "CNT miss" when using the msleep(1000); function calls in the thread loop - this can happen in Spin also.

    Here's a working version:
    c:\Users\Steve\Documents\side\rsadieka>propeller-elf-gcc -Os mcogs1.c
    
    
    c:\Users\Steve\Documents\side\rsadieka>propeller-load -p28 -r -t a.out
    Propeller Version 1 on COM28
    Writing 17632 bytes to Propeller RAM.
    Verifying ... Download OK!
    [ Entering terminal mode. Type ESC or Control-C to exit. ]
    Toggle Started on COG 1
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    
    
    c:\Users\Steve\Documents\side\rsadieka>cat mcogs1.c
    /*
     * mcogs1.c
     */
    #include <stdio.h>
    #include <sys/thread.h>
    #include <propeller.h>
    
    #define STACK_SIZE 16
    
    static int cog1_stack[STACK_SIZE];
    static _thread_state_t thread_data;
    
    volatile unsigned int wait_time;
    volatile unsigned int pins;
    
    /*
     * Set a pin high without affecting other pins.
     * param WCpin = pin number to set high.
     */
    void high(int WCpin)
    {
        unsigned int bits = 1 << WCpin;
        DIRA |= bits;
        OUTA |= bits;
    }
    
    /*
     * Set a pin low without affecting other pins.
     * param WCpin = pin number to set low.
     */
    void low(int WCpin)
    {
        unsigned int mask = 1 << WCpin;
        DIRA |= mask;
        OUTA &= ~mask;
    }
    
    void do_toggle(void *arg __attribute__((unused)))
    {
        unsigned int nextcnt;
        nextcnt = wait_time + CNT;
    
        while(1)
        {
            high(21);
            nextcnt = waitcnt2(nextcnt, wait_time);
            low(21);
            nextcnt = waitcnt2(nextcnt, wait_time);
        }
    }
    
    #define MIN_GAP 400000
    
    int main (int argc, char* argv[])
    {
        int n;
    
    
        wait_time = CLKFREQ;
    
    
        n = _start_cog_thread(cog1_stack + STACK_SIZE, do_toggle, NULL, &thread_data);
        printf("Toggle Started on COG %d\n", n);
    
    
        while(1)
        {
            printf("Hello, World!\n");
            waitcnt(CLKFREQ+CNT);
    
    
            wait_time >>= 1;
            if (wait_time < MIN_GAP)
                wait_time = CLKFREQ;
    
    
        }
        return 0;
    }
    
    


    BTW, the _start_cog_thread function will not work with XMM modes. We have to use a PASM interface for this kind of program in XMM modes today. I'm looking into how this can be done with XMM modes.
  • RsadeikaRsadeika Posts: 3,837
    edited 2012-02-12 04:58
    Well, I played around with the above code example. With the idea of correct timing, it sure looks to be a little like dealing with interrupts. I am not sure how I could possibly use this method. Could not figure out how to get the LED to flash every second.

    I an still looking for an example that would match the Spin functionality of:
    PUB Main
      cognew(Atask, ...)
      cognew(Btask, ...)
    
    PUB Atask
      'A cog that is run independently with no timing constraints.
    
    PUB Btask
      'A cog that is run independently with no timing constraints.
    
    

    I think that is what some of the programmers of Spin would sort of expect C to accomplish, besides being able to use XMM and XMMC modes. Now there was some mention of C++, but I am not sure if it is implemented in this version of Propeller GCC.

    Ray
  • ersmithersmith Posts: 6,099
    edited 2012-02-12 08:52
    Rsadeika wrote: »
    I an still looking for an example that would match the Spin functionality of:
    PUB Main
      cognew(Atask, ...)
      cognew(Btask, ...)
    
    PUB Atask
      'A cog that is run independently with no timing constraints.
    
    PUB Btask
      'A cog that is run independently with no timing constraints.
    
    

    I think you've already had some examples of that -- both pthreads and _start_cog_thread accomplish exactly what you want, *in LMM mode* (which is also a restriction for Spin, since Spin has no XMM mode). There is currently no way simple way to run multiple C threads on multiple COGs in XMM or XMMC modes. We hope to fix that restriction in a future release.

    In the current code threads are pretty straightforward in LMM mode; personally I would use pthreads (since it is cross platform and has a simple API) but _start_cog_thread gives you finer control and less overhead. In XMM and XMMC modes, you can write simple COG C programs and launch them the way you do PASM programs (see for example the cog_c_toggle demo), but there's no way in propgcc to have more than one cog running XMM code at the same time.
    Now there was some mention of C++, but I am not sure if it is implemented in this version of Propeller GCC.

    Yes, C++ is implemented.

    Eric
  • jazzedjazzed Posts: 11,803
    edited 2012-02-12 09:23
    Ray,

    The _start_cog_thread and waitcnt2 method allows precise timing. The example provided is precise, it just demonstrates sharing variables between cogs. I've provided an example below that makes all cogs blink its assigned pin at exactly the same rate and time.

    This is the closest parallel of "C starting a C program" in LMM to "Spin starting a Spin program" because there is no limit other than HUB memory of either C program size.

    Maybe the word "thread" is misleading in this case - it is entirely different from pthreads because the program started is another LMM program. Using pthreads is not "precise" in Propeller terms because usleep(1) can take longer than 1 microsecond, but the _start_cog_thread method is certainly precise in Propeller terms.

    The toggle demos provide all the ways you can run programs in Propeller-GCC so far. There seems to be another method coming - if it's possible, someone will post about it with proof.
    /*
     * blinkcogs.c
     *
     * Make all propeller cogs blink assigned pins at exactly the
     * same rate and time to demonstrate the precision of the
     * _start_cog_thread method. This program and method uses
     * 8 LMM C program COG "threads" of execution simultaneously.
     */
    #include <stdio.h>
    #include <propeller.h>
    
    #define COGS 8
    #define STACK_SIZE 16
    
    static int cog_stack[STACK_SIZE][8];
    static _thread_state_t thread_data;
    
    volatile unsigned int wait_time;
    volatile unsigned int startcnt;
    volatile unsigned int pins;
    volatile int syncstart;
    
    /*
     * Set a pin high without affecting other pins.
     * param WCpin = pin number to set high.
     */
    void high(int WCpin)
    {
        unsigned int bits = 1 << WCpin;
        DIRA |= bits;
        OUTA |= bits;
    }
    
    /*
     * Set a pin low without affecting other pins.
     * param WCpin = pin number to set low.
     */
    void low(int WCpin)
    {
        unsigned int mask = 1 << WCpin;
        DIRA |= mask;
        OUTA &= ~mask;
    }
    
    /*
     * toggle thread function
     * param arg = pin number to toggle
     */
    void do_toggle(void *arg)
    {
        int pin = (int) arg;
        unsigned int nextcnt;
    
        while(syncstart == 0); // wait for start signal from main cog
    
        nextcnt = wait_time + startcnt;
        while(1)
        {
            high(pin);
            nextcnt = waitcnt2(nextcnt, wait_time);
            low(pin);
            nextcnt = waitcnt2(nextcnt, wait_time);
        }
    }
    
    int main (int argc, char* argv[])
    {
        int n;
        int cog;
        int pin[] = { 16, 17, 18, 19, 20, 21, 22, 23 };
        unsigned int nextcnt;
        wait_time = CLKFREQ/20;
        syncstart = 0;
        for(n = 1; n < COGS; n++) {
            cog = _start_cog_thread(cog_stack[n] + STACK_SIZE, do_toggle, (void*)pin[n], &thread_data);
            printf("Toggle COG %d Started\n", cog);
        }
        startcnt = CNT;
        syncstart = 1;
        nextcnt = wait_time + startcnt;
        while(1)
        {
            high(pin[0]);
            nextcnt = waitcnt2(nextcnt, wait_time);
            low(pin[0]);
            nextcnt = waitcnt2(nextcnt, wait_time);
        }
        return 0;
    }
    
    


    We are accomplishing all the goals you mention. We are using a different word for cognew in the spin sense that you mention mainly because we reserve it for launching COG C programs. We use cognew for starting PASM programs.

    We have added a cognew mode that C programmers might prefer in that it starts COG C programs that run as fast as PASM programs.

    This C equivalent of Spin cognew starting a Spin program is demonstrated with Eric's vgademo. In that demo, a C program vgademo.c does cognew of a C program written to run in a COG - the second COG program is limited by COG size, but it runs at full Propeller COG speed.

    C++ does work in the current distribution and toggle demonstrates just one possible approach. One of our contributors has started a great wiki about using C++ on Propeller here: http://code.google.com/p/propgcc/wiki/PropGccTightMemory


  • RsadeikaRsadeika Posts: 3,837
    edited 2012-02-12 10:45
    While I am in the process of figuring out what I will be doing next, I would like to take this moment to tell the PropGCC team that you guys are doing an excellent job. Trying as hard as I can to find bugs and problems with the software, I am not succeeding, in finding any bugs or problems, but then I am new at this. Hopefully everything will work as well when the Eclipse IDE is presented, any release updates?

    I am open to suggestions as to what area I should look into next, I am trying to explore areas that a new user may want to program in. The areas that have not been looked into would be:
    RTC - A simulated clock that could be run in XMM, or XMMC mode, with a start up program that would be on an uSD card.
    ADC - Since the C3 has that, would be nice to test out.
    Xbee - Maybe the start of some preliminary code and ideas as to how to get that going.
    uSD - I have to get back to that one. Is there a 2GB limit on that.

    Some of the other items, like VGA, TV, sound, and PS2, I think other people have more interest in that so maybe they will get on board and help out with the Alpha testing via real programs that could be used immediately.

    Ray
  • jazzedjazzed Posts: 11,803
    edited 2012-02-12 11:15
    Rsadeika wrote: »
    ... Hopefully everything will work as well when the Eclipse IDE is presented, any release updates?

    Ray,

    Thanks for you supportive words. Nice to hear your experience is good so far.

    It may be a while before the Eclipse IDE is ready.
    I do have an IDE project (not Parallax sponsored) that I can offer soon.
    Jeff thinks it's Ok to do this - I have been hesitant to post without his Ok.

    Rsadeika wrote: »
    I am open to suggestions as to what area I should look into next, I am trying to explore areas that a new user may want to program in.

    You may be interested in working on a "QuickBot" program I started (QuickStart BOE-BOT).
    Servo management is probably the most interesting aspect of QuickBot.
    I haven't had much time for it yet.
  • denominatordenominator Posts: 242
    edited 2012-02-12 23:44
    ersmith wrote: »
    There is currently no way simple way to run multiple C threads on multiple COGs in XMM or XMMC modes. We hope to fix that restriction in a future release.

    Just curious: Is caching the issue here (in other words there is no way to share the RAM cache between different XMM cogs)?
  • pmrobertpmrobert Posts: 677
    edited 2012-02-13 05:47
    I've been reading this thread since it's inception, lots of good stuff here for us newbies trying to move from Spin to C. Thanks to all! Now, a question: using pthreads in the LMM case, is it strictly necessary to use thread-safe delay techniques such as the various sleeps? I've replaced the thread safe delays with typical waitcnt delays and all seems well. Is this only because I've created less threads than cogs so there is no need for a thread to yield to another? The need to specifically yield would come into play when more than one thread has to run on the same cog, correct? I'm probably wording this poorly, I hope you can figure out my question.

    -Mike

    Edit: Never mind. http://forums.parallax.com/showthread.php?137776-What-is-a-pthread answers most of my questions and gives me direction to answer the rest.
  • jazzedjazzed Posts: 11,803
    edited 2012-02-13 08:31
    Just curious: Is caching the issue here (in other words there is no way to share the RAM cache between different XMM cogs)?
    That is the issue for now. If we move more of the cache algorithm to the XMM interpreter COG, we may be able to handle it and get a speedup.
  • jazzedjazzed Posts: 11,803
    edited 2012-02-13 08:41
    @pmrobert

    Hi there. Glad you found answers to most of your questions. Just briefly, I wanted to reiterate that any time we use pthreads, the thread-safe usleep and others must be used. Don't mix waitcnt in the main program or threads using pthreads because waitcnt is "not equipped to cooperate" with pthreads.

    However, if you have a program (or driver) started in another COG with cognew, that program can use waitcnt as long as it does not interfere with the main program which may be using pthreads. PASM FullDuplexSerial is a good example where waitcnt is used. The COG C based VGA driver is a good example where waitvid is used.

    --Steve
  • RsadeikaRsadeika Posts: 3,837
    edited 2012-02-17 09:55
    I started working with uSD program by Dave Hein using SimpleIDE. First thing I noticed is that it has to be compiled with XMM or XMMC it does not fit in LMM . I am using FileDriver.c which is located on page one of this thread, no need to upload it twice. I noticed the a.out file is 39KB in size. When I compile I have -Os turned on, and I do not see any other parameters to help reduce the size of this code.

    I guess I am wondering why this program is so large? What can be done to make this fit into LMM at the very least. Below is my file, which is 7KB, and FileDriver.c is 9KB in size. Any ideas?

    Ray


    /* test1.c */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <cog.h>
    #include <propeller.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <dirent.h>
    
    extern _Driver _SimpleSerialDriver;
    extern _Driver _FileDriver;
    
    _Driver * _driverlist[] = {
    &_SimpleSerialDriver,
    &_FileDriver,
    NULL
    };
    
    char *FindChar(char *ptr, int val);
    
    FILE *stdinfile;
    FILE *stdoutfile;
    
    void Help()
    {
      printf("Commands are help, ls, cat ...\n");
    }
    
    void List(int argc, char **argv)
    {
      int i, j;
      char *ptr;
      char fname[13];
      int32_t count = 0;
      uint32_t filesize;
      uint32_t longflag = 0;
      char *path;
      char drwx[5];
      int column;
      int prevlen;
      DIR *dirp;
      struct dirent *entry;
    
      for (j = 1; j < argc; j++)
      {
        if (argv[j][0] == '-')
        {
          if (!strcmp(argv[j], "-1"))
             longflag = 1;
          else
             printf("Unknown option \"%s\"\n", argv[j]);
        }
        else
          count++;
      }
    
      for (j = 1; j < argc || count == 0; j++)
      {
         if (count == 0)
         {
           count--;
           path = "./";
         }
         else if (argv[j][0] == '-')
            continue;
         else
            path = argv[j];
         if (count >= 2)
            fprintf(stdoutfile, "\n%s:\n", path);
    
         dirp = opendir(path);
    
         if (!dirp)
         {
            perror(path);
            continue;
         }
    
         column = 0;
         prevlen = 14;
         while (entry = readdir(dirp))
         {
            if (entry->name[0] == '.') continue;
            ptr = fname;
            for (i = 0; i < 8; i++)
            {
               if (entry->name[i] == ' ') break;
               *ptr++ = tolower(entry->name[i]);
            }
            if (entry->name[8] != ' ')
            {
               *ptr++ = '.';
               for (i = 8; i < 11; i++)
               {
                  if (entry->name[i] == ' ') break;
                  *ptr++ = tolower(entry->name[i]);
               }
            }
            *ptr = 0;
            filesize = entry->filesize_3;
            filesize = (filesize << 8) | entry->filesize_2;
            filesize = (filesize << 8) | entry->filesize_1;
            filesize = (filesize << 8) | entry->filesize_0;
            strcpy(drwx, "-rw-");
            if (entry->attr & ATTR_READ_ONLY)
               drwx[2] = '-';
            if (entry->attr & ATTR_ARCHIVE)
               drwx[3] = 'x';
            if (entry->attr & ATTR_DIRECTORY)
            {
               drwx[0] = 'd';
               drwx[3] = 'x';
            }
            if (longflag)
               fprintf(stdoutfile, "%s %8d %s\n", drwx, filesize, fname);
            else if (++column == 5)
            {
               for (i = prevlen; i < 14; i++) fprintf(stdoutfile, " ");
               fprintf(stdoutfile, "%s\n", fname);
               column = 0;
               prevlen = 14;
            }
            else
            {
               for (i = prevlen; i < 14; i++) fprintf(stdoutfile, " ");
               prevlen = strlen(fname);
               fprintf(stdoutfile, "%s", fname);
            }
         }
         closedir(dirp);
         if (!longflag && column)
            fprintf(stdoutfile, "\n");
      }
    }
    
    void Cat(int argc, char **argv)
    {
        int i;
        int num;
        void *infile;
        uint8_t buffer[40];
        
        for (i = 0; i < argc; i++)
        {
            if (i == 0)
            {
                if (argc == 1 || stdinfile != stdin)
                    infile = stdinfile;
                    else
                       continue;
            }
            else
            {
                infile = fopen(argv[i], "r");
                if (infile == 0)
                {
                    perror(argv[i]);
                    continue;
                }
            }
            if (infile == stdin)
            {
                while (gets(buffer))
                {
                    if (buffer[0] == 4) break;
                    fprintf(stdoutfile, "%s\n", buffer);
                }
            }
            else
            {
                while ((num = fread(buffer, 1, 40, infile)))
                       fwrite(buffer, 1, num, stdoutfile);
            }
            if (i)
              fclose(infile);
        }
        fflush(stdout);
    }
    
    char *SkipChar(char *ptr, int val)
    {
       while (*ptr)
       {
          if (*ptr != val) break;
          ptr++;
       }
       return ptr;
    }
    
    
    char *FindChar(char *ptr, int val)
    {
      while (*ptr)
      {
        if (*ptr == val) break;
        ptr++;
      }
      return ptr;
    }
    
    
    int tokenize(char *ptr, char *tokens[])
    {
      int num = 0;
    
      while (*ptr)
      {
        ptr = SkipChar(ptr, ' ');
        if (*ptr == 0) break;
        if (ptr[0] == '>')
        {
           ptr++;
           if (ptr[0] == '>')
           {
              tokens[num++] = ">>";
              ptr++;
           }
           else
              tokens[num++] = ">";
           continue;
        }
        if (ptr[0] == '<')
        {
           ptr++;
           tokens[num++] = "<";
           continue;
        }
        tokens[num++] = ptr;
        ptr = FindChar(ptr, ' ');
        if (*ptr) *ptr++ = 0;
      }
    
      return num;
    }
    
    
    
    
    int CheckRedirection(char **tokens, int num)
    {
      int i, j;
    
      for (i = 0; i < num-1; i++)
      {
        if (!strcmp(tokens[i], ">"))
        {
           stdoutfile = fopen(tokens[i+1], "w");
           if (!stdoutfile)
           {
              perror(tokens[i+1]);
              stdoutfile = stdout;
              return 0;
           }
        }
        else if (!strcmp(tokens[i], ">>"))
        {
          stdoutfile = fopen(tokens[i+1], "a");
          if (!stdoutfile)
          {
            perror(tokens[i+1]);
            stdoutfile = stdout;
            return 0;
          }
        }
        else if (!strcmp(tokens[i], "<"))
        {
          stdinfile = fopen(tokens[i+1], "r");
          if (!stdinfile)
           {
             perror(tokens[i+1]);
             stdinfile = stdin;
             return 0;
           }
        }
        else
          continue;
        for (j = i + 2; j < num; j++) tokens[j-2] = tokens[j];
        i--;
        num -= 2;
      }
    
      return num;
    }
    
    void CloseRedirection()
    {
       if (stdinfile != stdin)
       {
         fclose(stdinfile);
         stdinfile = stdin;
       }
       if (stdoutfile != stdout)
       {
         fclose(stdoutfile);
         stdoutfile = stdout;
       }
    }
    
    
    int main()
    {
        sleep(1);
        printf("The uSD program.\n"); 
    
      int num;
      char *tokens[20];
      uint8_t buffer[80];
    
      stdinfile = stdin;
      stdoutfile = stdout; 
    
    
    #ifdef __PROPELLER_LMM__
    #ifdef SPINNERET_CARD
      buffer[0] = 16;
      buffer[1] = 21;
      buffer[2] = 20;
      buffer[3] = 19;
      LoadSDDriver(buffer); 
    #else
      LoadSDDriver(0);  
    #endif
    #endif
    
      dfs_mount(); 
    
      printf("\n");
      Help();
    
      while(1)
      {
        printf("\n>");
        fflush(stdout);
        gets(buffer);
        num = tokenize(buffer, tokens);
        num = CheckRedirection(tokens, num);
        if (num == 0) continue;
        if (!strcmp(tokens[0], "help"))
           Help();
        else if (!strcmp(tokens[0], "ls"))
           List(num, tokens);
        else if (!strcmp(tokens[0], "cat"))
           Cat (num, tokens);
        else
        {
          printf("Invalid command\n");
          Help();
        }
        CloseRedirection();
      }
      return 0;
    }
    
    
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-02-17 09:59
    There is a printf.c file in the c3files/src directory. You have to include this file in your build to make it fit in the LMM mode. Even the _simple_printf in the library is too big for LMM.

    EDIT: I think the problem with using _simple_printf is that filetest.c also uses fprintf, so it pulls in the standard library functions in addition to _simple_printf.
  • RsadeikaRsadeika Posts: 3,837
    edited 2012-02-17 10:16
    Yes, it works, but the a.out file is now 28KB in size. I guess that does not leave a lot of room for the main file to grow. Is this file growth because of programming in C? Once people see this, and they may not be interested in working with uSD stuff. So, what other devices are going to be growing like this?

    Ray
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-02-17 10:46
    I get 30,852 bytes for the LMM version of c3files. That leaves almost 2,000 bytes for malloc space and the stack, which is just barely enough. Your test1.c program is based on filetest.c, but you must have removed some code to make it slightly smaller. You shouldn't need to include FileDriver.c with your project, since this is also located in the library. I had suggested earlier that you include a copy of FileDriver.c so you could add debug prints, but you shouldn't need that anymore.

    C does generate a larger executable than Spin. That probably the only real disadvantage to using C versus Spin. It's great for small programs, but you will need to use XMM/XMMC for larger programs.
Sign In or Register to comment.