Shop OBEX P1 Docs P2 Docs Learn Events
FastGUI SPIN 2 Address Confusion — Parallax Forums

FastGUI SPIN 2 Address Confusion

potatoheadpotatohead Posts: 10,261
edited 2019-12-08 09:14 in Propeller 2
I'm looking to move some all PASM code to SPIN+PASM and I am having trouble locating a file at a specific address in hub RAM.

Simple code attached.

I thought I could do this:
CON
		
  bitmap	= $1_0000	'bitmap buffer start

Then some SPIN code:
PUB Main | x
    clkset(_clkmode, _clkfreq)
    waitcnt(clkfreq + cnt)

    coginit(HDMIDSP,@pgm_hdmi, 0)
    repeat 500
	x := x + $10
    'code added here adds to bitmap address

Follow that with PASM I want to launch in various cogs:
' HDMI Display Bitmap @ bitmap
DAT             org	

pgm_hdmi        setcmod #$100                   'enable HDMI mode
                drvl    #7<<6 + hdmi_base       'enable HDMI pins
                wrpin   ##%001001<<8,#7<<6 + hdmi_base  'set 1 mA drive on HDMI pins

                setxfrq ##$0CCCCCCC+1           'set streamer freq to 1/10th clk (25 MHz)

                rdfast  ##640*480/64,##bitmap   'set rdfast to wrap on 300KB bitmap

[some code omitted for clarity]

m_vi            long    $70810000 + hdmi_base<<17 + 640         'visible
m_rf            long    $B0820000 + hdmi_base<<17 + 640         'visible rfbyte luma8

i               long    1
hsync0          long    1
hsync1          long    1

'end of cog driver code

Followed by data in higher RAM:
orgh    $2000
		byte	$DE, $AD, $BE, $EF


                orgh    bitmap - $436    'justify pixels at $1000, pallete at $1000-$400
                file    "bitmap.bmp"

Turns out, the actual location in the HUB of the $DEADBEEF targeted at $2000 above is $2574, and that varies depending on how much SPIN I write in main. It does not appear to be affected by code added in the DAT section containing PASM. <-- This is wrong. I just added another PASM DAT block, and the address target $2000 did move.

(Thanks for the awesome listing file feature Eric! It reloads on recompile and keeps cursor / display window position. Love it. It's the little things that help.)
02574                 | 
02574                 | 		orgh    $2000
02574     DE AD BE EF 
02578     00 00 00 00 
0257c     00 00 00 00 
02580     00 00 00 00 | 		byte	$DE, $AD, $BE, $EF

How can I specify where I want something in the HUB? I gotta be missing something basic. What is it? I have messed with this for a little too long.


Comments

  • potatoheadpotatohead Posts: 10,261
    edited 2019-12-08 09:32
    Well dang! I just looked at the GUI stderr and there it is:

    orgh with explicit origin does not work if Spin methods are present

    That's the thing I'm missing. Just didn't see it. That light orange color went right past me. I added another file, and saw two of those messages. Guess that's what it takes late at night to get my attention!

    Any workarounds?

    Second question @ersmith : Will this be supported eventually?
  • RaymanRayman Posts: 14,646
    edited 2019-12-08 12:23
    I ran into this in my 90’s 3D demo, now in spin...

    I’m trying to remember... think just pass @ or @ @ to assembly... one of those...
  • potatohead wrote: »
    Well dang! I just looked at the GUI stderr and there it is:

    orgh with explicit origin does not work if Spin methods are present

    That's the thing I'm missing. Just didn't see it. That light orange color went right past me. I added another file, and saw two of those messages. Guess that's what it takes late at night to get my attention!

    Any workarounds?

    The best solution is to replace
       orgh $2000
       stuff
    
    with
       orgh
    my_base_addr
       stuff
    
    and then everywhere you used to use "$2000" use "@my_base_addr". You may also need to change things like "$1FFF" to "@my_base_addr - 1" and such as well.

    This is much cleaner because now your object is relocatable.

    The other alternative, which I would strongly suggest avoiding unless you really need it, is to remove the FILE data from your code and instead to use loadp2 to load your data file directly at $2000, something like:
       loadp2 @0=myprog.bin,@2000=data.bin
    
    That will only work if your program plus all the libraries will fit in the memory below $2000.
    Second question @ersmith : Will this be supported eventually?

    Short answer: probably not.

    Longer answer: besides the technical difficulties involved in trying to support letting the user put data wherever they want, regardless of what the Spin compiler is doing with memory, what does it even mean if two objects both try to do "orgh $2000" simultaneously?

  • potatoheadpotatohead Posts: 10,261
    edited 2019-12-08 17:39
    Thanks Eric.

    For sake of discussion, the answer to the question could be as simple as, "Error: duplicate orgh found"

    And does that imply a structure, or process not currently part of FastGUI?

    Just wanting to understand those difficulties.

    Secondly, it's not an object I'm wanting to declare. It's data.

    Should I then pack the data in before the objects? Your workaround would be valid then, because the references to the data would be present prior to the objects needing them. This is not as readable, but... :smiley:

    Or, can I make a sort of data object? Maybe that's more readable.

    This one may come up from Prop Tool users, who would do this kind of thing once they see "orgh" Well, I did!

    The general idea here is Spin 1 sort of ignored higher memory. Declaring buffers and such up there made sense. We didn't have a big PASM model and no orgh... Would be super nice to drop some data somewhere.

    Thanks again. In every other way I've used it so far, FastGUI is exemplary. Great work. I'm just whining. No worries.



  • potatoheadpotatohead Posts: 10,261
    edited 2019-12-08 17:30
    Rayman wrote: »
    I ran into this in my 90’s 3D demo, now in spin...

    I’m trying to remember... think just pass @ or @ @ to assembly... one of those...

    Rayman, I'll go give your code a look. Was attempting to do the usual, one file Spin thing. Looks like I still can, but need to think about it differently.

  • evanhevanh Posts: 15,916
    Did Spin1 really have something for this? Isn't ORGH new to Spin2?


  • potatoheadpotatohead Posts: 10,261
    edited 2019-12-08 18:11
    No, it didn't. I made an edit to my post just a while ago.

    Really, what we did with Spin 1, when working this way, was to pass addresses into assembly programs, and then abuse high memory with buffers, dynamically generated data, whatever. We did just declare those.

    Orgh is new, and this seems an obvious use, given we now can make PASM outside the COG scope.

    I'm not saying it should be done. I am saying it would be awful nice if it could. I feel it's a logical extension of how hubexec allows one to work in RAM. I could just make this project a PASM one too.

    I do not want to use the load at address facility Eric mentioned. PITA, but I'm glad that is there.

  • evanhevanh Posts: 15,916
    Might need to have fancier loaders to handle that, otherwise you're going to end up with a lot of padded binaries.

  • That's fine :smiley:

    Padding was expected.
  • evanhevanh Posts: 15,916
    I meant everyone's code. That's not exactly ideal left that way.
  • potatoheadpotatohead Posts: 10,261
    edited 2019-12-08 19:17
    Depends doesn't it?

    And there is one trade-off right there! I really was not thinking about the mix 'n match aspect in all of this. Eric is right. If people sprinkled them throughout...

    Messy. That's helping me understand. Appreciated.

    But, it seems SO easy in the "stuff it in one file" and go scenario too. Ah well, everything costs something and doing this appears increasingly expensive, unless it's confined to a very narrow set of use cases, and doing that is expensive too.

  • evanh wrote: »
    Might need to have fancier loaders to handle that, otherwise you're going to end up with a lot of padded binaries.
    I have a question. So one option being talked about is just assuming memory is available, and hardcoding a constant address. Which can easily be missed especially if buried. And if forgotten about, totally tramples the idea of structured, modular programming.

    Another is to declare a variable array, string, or series of bytes as a data block. The only downside is the binary image has this variable data pre-initialized. So in other words the binary reflects the total memory being used.

    Is there a third option to tell the linker to reserve these memory blocks at the end, while still advancing the orgh address, so to say that this can be snipped off, but these memory areas are definitely in use?

    If we're taking 512 kB, is this really an issue though?
  • There is no linker in FastGUI.
    And if forgotten about, totally tramples the idea of structured, modular programming.

    Definitely. Original intent was "one file" just write it in much the same way one would do with PASM. Really, it was just about including data to be located at a specific place in RAM, ideally above all the active program.

    We can do the third option pretty much now. Just specify the address and go. That's about buffers and such, not so much locating bits of code all over the place.
  • Cluso99Cluso99 Posts: 18,069
    If you don’t need the data initialised, then you can use an equate at the start of you program in the CON section.
    That’s what I do to call the ROM code.
    Not sure if this helps, but it’s a better way than hard coding a constant. You can test to ensure your code is below that address.
  • Not sure I understand why the data has to be loaded at a specific hard coded address. Is there some reason my proposed solution (using a label in front of the data) doesn't work for you? I think "@picturedata" or something like that is more descriptive than "$2000" anyway.

    I guess it does mean that the data has to be initialized, which is perhaps a bit of a pain. Maybe we could create something like "res" but which is guaranteed to be after all the program and data. Would that solve your use case?
  • On code targeted by the GNU toolchains (x86, ARM, MIPS, etc), you can run
    ld -r -b myfile.bin -o myfile.o
    
    which will make an object file containing myfile.bin as data, and three symbols you can link against: _myfile_start, _myfile_end, and _myfile_size.

    From C, you can
    extern char _myfile_start, _myfile_end;
    extern int _myfile_size;
    
    uint8_t *get_myfile()
    {
        return &_myfile_start;
    }
    
    int get_myfile_size()
    {
        return (int)(&_myfile_size);
    }
    

    Is there possibly something similar that could be done from FastGUI? Add a "myfile.bin" to a project and have _myfile_start become an available global symbol?
  • potatoheadpotatohead Posts: 10,261
    edited 2019-12-08 22:56
    I guess it does mean that the data has to be initialized, which is perhaps a bit of a pain. Maybe we could create something like "res" but which is guaranteed to be after all the program and data. Would that solve your use case?

    Yeah, it's initialized data, and some of it isn't intended to be mutable. Media assets would be the main use case. Pictures, sounds, scores. Later, with bigger programs, external RAM, SD storage, it either won't come up, as those things will be dynamically loaded into defined buffers, or will be referenced where they are.

    This is a simple, stupid case. Maybe we should not worry about it.

    All I really want to do is say, "put this blob right here." And using orgh for that, in all the other multi-file, reuse cases, makes for a big potential mess. Bummer. I totally don't want to be the one who started that.

    Maybe the loader option is easy?

    I think the sticking point is making a plan for the RAM, PASM style.

    Maybe just me too. Wanting things to be too lean. I need to explore all the options.
  • potatohead wrote: »
    I guess it does mean that the data has to be initialized, which is perhaps a bit of a pain. Maybe we could create something like "res" but which is guaranteed to be after all the program and data. Would that solve your use case?

    Yeah, it's initialized data, and some of it isn't intended to be mutable. Media assets would be the main use case. Pictures, sounds, scores. Later, with bigger programs, external RAM, SD storage, it either won't come up, as those things will be dynamically loaded into defined buffers, or will be referenced where they are.
    OK. I'm still not seeing the difficulty with writing this as:
        org 0
        '' PASM COG code here
    
        orgh
        '' HUB data here
    myinitdata
        file "something.bin"
    
    This puts the initialized data into HUB RAM. The PASM program can access it at "@myinitdata". Everything can be in one .spin2 file. Am I missing something?

  • potatoheadpotatohead Posts: 10,261
    edited 2019-12-08 23:18
    Maybe not. Hope not. Lol

    When I get a chance, I will do exactly that.

    For done reason, I thought it did not work for me, but I could be wrong, did not actually do that, or did it incorrectly too.

    We will know in a bit.



  • Is there possibly something similar that could be done from FastGUI? Add a "myfile.bin" to a project and have _myfile_start become an available global symbol?

    Well, we don't have "projects" in FlexGUI. You can certainly include binary data into a .spin file though via:
    DAT
        ORGH
    _myfile_start
        file "myfile.bin"
    
    or you could do the same in C with:
    __pasm {
    _myfile_start
        file "myfile.bin"
    }
    

    For example, a program to print itself is:
    // name this program "foo.c"
    #include <stdio.h>
    
    __pasm {
    _myfile_start
        file "foo.c"
    }
    
    void main() {
        printf("%s\n", &_myfile_start);
    }
    
  • I'm on travel, and had some P2 time this evening.

    Eric, this works. It's not actually doing what I would prefer, which is to just put a dataset at an address. But, I also don't care. What I can do is get it into the P2, and just move it, should that address matter for some reason or other, or work with it where it is.

    I'm happy. No worries, though I do think if we can just declare some buffer in upper memory for some reason, we should also just be able to put data there for some reason. Either scenario could require a refactor should the code find it's way into some other code body. I also think we've got a zillion other worries that are more important too. Thanks to the people who explained things to me.

    On another note, I've got an HDMI TV here that I cannot reliably drive. I think I'm going to maybe start a thread where we can post displays and what worked.

Sign In or Register to comment.