Shop OBEX P1 Docs P2 Docs Learn Events
Catalina 2.9 - Page 12 — Parallax Forums

Catalina 2.9

1910121415

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-03-16 06:00
    Dr_Acula wrote: »
    1) in "serial_rxcheck, if I don't explicitly set rxbyte to zero at the beginning of the function, it decrements each time. I thought C set a variable to zero when the variable was defined? Maybe it is good programming practice to set variables to zero anyway?
    Local variables are not automatically initialised in C. In this particular function just use
    unsigned long rxbyte = -1;
    
    Dr_Acula wrote: »
    I get a compiler error when using <0, but 0xffffffff and -1 works fine. It doesn't really matter but it might make it easier translating spin.
    What's the exact error? Something about signed comparison?
  • Heater.Heater. Posts: 21,230
    edited 2011-03-16 06:01
    Dr_A,
    The IDE is taking the pasm part (which exists as a comment block in C), compiling it, pasting it back into C as an array, and the C part is interacting with this.

    I'm sorry but this is grotesque:)

    I don't like the idea of my tools hacking on my source files.

    Would it not be easier and more elegant to:

    1) Compile the FullDuplexSerial spin file with BST or HomeSpun using whatever the command line option is to extract the compiled PASM as binary into a file discarding all the Spin stuff.

    2) Massage that binary into a C source file containing a declaration of an array with the PASM in it. in hex.

    3) Compile and link you FDX access functions with the PASM contained in the above file.

    That is pretty much what I did for Zog a while back. Except there I have a tool to convert the raw binary PASM produced by compiling the Spin files into object files that can be linked into any C program like any other C objects.

    Must say I prefer having by curly brackets on their own lines as well.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-16 06:09
    That sounds an interesting idea heater.

    Initially I did it this way because I wasn't sure if I would need to edit the pasm and the C at the same time, and it would be easier debugging if they were both in the same program.

    But it is extremely messy, especially as it rewrites the source code. And it has bitten me once when it deleted some working code (lucky I had posted it to the forum).

    However... it looks like it may be possible to use the pasm part without making any changes. SimpleSerial pasm has not been changed at all. I need to take a look at a few other objects and see if they work in the same way, but certainly ones that pass values using "par" ought to work.

    So - if no changes are made, we could reduce this down to maybe one line in the C program that just has the name of the spin file? Maybe even take it further and use the .cog files on the sd card (I have that bit working - it is a single button "compile pasm and rename .bin to .cog and download .cog file to sd card using Kyedos")

    I guess pasting in the compiled code as a C array means it is a self contained C program, but at the same time, I imagine that this is only ever going to be practical on boards with external memory and with an sd card. So the .cog approach is going to be so much neater.

    The C program would contain a function to load a .cog file off an sd card and into a cog. I think all code to do that exists already.

    I have a vague feeling that not all objects use the "par" method. If values are linked in some other way eg via common variables, the Spin file is going to need a lot more editing. Such spin files would need rewriting anyway, as they would tend to scatter variables all over the hub ram, wheras the "par" method keeps all the variables together. Also, Catalina is set up to use the "par" method. Would Zog use this too?
  • Heater.Heater. Posts: 21,230
    edited 2011-03-16 06:23
    Yep, for my method to work it is required that the PASM is not in any way "linked" with the Spin. That is to say that there are no variables in the DAT that are modified by Spin prior to the COG being loaded with the PASM from that DAT. I'm sure this is true for using PASM code in any other language system. The PASM code must get it's parameters via PAR at load time and it must have a neat "mailbox" area in RAM to interact with the C or whatever other code.

    When I got FullDuplexSerial working with Zog there was at least one VAR in DAT (can't remeber what it was) that was set up by Spin. I got rid of that. Now I have an FX that can be used normally in a Spin program or compiled into a PASM binary blob for use with C.
    Catalina is set up to use the "par" method. Would Zog use this too?

    Yes, exactly as I describe above.

    For sure a lot of existing objects have probably got variables being set up from Spin and will need to be modified to use as we are doing. Bill Henning myself and others have been harping on about this for a while. It should be some sort of standard that object writers don't do that. Then PASM objects would be useable form any language system and life would be good:)
  • RossHRossH Posts: 5,547
    edited 2011-03-16 07:33
    David, Jazzed ...

    I have just emailed you both a pre-release version of Catalina 3.0. The DracBlade and C3 are the only platforms I have tested as yet (they are currently the only ones that support the caching XMM driver)..

    Ross.
  • RossHRossH Posts: 5,547
    edited 2011-03-16 07:40
    Dr_A,

    I think your approach is worh pursuing - it allows the type of "encapsulation" that SPIN offers, which is one thing that makes SPIN and PASM work so well together. It would also assist users of those languages to migrate to C (which is not a language that supports encapsulation at all well!).

    Now that Catalina 3.0 is finally coming together, I hope to get some time to play with it.

    Ross.
  • jazzedjazzed Posts: 11,803
    edited 2011-03-16 07:42
    Heater. wrote: »
    Would it not be easier and more elegant to:

    1) Compile the FullDuplexSerial spin file with BST or HomeSpun using whatever the command line option is to extract the compiled PASM as binary into a file discarding all the Spin stuff.

    2) Massage that binary into a C source file containing a declaration of an array with the PASM in it. in hex.

    3) Compile and link you FDX access functions with the PASM contained in the above file.

    There is a long history of doing this even with Propeller :-) Catalina can do it.
    Heater. wrote: »
    Must say I prefer having by curly brackets on their own lines as well.
    Me too. It makes some things much easier.
    RossH wrote: »
    I have just emailed you both a pre-release version of Catalina 3.0.
    Thanks. Got it. I'll be looking at it later today - I have another commitment this morning.
  • David BetzDavid Betz Posts: 14,519
    edited 2011-03-16 07:44
    RossH wrote: »
    David, Jazzed ...

    I have just emailed you both a pre-release version of Catalina 3.0. The DracBlade and C3 are the only platforms I have tested as yet (they are currently the only ones that support the caching XMM driver)..

    Ross.

    Got it! Thanks Ross.
  • Heater.Heater. Posts: 21,230
    edited 2011-03-16 08:23
    RossH,
    It would also assist users of those languages to migrate to C (which is not a language that supports encapsulation at all well!)

    Which is why Zog encapsulates FullDuplexSerial PASM code into a C++ class.
    The you can write:
    ser.tx('A');
    
    similar to what you do in Spin.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-16 15:31
    Heater, how does Zog do the memory management?

    One of the problems with trying to replicate a spin "object" is where things are stored. If you want to save hub ram by storing cog data in external memory, then this means that in catalina you have to declare the array in the 'main'. And every function needs to know where the common variables are stored, so you have to pass that array to each and every method.

    So behind the scenes, when you are using
    ser.tx('A');
    

    how does .tx know where the buffer is located, or the value for the head counter?

    In some ways, this leads to a discussion about the merits of global variables. When I first started coding, everything was 'global' but I have seen languages evolve, and things like pointers in C have appeared in other ways in other languages, eg "byref" and "byval" in .net I've also seen people edit code I have posted so that variables are passed to functions and are not global.

    One can see the merit in this - the main advantage is in debugging where 50 functions might be changing a global variable, it can get very hard to track down bugs. If variables are explicitly passed to a function, it can make debugging easier as you can print out all the variables before the function is called and then all the variables after and compare them.

    Spin has global variables, and indeed, it may be the availability of this that has led to objects being written that don't use the 'par' method of talking to cogs.

    Your example ser.tx('A'); also implies global variables, because there are a number of variables that .tx is going to need to know in order to function.

    When you say this is a C++ class, could you explain a bit more how this works?

    I wonder also about the merits of the spin object system. The obvious advantage is that it is easy to go to the obex, copy a file into your program, reference it and then use it.

    But I've never quite worked out whether sub objects can use other sub objects. Consider 'main' which has the subobject 'simpleserial'. It also has the subobject 'strings'. Say you are debugging 'strings'. Can you send data out using 'simpleserial'?

    You could add another instance of simpleserial, but that uses more precious memory.

    Ross said
    (C... is not a language that supports encapsulation at all well!).

    I am not entirely sure this is such a bad thing, because the advantage of the way C does things is that every function can call every other function. So you don't need multiple instances of simpleserial to debug your program.

    It gets more complicated when you consider objects that use multiple cogs - eg a video driver using three cogs. How do you have 3 instances of that? I wonder if this is the reason a lot of debugging is done via the serial terminal rather than to a vga screen?
  • RossHRossH Posts: 5,547
    edited 2011-03-16 15:33
    Heater. wrote: »
    RossH,



    Which is why Zog encapsulates FullDuplexSerial PASM code into a C++ class.
    The you can write:
    ser.tx('A');
    
    similar to what you do in Spin.

    I agree with the last line, but not the rest. "Encapsulation" is not the same as "information hiding" - and it is the latter which is the primary purpose of a C++ class (e.g. to hide the implementation from the interface). But on the Propeller we actually get benefit from doing exactly the opposite (I don't know a good term for this - perhaps "information exposure?")

    There's not much benefit to be gained from "information hiding" on a microcontroller like the Propeller, where the largest program you can write consists of only a few dozen pages of code. So SPIN does the opposite - i.e. it makes a real virtue out of exposing relevant low level information information at the high level. In SPIN, the ability to encapsulate the related PASM code along with the SPIN code - so that you can see it, understand it, and also modify it when you need to - is what gives SPIN its power and makes it usable on a microcontroller - despite the fact that by itself SPIN is a slow and quirky interpreted language. In other wods, the reason it works is because the SPIN code (which generally provides the interface) is logically encapsulated with the PASM code (which generally does the work) but not hidden.

    A key advantage of Dr_A's approach is that it allows a very similar thing to be done in C. Dr_A may be doing this to make dynamically loadable "cogjects" - but I think its main benefit could be that it allows C to be substituted for SPIN in a way that will be both familiar to SPIN programmers and accessible to C programmers - yet doesn't rely on non-standard extensions to C, and which also doesn't require a complex understanding of a language tool chain like gcc (or Catalina for that matter) to build and run.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-16 15:44
    Ross and I posted at the same time replying to heater!

    Ok, Ross, regarding information exposure, let's say we take simpleserial and we split it into the pasm and the spin part. We leave the pasm as it is, and we translate the spin into C (or Basic for that matter). We then compile the pasm part into a binary file and call it a .cog file and put it on the sd card.

    Do you think that would mean the information in that pasm file starts to get lost, or forgotten about?

    Or is it better for the pasm code to always be visible in your main program, to keep reminding you what it is?

    I wonder how many people use objects as they are, and how many people tweak the code? My gut feeling is that most people use the code as it is, but then again, I have not found a single object that does exactly what I want, and they have all ended up being changed a bit.

    I'm thinking of different approaches:

    a C program with pasm in it, that gets converted to a C array (heater says this is messy, and I tend to agree)
    a C program with pasm in it that gets converted to a .cog file and downloaded separately (this could slow down the download process)
    a C program where the pasm is in a completely separate program and is compiled separately
    a C program where the pasm is converted to a .cog file, but you have the option to not download the .cog file as well (ie if you have not edited it)

    or maybe an IDE that displays both.

    I can see advantages and disadvantages with each of these approaches.
  • RossHRossH Posts: 5,547
    edited 2011-03-16 16:03
    Dr_Acula wrote: »
    Ross and I posted at the same time replying to heater!

    Ok, Ross, regarding information exposure, let's say we take simpleserial and we split it into the pasm and the spin part. We leave the pasm as it is, and we translate the spin into C (or Basic for that matter). We then compile the pasm part into a binary file and call it a .cog file and put it on the sd card.

    Do you think that would mean the information in that pasm file starts to get lost, or forgotten about?
    Not "fogotten about", but certainly not as accessible - or as easy to modify - as it would be in SPIN.
    Dr_Acula wrote: »

    Or is it better for the pasm code to always be visible in your main program, to keep reminding you what it is?
    Exactly - don't forget that our target market is a microcontroller - where understanding the low level detail of what is actually going on in the cogs, registers and pins is vital. I probably wouldn't have the same opinion if we were discussing a general purpose processor where I could safely leave all the details to the operating system and simply rely on the fact that I have a zillion times more processing power to do any job than I actually need.
    Dr_Acula wrote: »

    I wonder how many people use objects as they are, and how many people tweak the code? My gut feeling is that most people use the code as it is, but then again, I have not found a single object that does exactly what I want, and they have all ended up being changed a bit.
    I can only really speak for myself - but I rarely find myself using an object without some "tweaking". Also, given that most code in the OBEX has minimal documentation, you have to be able to read the code - and refer back to it many times - to be able to use it.
    Dr_Acula wrote: »
    I'm thinking of different approaches:

    a C program with pasm in it, that gets converted to a C array (heater says this is messy, and I tend to agree)
    a C program with pasm in it that gets converted to a .cog file and downloaded separately (this could slow down the download process)
    a C program where the pasm is in a completely separate program and is compiled separately
    a C program where the pasm is converted to a .cog file, but you have the option to not download the .cog file as well (ie if you have not edited it)

    or maybe an IDE that displays both.

    I can see advantages and disadvantages with each of these approaches.

    I vote for the first option because it is closest to the way most people currently use the Propeller.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-16 17:33
    Ok. Do you ever think that people would want binary files on an sd card? I'm thinking of zog, and maybe basic?

    I guess in a general sort of way, would people who have external memory be likely to be using an sd card as well? I think they probably would be as you need to load the big C program from somewhere.

    But then again, maybe the binary blob idea might be useful for a propeller without external memory but with an sd card.

    If so, I an testing these out - just realised from the catalina 2.6 thread, 14th December, that a .binary file is not the true source file. A reminder to myself:
    1) the true file starts at 18H and
    2) the bytes are reversed in groups of 4
  • RossHRossH Posts: 5,547
    edited 2011-03-16 17:43
    Hi Dr_A,

    I think allowing the loading of binary "blobs" on an SD Card is a good idea - but just keep in mind that it is a technique that has only limited application. We all write various operating systems and fancy program loaders for our Propellers because we find them useful as developers (and also because its fun to do so!) - but in reality I'd expect that >90% of all Propellers used in production systems just need to load a single fixed application - once - on bootup. Mostly that would be from EEPROM, but sometimes from SD Card.

    And yes, I think you absolutely have to have an SD card (or something!) when you have external ram. Loading large programs serially can take many, many minutes. With jazzed's 32Mb SDRAM card, you could probably spend 10 minutes just booting the propeller if you had to load it serially!

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-16 17:57
    Ok, that makes sense.

    Another reason I'm looking at binary blobs is for a propeller with no external memory but with an sd card. The aim would be to load all binary blobs through a common 2k block of hub ram, and hence save up to 14k of program space.

    There is something about heaters comment that is right - at the moment I am self modifying the code by creating an array with the cog code in it, and that has already bitten me. Even doing an include.h is self modifying if you change the name of the pasm bit.

    Also I've been staring at my code for a long time, and while it is very useful to see the pasm code and to modify it, I don't think it has been terribly useful to see the binary file it creates
           unsigned long mycogject_array[] =
           {
               0xa0bc21f0, 0x08bc1c10, 0x80fc2004, 0x08bc1e10, 
               0x083c1e0e, 0x80fc2004, 0x80fc1c04, 0x08bc1e10, 
               0x083c1e0e, 0x80fc2004, 0x80fc1c04, 0x08bc1e10, 
               0x083c1e0e, 0x5c7c000d, 0x00000000, 0x00000000, 
               0x00000000
           };
    

    Is there any extra speed cost in loading off the sd card as binary blobs? I am not certain there is much of a cost, because you are either loading this data into external ram as part of a program, or you load it later when the program runs.

    Which is tending to sway me towards binary blobs rather than inline arrays.

    I think I will still keep the pasm code as part of the program though. (as a comment block).

    Your thoughts?
  • RossHRossH Posts: 5,547
    edited 2011-03-16 18:08
    Dr_A,

    Yes I agree that seeing the blob itself is not useful - it's like being forced to look at the intermediate object file every time you compile a program. But in my view separating them out to separate files in this instance is worse. But this is why we have tools - the tool needs to keep them in one file, but display them in such a way that the PASM is easy to see, the C code is easy to see, but the ugly binary blob which is the intermediate format is not. Perhaps some marker comments in the source file that tells the tool to display some parts of the program but hide others unless specifically requested to display them - a bit like the Propeller tools various options? (I can't remember what they're called now - something like "condensed" and "summary"?).

    Ross.

    P.S. Yes, there is a significant speed loss in loading from SD Card. Also, it means all programs have to contain SD Card drivers. This will be a problem for smalll appications.
  • RossHRossH Posts: 5,547
    edited 2011-03-16 19:06
    David Betz wrote: »
    I just installed this and built my xbasic interpreter successfully It generates 134k of code and 19k of data so it should run on the C3 with -x3 to put the code in flash. Unfortunately, I can't load it successfully using payload. I specified -m10 to increase the number of retries but it still fails. Do I need an even bigger number?

    Hi David,

    Can you post what Payload says? also, here are a couple of things to try:

    1. Make sure you have rebuild the "utilities" folder using the same options you used to build the program. For instance, if you build the program using -D C3 -D CACHED, then rebuild the utilities folder by saying:
    cd utilities
    build_all C3 CACHED
    
    2. Specify the -t (timeout) option, not -m. For instance:
    payload xmm xbasic -t 1000
    
    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-16 19:06
    Yes good points. I am finding the loader is a little slow. And you are right about not all programs having an sd card.

    Maybe for the moment I'll work on both including an array inline, and also loading binary blobs, and test them in parallel to make sure both work, then later on look at some sort of switch to choose to do one or the other? It takes no time at all in the IDE to create .cog files as well as all the other things so easy to have these as well.

    I was wondering if you could help with another little problem.

    The sd loader is loading in 2047 bytes. But the cog loader is expecting longs
    _coginit((int)parameters_array>>2, (int)hubcog>>2, cognumber); // load the cog

    Whjat is the simplest way to convert an array of bytes to an array of longs?

    Little endian vs big endian is not a problem as the vb.net IDE can create either.

    In C, there is getc, but I am not sure if there is a 'long' equivalent.

    Do you need to go through each value and rebuild a long, with binary shifts and/or multiplies?

    Or is there a way of passing a byte array to a function, but reading it as a long array?

    Or is there another way?
  • RossHRossH Posts: 5,547
    edited 2011-03-16 19:21
    Dr_Acula wrote: »
    I was wondering if you could help with another little problem.

    The sd loader is loading in 2047 bytes. But the cog loader is expecting longs
    _coginit((int)parameters_array>>2, (int)hubcog>>2, cognumber); // load the cog

    Whjat is the simplest way to convert an array of bytes to an array of longs?

    Little endian vs big endian is not a problem as the vb.net IDE can create either.

    In C, there is getc, but I am not sure if there is a 'long' equivalent.

    Do you need to go through each value and rebuild a long, with binary shifts and/or multiplies?

    Or is there a way of passing a byte array to a function, but reading it as a long array?

    Or is there another way?

    Here is some "quick and dirty" code I use. I'm sure there are better ways:

    To read:
    my_long = getc(my_file) | (getc(my_file)<<8) | (getc(my_file)<<16) | (getc(my_file)<<24);
    
    To write:
    putc(my_long & 0xff, my_file);
       putc(my_long>>8 & 0xff, my_file);
       putc(my_long>>16 & 0xff, my_file);
       putc(my_long>>24 & 0xff, my_file);
    
    Ross.
  • Martin HodgeMartin Hodge Posts: 1,246
    edited 2011-03-16 20:05
    This thread surely is in the top 5 most informative and productive ever on this forum!
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-16 23:57
    Thanks Ross - that code looks perfect!
  • David BetzDavid Betz Posts: 14,519
    edited 2011-03-17 06:29
    I mostly got xbasic running on the C3 under Catalina 3.0 using the -x3 memory configuration. Thanks to Ross I've also fixed a memory management bug that had nothing to do with Catalina! I've also removed all of the code that used to deal with the old Catalina HMI character handling and am now assuming ANSI handling of characters. The only problem seems to be that trying to load a program from the SD card causes the C3 to reset. I'm not sure why this is happening and will have to look into it further later. In the meantime, here is the code I have running so far. It's a fairly simple Basic. The syntax is described briefly in a file called syntax.txt included in the zip file.
  • RossHRossH Posts: 5,547
    edited 2011-03-17 14:46
    David Betz wrote: »
    The only problem seems to be that trying to load a program from the SD card causes the C3 to reset.

    Hi David,

    I must admit I've only tried to load xbasic serially - I'll have a look at the SD loader code tonight.

    Also, probably worth pointing out that this code won't run on the C3 (at least not using Catalina) until I release version 3.0.

    Ross.

    EDIT: just realized that if David has reverted this code to assuming ANSI character handling, then this version wont run under Catalina on any platform until I release version 3.0!
  • David BetzDavid Betz Posts: 14,519
    edited 2011-03-17 16:44
    RossH wrote: »
    Hi David,

    I must admit I've only tried to load xbasic serially - I'll have a look at the SD loader code tonight.

    No, I didn't mean that I loaded xbasic from the SD card. I've always used payload to load it serially. I meant that when I tried to type "load test.bas" at the Basic prompt my C3 reset. This used to work with the old C3 version of Catalina so I'm not sure what I've changed that makes it fail. The same code works under ZOG and under Mac OS.
  • RossHRossH Posts: 5,547
    edited 2011-03-17 17:16
    David Betz wrote: »
    No, I didn't mean that I loaded xbasic from the SD card. I've always used payload to load it serially. I meant that when I tried to type "load test.bas" at the Basic prompt my C3 reset. This used to work with the old C3 version of Catalina so I'm not sure what I've changed that makes it fail. The same code works under ZOG and under Mac OS.

    Ah, got it now. This works okay for me - does it happen every time you try and load?

    Ross.
  • David BetzDavid Betz Posts: 14,519
    edited 2011-03-17 18:16
    RossH wrote: »
    Ah, got it now. This works okay for me - does it happen every time you try and load?

    Ross.

    It has always failed for me. Strange since we're both using the same tools and the same hardware.
  • RossHRossH Posts: 5,547
    edited 2011-03-17 18:43
    David Betz wrote: »
    It has always failed for me. Strange since we're both using the same tools and the same hardware.

    That is odd. Can you try a different SD Card? If possible, try one that has just been formatted with a cluster size of 32k and an MBR?

    Ross.
  • RossHRossH Posts: 5,547
    edited 2011-03-17 19:23
    David Betz wrote: »
    FAT or FAT32?

    Try FAT - that's what I used. But FAT32 should also work.

    Ross.
  • David BetzDavid Betz Posts: 14,519
    edited 2011-03-17 19:36
    RossH wrote: »
    Try FAT - that's what I used. But FAT32 should also work.

    Ross.

    I'm not sure how to make sure there's an MBR on the card but I tried reformatting my existing card and that still didn't help. I'll try another card.
Sign In or Register to comment.