Shop OBEX P1 Docs P2 Docs Learn Events
My new(old) dev platform — Parallax Forums

My new(old) dev platform

RsadeikaRsadeika Posts: 3,837
edited 2013-01-24 13:20 in Propeller 1
I was looking at the pile of propeller boards I have laying around, and I noticed I have an Original Propeller Platform (OPP) board, so fired it up, it came up with a 'no propeller found' error. I pulled the Propeller chip and was ready to toss it, but I decided to push it back in, and now it works. I guess those Propeller chips get lazy if they are not worked all of the time.

I decided this will be one of my dev platforms. On a piece of cardboard, I mounted the OPP, and added a breadboard. On the breadboard I have a Parallax uSD breakout board, an will be adding a Parallax XBee adapter, plus there will enough room on the breadboard for other things to tested. Below I have Dave Hine's filetest program which has a mount() function for the uSD which uses pins 24,25,26,and 27. Two things that I see that the program needs are, a format() command, and a small editor for doing some more than what echo can permit. Anybody have such things?

In the mount command I included the code below, when I start the program with no SD card inserted, it comes back with an error '6', where is it getting the error numbers from, and is there a way of printing that full error explanation, plus whatever other error codes are associated?
    uint32_t mountErr = dfs_mount(mountParams);
    if (mountErr)
    {
        printf("Mount ERROR: %d\n", mountErr);
        printf("Check for card insertion \n");
        exit(1);
    }

The next thing I will be adding is an XBee module, I have to learn more about what I can do with those series 1 modules within the C environment. Since the OPP only has a 32KB EEPROM, I am constrained to a CMM mode, maybe if I find a 64KB EEPROM laying around I will use that, and then I will be able to use XMMC modes. Which leads to another problem, does anybody have a cfg example for that board, the HUB type does not cover XMMC or any form of writing to the SD card?

Since I have been looking at the OPP, I think it makes a very good dev board for a dev platform, you fry a pin, pull the chip, and replace it with a new one, I am starting to realize, for this particular project, the necessity of having parts that are socket-ed.

Ray
/**
 * @file test_opp.c
 * This is the main test_opp program start point.
 */
#include <propeller.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sd.h>
#include <dirent.h>

#include <string.h>
#include <sys/stat.h>
#include <ctype.h>
#include <cog.h>
#include <unistd.h>

extern _Driver _SimpleSerialDriver;
extern _Driver _FileDriver;

_Driver *_driverlist[] = {
    &_SimpleSerialDriver,
    &_FileDriver,
    NULL
};


char *FindChar(char *ptr, int val);

FILE *stdinfile;
FILE *stdoutfile;


/* Print help information */
void Help()
{
    printf("Commands are help, cat, rm, ls, ll, echo, cd, pwd, mkdir, rmdir and quit\n");
}

void Cd(int argc, char **argv)
{
    if (argc < 2) return;

    if (chdir(argv[1]))
        perror(argv[1]);
}

void Pwd(int argc, char **argv)
{
    uint8_t buffer[64];
    char *ptr = getcwd(buffer, 64);
    if (!ptr)
        perror(0);
    else
        fprintf(stdoutfile, "%s\n", ptr);
}

void Mkdir(int argc, char **argv)
{
#ifndef __PROPELLER_LMM__
    int i;

    for (i = 1; i < argc; i++)
    {
        if (mkdir(argv[i], 0))
            perror(argv[i]);
    }
#else
    printf("Not enough memory for mkdir in LMM mode\n");
#endif
}

void Rmdir(int argc, char **argv)
{
#ifndef __PROPELLER_LMM__
    int i;

    for (i = 1; i < argc; i++)
    {
        if (rmdir(argv[i]))
            perror(argv[i]);
    }
#else
    printf("Not enough memory for rmdir in LMM mode\n");
#endif
}

/* This routine implements the file cat function */
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);
}

/* This routine deletes the files specified by the command line arguments */
void Remove(int argc, char **argv)
{
    int i;

    for (i = 1; i < argc; i++)
    {
        if (remove(argv[i]))
            perror(argv[i]);
    }
}

/* This routine echos the command line arguments */
void Echo(int argc, char **argv)
{
    int i;
    for (i = 1; i < argc; i++)
    {
        if (i != argc - 1)
            fprintf(stdoutfile, "%s ", argv[i]);
        else
            fprintf(stdoutfile, "%s\n", argv[i]);
    }
}

/* This routine lists the root directory or any subdirectories specified
   in the command line arguments.  If the "-l" option is specified, it
   will print the file attributes and size.  Otherwise, it will just
   print the file names.  */
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;

    // Check flags
    for (j = 1; j < argc; j++)
    {
        if (argv[j][0] == '-')
        {
            if (!strcmp(argv[j], "-l"))
                longflag = 1;
            else
                printf("Unknown option \"%s\"\n", argv[j]);
        }
        else
            count++;
    }

    // List directories
    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");
    }
}

/* This routine returns a pointer to the first character that doesn't
   match val. */
char *SkipChar(char *ptr, int val)
{
    while (*ptr)
    {
        if (*ptr != val) break;
        ptr++;
    }
    return ptr;
}

/* This routine returns a pointer to the first character that matches val. */
char *FindChar(char *ptr, int val)
{
    while (*ptr)
    {
        if (*ptr == val) break;
        ptr++;
    }
    return ptr;
}

/* This routine extracts tokens from a string that are separated by one or
   more spaces.  It returns the number of tokens found. */
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;
}

/* This routine searches the list of tokens for the redirection operators
   and opens the files for input, output or append depending on the 
   operator. */
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;
}

/* This routine closes files that were open for redirection */
void CloseRedirection()
{
    if (stdinfile != stdin)
    {
        fclose(stdinfile);
        stdinfile = stdin;
    }
    if (stdoutfile != stdout)
    {
        fclose(stdoutfile);
        stdoutfile = stdout;
    }
}

void mount()
{
/* This setup is for the Parallax micro-SD Card Adaapter(#32312) */
/* Make sure you have #include <sys/sd.h> for SD params
                      #include <stdlib.h> for exit() control */

    printf("Load and mount SD:\n");
    _SD_Params* mountParams = (_SD_Params*)-1;
    
    static _SD_Params params =
    {
        AttachmentType: _SDA_SingleSPI,
        pins:
        {
            SingleSPI:
            {
                MISO: 24, // DO
                CLK : 25, // CLK
                MOSI: 26, // DI
                CS  : 27  // CS
            }
        }
    };
    mountParams = &params;
    if (mountParams == (_SD_Params*)-1)
    {
        printf("You must specify the SD parameters in mount()\n");
        exit(1);
    }
    
    uint32_t mountErr = dfs_mount(mountParams);
    if (mountErr)
    {
        printf("Mount ERROR: %d\n", mountErr);
        printf("Check for card insertion \n");
        exit(1);
    }
    printf("SD mounted\n");
}



/**
 * Main program function.
 */
int main(void)
{
    int num;
    char *tokens[20];
    uint8_t buffer[40];
    
    stdinfile = stdin;
    stdoutfile = stdout;
    
    waitcnt(CLKFREQ + CNT);
    mount();
    printf("Program start\n");
    while(1)
    {
        printf(">");
        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], "quit"))
            break;
        else if (!strcmp(tokens[0], "ls"))
            List(num, tokens);
        else if(!strcmp(tokens[0], "ll"))
        {
            tokens[num++] = "-l";
            List(num, tokens);
        }
        else if (!strcmp(tokens[0], "echo"))
            Echo(num, tokens);
        else if (!strcmp(tokens[0], "cat"))
            Cat(num, tokens);
        else if (!strcmp(tokens[0], "rm"))
            Remove(num, tokens);
        else if (!strcmp(tokens[0], "cd"))
            Cd(num, tokens);
        else if(!strcmp(tokens[0], "pwd"))
            Pwd(num, tokens);
        else if (!strcmp(tokens[0], "mkdir"))
            Mkdir(num, tokens);
        else if (!strcmp(tokens[0], "rmdir"))
            Rmdir(num, tokens);
        else
        {
            printf("Invalid command\n");
        }
        CloseRedirection();
    }
    printf("System Stop\n");
    return 0;
}

Comments

  • jazzedjazzed Posts: 11,803
    edited 2013-01-23 15:03
    If you setup a board .cfg file with the SD pins, you don't need to use mount. Look at ppusb.cfg in propgcc\propeller-load for a good example.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-01-23 15:36
    Error 6 is defined in dosfs.h as DFS_IOERROR. I think this is being returned when the SPI cog is loaded, and the code is waiting for a response from the cog. You said you did not have an SD card loaded, so I think this is the response that you'll get.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-01-24 03:54
    I added a mount() command to the program with a warning that says "SD card not mounted", at the start of the program. I was experimenting with doing a mount, then removing the SD card and then trying to do a remount, which is not working as expected. I thought it would be nice to have the ability to switch out SD cards, and be able to mount the new one, while still running the program. I am wondering if that can be accomplished with the amount of memory that is still available in CMM mode?

    I guess by adding a remount, a format feature, and a mini vi, that just might put it to the limits of CMM space that is available, but I am not sure?

    Ray
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-01-24 12:15
    The file driver sets a flag called dfs_mountflag to indicate that mount has been called. The driver never resets this flag, so subsequent calls to mount will just return immediately. You could add and "extern int dfs_mountflag;" to your code, and set dfs_mountflag to zero when the SD card is removed.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-01-24 13:20
    I added the 'extern int dfs_mountflag;', and created an unmount command, which is shown below. This is not getting me anywhere. I thought the code below would reset the pins to 'NULL', meaning, there is no SD socket attached, and then set dfs_mountflag to 0. After I do an 'unmount', and then an 'ls', I do not get the 'IO error' ,which is what I am expecting to see. Anybody have any ideas?

    Ray
    void unmount()
    {
        _SD_Params* mountParams = (_SD_Params*)-1;
        static _SD_Params params =
        {
            AttachmentType: _SDA_SingleSPI,
            pins:
            {
                SingleSPI:
                {
                    MISO: NULL,
                    CLK:  NULL,
                    MOSI: NULL,
                    CS:   NULL
                }
            }
        };
        mountParams = &params;
        dfs_mountflag = 0;
        printf("SD is unmounted.\n");
    }
    
Sign In or Register to comment.