My new(old) dev platform
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?
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
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 = ¶ms;
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
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
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 = ¶ms; dfs_mountflag = 0; printf("SD is unmounted.\n"); }