Shop OBEX P1 Docs P2 Docs Learn Events
flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler - Page 47 — Parallax Forums

flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler

14445474950117

Comments

  • Thanks for the explanation. I would be concerned about random data matching the tag and valid heap addresses. However, I suppose the probability is quite low.
  • Dave Hein wrote: »
    Thanks for the explanation. I would be concerned about random data matching the tag and valid heap addresses. However, I suppose the probability is quite low.
    Also, the only problem that could cause is blocks of memory that are never freed even though they are not actually in use. Given the low probability that probably doesn't matter much unless the block happens to be large.

  • @ersmith Memory map?

    I asked this a while ago but I don't think it was ever answered. If I don't use the heap manager at all, how can I identify free areas of memory I could use for my own allocator after my program has loaded? Is there some "top of code" symbol I can use? Also, where is the stack placed? I know I could just declare a huge array in my code but I'd rather not do that.
  • ersmithersmith Posts: 5,918
    edited 2020-04-23 12:12
    There's a message on the previous page giving the memory map. I'll put it here as well:
    ersmith wrote: »
    David Betz wrote: »
    What is the memory map used by fastspin? Where is code loaded? Where is the stack placed? How can I know what memory is still available after loading a program?

    There is a command line switch (-H) to specify the starting address, but the default is 0. First comes whatever COG code is needed (very little for the P2, just enough to bootstrap). Then comes the hubexec code. Then comes the data (including all variables). The heap (the size of which is given by HEAPSIZE) is part of that data. After that comes the stack, which grows upwards towards the end of memory. You can access the stack pointer by the variable "sp" in inline assembly, or by calling __getsp() in a high level language. The stuff above that is "free" (as long as you don't need a deeper stack, of course).

  • Also, if you are trying to write portable C code that will work on all systems then you'll have to either use malloc() or a large fixed size array to get your "free areas of memory". (sbrk() would be an alternative for Unix, but that isn't standard C).
  • ersmith wrote: »
    There's a message on the previous page giving the memory map. I'll put it here as well:
    ersmith wrote: »
    David Betz wrote: »
    What is the memory map used by fastspin? Where is code loaded? Where is the stack placed? How can I know what memory is still available after loading a program?

    There is a command line switch (-H) to specify the starting address, but the default is 0. First comes whatever COG code is needed (very little for the P2, just enough to bootstrap). Then comes the hubexec code. Then comes the data (including all variables). The heap (the size of which is given by HEAPSIZE) is part of that data. After that comes the stack, which grows upwards towards the end of memory. You can access the stack pointer by the variable "sp" in inline assembly, or by calling __getsp() in a high level language. The stuff above that is "free" (as long as you don't need a deeper stack, of course).
    Thanks! I must have missed that when you first posted it.

  • ersmith wrote: »
    Also, if you are trying to write portable C code that will work on all systems then you'll have to either use malloc() or a large fixed size array to get your "free areas of memory". (sbrk() would be an alternative for Unix, but that isn't standard C).
    Yes, I realize that I will have to put any heap allocation code in an OS-specific module. I don't mind doing that. In fact, I'm already doing that with junkbasic by declaring a big array in the OS-specific code and using that as my heap. I just wanted to get away from a hardcoded array size.
  • Does fastspin support this syntax for initializing union elements?
    union {
          char birthday[9];
          int age;
          float weight;
          } people = { .age = 14 };
    
  • David Betz wrote: »
    Does fastspin support this syntax for initializing union elements?
    union {
          char birthday[9];
          int age;
          float weight;
          } people = { .age = 14 };
    

    Not yet, no.
  • ersmith wrote: »
    David Betz wrote: »
    Does fastspin support this syntax for initializing union elements?
    union {
          char birthday[9];
          int age;
          float weight;
          } people = { .age = 14 };
    

    Not yet, no.
    No problem. Thanks for letting me know.

  • @ersmith I'm having a bit of a "discussion" with the garbage collector. It occasionally wants to run when I'm doing something time-critical. Is there a way to tell the GC "hold-off for just a bit"?

    Creating a bigger HEAPSIZE just kicks the can down the road, so my current workaround is to delete unused strings manually and then invoke _gc_collect() *before* entering a time-critical bit of code. But I'm thinking there is probably something more elegant.

    BTW: This compiler suite is really coming together nicely. Darned impressive effort!
  • JRoark wrote: »
    @ersmith I'm having a bit of a "discussion" with the garbage collector. It occasionally wants to run when I'm doing something time-critical. Is there a way to tell the GC "hold-off for just a bit"?
    No, because the GC only kicks in when you're trying to allocate memory and have run out; if you told it to "hold off for a bit" then the memory allocation you were trying to do would fail.

    Basically I would recommend moving any memory allocation code outside of critical regions: don't do string manipulation and such inside time critical regions. If you can't do that, try to make sure that before you enter the region there's enough available free memory, e.g. by freeing up as much as you can manually, and/or calling _gc_collect() explicitly before the critical region.

    Remember, all the GC does is look for memory that could have been freed but hasn't been yet. If you have enough memory available already, it'll never be invoked.
  • Good to know, Eric. Thanks!
  • RaymanRayman Posts: 13,900
    I seem to have a sprintf/stdio issue with latest 4.1.6...

    Getting an error in the p2asm, changing hub value for symbol: ___struct__anon_193f688200000005_sputc

    Seems this subroutine appears in two places in the assembly...
  • @Rayman: sprintf works fine from C, but it appears there's a problem calling it from Spin. Not sure how I can fix that, but I'll look into it.
  • RaymanRayman Posts: 13,900
    edited 2020-04-25 16:17
    Looks like it's not actually FastSpin.exe per se... It's something in the library...

    I just discovered I've been using the 4.0.3 library for some time and it was all good..
    But, even the 4.1.4 library has this issue.
    It's something to do with the included files.

    The old version build output ends like this:
    sprintf.c
    dofmt.c
    fmt.c
    strcpy.c
    strlen.c
    1080p_TileDriver_Test6i.p2asm
    Done.
    Program size is 422624 bytes
    

    The new version build of a similar file ends like this:
    sprintf.c
    dofmt.c
    fmt.c
    sprintf.c
    fprintf.c
    posixio.c
    dofmt.c
    bufio.c
    errno.c
    1080p_TileDriver_Test7a.p2asm
    Done.
    d:\Propeller2\2BitTiles\1080p_TileDriver_Test7a.p2asm:16109: error: Changing hub value for symbol ___struct__anon_193f688200000005_sputc
    d:\Propeller2\2BitTiles\1080p_TileDriver_Test7a.p2asm:16124: error: Changing hub value for symbol ___struct__anon_193f688200000005_sputc_ret
    

    I imagine that sprintf.c being included twice is the issue...
  • Got this trying to compile on a Mac (I'm in the process of trying to get this to compile both under FastSpin and PNut):
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2020 Total Spectrum Software Inc.
    Version 4.1.6 Compiled on: Apr 22 2020
    FemtoBasic.spin2
    error: Internal error: tried to use memory directly
  • What is the correct syntax in FastSpin to pass arguments when spawning a new Spin COG?

    Eg. suppose I want to start this Spin Method as a new COG
    PUB runmouse(xmax, ymax) | btns
            usbmouse.start(xmax, ymax)
            repeat
                btns:= usbmouse.buttons
                display[7]:= usbmouse.getxy
                ...
    
    I can't seem to simply use this syntax...
            cognew(runmouse(w, h), @mousestack)
    
    because it will never return when it tries to evaluate runmouse(xmax, ymax), resulting in it running the method synchronously from the calling COG instead of in a new COG. Are passing the SPIN parameters not supported? I do understand why this is occurring if cognew is a standard function call under the covers but I think the P1 SPIN has this capability to pass input parameters IIRC. Would this difference be documented somewhere perhaps?



  • That's exactly the syntax you need to use to start runmouse with w and h as the two parameters. You're right about it never returning though. The cognew returns as soon as the new cog begins execution, just before runmouse is actually begun. If runmouse returns (or falls through the end of the method), the new cog does an automatic self stop.
  • AribaAriba Posts: 2,682
    If this is a .spin2 file, then try:
    cogspin(16,runmouse(w, h), @mousestack)
    
    Andy
  • Thanks Andy I'll give that way a go and test it out soon...
  • Still doesn't work unfortunately. The Spin COG entry parameter passed into cogspin, cognew etc seems to want to first evaluate "runmouse(w, h)" as a normal Spin method call which just results in its execution by the calling COG. Maybe passing parameters just can't be done in Fastspin, or there is a different way to do it.
  • @Rayman: The problem is related to the libraries, but it's actually a bug in the compiler itself (in the handling of the Spin -> C interface) that's exposed by a change in the libraries. It's fixed in github now.

    @"Mike Green" : Thanks for the bug report, there was a problem with evaluating arguments of FRAC if they weren't simple variables. It's fixed in github now, I'll make a new binary release soon.
  • rogloh wrote: »
    Still doesn't work unfortunately. The Spin COG entry parameter passed into cogspin, cognew etc seems to want to first evaluate "runmouse(w, h)" as a normal Spin method call which just results in its execution by the calling COG. Maybe passing parameters just can't be done in Fastspin, or there is a different way to do it.

    I don't know what's going wrong for you, but in general fastspin does work the same way as Spin in terms of passing parameters to Spin functions in cognew. For example here's a simple program to flash 3 LEDs:
    con
      _clkfreq = 180_000_000
    var
      long stack1[16]
      long stack2[16]
      
    pub demo
      cognew(runblink(56, _clkfreq/4), @stack1)
      cognew(runblink(57, _clkfreq/10), @stack2)
      runblink(58, _clkfreq/3)
    
    pub runblink(pin, delay)
      repeat
        pintoggle(pin)
        waitx(delay)
    
    

    If "runblink()" were evaluated completely then only one LED (56) would ever toggle, since the runblink function never returns. In fact I see all 3 toggling on my board, as I would expect.

    So you're running into some other problem. Perhaps your stack isn't big enough?
  • ersmith wrote: »
    So you're running into some other problem. Perhaps your stack isn't big enough?

    Yep it's a strange one. I did consider that and had set a huge 2000 long stack just in case however the 3 called methods in the spawned COG executing my runmouse method are also very simple so shouldn't even need much stack as you can see below.

    I am running an older 4.1.0 Fastspin so that may have something to do with it and I should try a more recent version. Work fine if I don't try to pass in any xmax,ymax entry parameters but fails when I do. I wonder how best to debug... I'll try to take another deeper look tomorrow.
    
    DAT
    	orgh
    mousestack      long 0[2000]
    
    ...
    
    ' The 3 calls made from runmouse into the usbmouse object code only do this:
    
    PUB start(mx, my)
       maxx:=mx
       maxy:=my
       par_head:=0
       par_tail:=0
       cognew(mouseinit, @usbstack)
    
    PUB getxy | x,y
      return mousey << 16 + mousex
    
    PUB buttons
      return mouse buttons
    
    
  • roglohrogloh Posts: 5,171
    edited 2020-04-27 07:13
    Definitely hangs if you pass parameters. I reduced the spawned SPIN code in the runmouse method to bare bones which is this...
    PUB runmouse(xmax, ymax)
       repeat
    
    And I added an LED toggle after the cognew command. It never lights up. It will light if I move the "dirb |=..." line to be before the cognew.
            cognew(runmouse(w,h), @mousestack)
            dirb |= (1<<(58-32))
    
    If I get rid of the arguments in the runmouse method entry point, it works and the LED lights up. When it fails I also increased the stack of the caller to 2000 longs and the mousestack to be 2000 longs. Neither helped. I will have to try a newer Fastspin to see if that helps.

    Update: @ersmith After a bit more testing I think I found an issue. The Spin code being spawned must come AFTER the method that spawns it in the source file. Once I moved the spawned SPIN code to come after the caller, it worked. Prior to this it was defined before the calling method in the file. So it seems to be address dependent. Does the Fastspin code compile differently based on the order of the methods in the code?
  • Ok try out this with your test code slightly modified Eric. It will show you the problem. Then move runblink back to be after demo method in the file and it will work differently (this is with Fastspin 4.1.0).

    con
      _clkfreq = 180_000_000
    var
      long stack1[16]
      long stack2[16]
      long stack3[100]
    
    pub start
      coginit(cogid, demo, @stack3)  
    
    pub runblink(pin, delay)
      repeat
        pintoggle(pin)
        waitx(delay)
    
    pub demo
      cognew(runblink(56, _clkfreq/4), @stack1)
      cognew(runblink(57, _clkfreq/10), @stack2)
      runblink(58, _clkfreq/3)
    
    
  • You've found an interesting bug there, @rogloh . Not only is it order dependent, but also depends on the function not returning a value. Thanks for the bug report, I'll get a fix for it soon. In the meantime I think you can work around it by adding "return 0" to the end of any function that's being coginit'ed (even if it's got an infinite loop and will never hit the return). The bug is a side effect of an optimization for handling Spin functions that have no return value but are later used in an expression. It causes the coginit to no longer be recognized as a "special" Spin coginit.
  • roglohrogloh Posts: 5,171
    edited 2020-04-27 12:27
    No worries, and thanks for figuring out what was going on internally to cause it so that you can ultimately solve it.

    A couple of weeks back I encountered other behaviour that again looked potentially like a different Fastspin bug with memory layout but it disappeared when I moved around something else I considered totally unrelated. Then once it worked I just moved on from there so unfortunately I didn't try to nail it down at the time or collect any details. If I see it again I'll definitely try to get more information and let you know. It could still have been my own bug somehow but I recall it was highly suspicious at the time. I'll need to hit it again before I know what it was.
  • Cluso99Cluso99 Posts: 18,069
    Eric,
    I posted this on the Flexgui thread - you may have missed it

    Eric,
    I just tried compiling my Monitor Demo in spin2 with Fastspin 4.16.

    It does not like the "mon." prefix in the pasm operands. I presume you've not got around to this yet.
    OBJ
        mon : "RamMonitorEqu"           ' "RamMonitorEqu.spin2"     register & call equates
    .....
    DAT
    entry       mov         mon.bufad,        ##mon.BUF     ' locn of hub buffer for serial routine 
    
    Code is posted here
    forums.parallax.com/discussion/171502/p2-replacing-the-rom-monitor-debugger-and-calling-from-spin-or-pasm
Sign In or Register to comment.