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

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

1117118120122123

Comments

  • con
    
        rh_header_s(byte length, ...
                    byte dest, ...
                    byte src, ...
                    byte flags )
    
        control_s(  byte type, ...
                    byte class, ...
                    byte cmd )
    
        msgq_s( rh_header_s header, ...
                control_s   ctrl, ...
                byte        payload[32-4-3], ...
                byte        slot_in_use )
    
    
    obj
    
        ser:    "spin/SmartSerial"
    
    
    dat
    
        name    byte    "Testing testing 1 2 3", 0
    
    
    pub main() | msgq_s test1, b
    
        ser.startx(63, 62, 0, 2_000_000)
    
        test1.header.length :=  6+strsize(@name)
        test1.header.dest :=    $04
        test1.header.src :=     $01
        test1.header.flags :=   0
        test1.ctrl.type :=      8
        test1.ctrl.class :=     $de
        test1.ctrl.cmd :=       $ad
    
        ' fill payload array: method 1
        bytemove(@test1.payload, @name, strsize(@name) <# 25)
    
        ' fill payload array: method 2
    '    repeat b from 0 to strsize(@name)-1
    '        test1.payload[b] := byte[@name][b]
    
        ' hexdump of structure memory
        repeat b from 0 to 7+strsize(@name)-1
            ser.hex(byte[@test1+b], 2)
            ser.tx(" ")
    ' results in 1B 04 01 00 08 DE AD >20< 54 65 73 74 69 6E 67 20 74 65 73 74 69 6E 67 20 31 20 32 20 33
    ' the byte surrounded by > < is extra, and may change
    
    ' here's the code that _would_ appear afterwards:
    ' radio.tx_payload(@test1, 7+strsize(@name) ) ' this would just copy the data in the test1 structure to the packet radio's FIFO, to be transmitted
    

    Hi Eric, Ada,

    In the above snippet (distilled down from a project I'm working on that sends packets over wireless links using nRF24L01+ or other similar chips), I'm filling a structure with data (well, manually populating each member here, anyway) but am having an issue when sending this structure as a packet of data.
    In my original code I was sending the structure with a string copied to the payload array member, which mostly worked, but the last character of the payload was always getting cut off on the other end. Eventually I traced it to the transmitter, before it reached the radio. In memory, it looks like there's an unexpected gap between the ctrl.cmd member and the payload member array (shown in the above with the hexdump). It seems like this might be related to long-alignment, since the gap disappears if I add another member to the control_s structure. Can you confirm this is expected? If it is, do you have any advice on ways to write the closest equivalent of the above (pretending the last line with tx_payload() that's commented out actually does something)?

    Also, is a call to bytemove the recommended way to copy one structure to another right now? In this application, there's a function that queues messages to be sent by copying them into an available slot - it takes a pointer to a structure as the param, then copies it with bytemove to the queue. This seems to work fine.
    BTW this is with both P2 bytecode (Nu) and PASM2.

    Thanks!

  • ersmithersmith Posts: 6,068

    @avsa242 Unfortunately as it stands now structs are always padded out to longword boundaries. That means you'll get a byte inserted at the end of your control_s structure. I don't know if this is a conflict with PNut or not. Chip is still revising structures, so we'll have to see how that settles down.

    In the meantime, for transmissions or other things where the in-memory format has to match exactly you'll have to use arrays, or else manually transmit any shorter structs.

    For copying structures, I think the new COPY method is currently the way to do this, but again, the struct stuff seems still to be churning and this may get replaced by an operator. BYTEMOVE should always work though.

  • Gotcha, thanks!

  • I am having an issue adding libraries. Attempting to add the simpleide libraries because when I open up the examples I see
    that the icon for flexprop is there. Assumption that flexprop will run these. Am I missing something.
    Thanks in advance
    Martin

  • evanhevanh Posts: 16,029

    @pilot0315 said:
    I am having an issue adding libraries. Attempting to add the simpleide libraries because when I open up the examples I see that the icon for flexprop is there. Assumption that flexprop will run these. Am I missing something.

    Spin code is generally compatible. What problem is occurring?

  • evanhevanh Posts: 16,029

    Got a question myself ... I'm trying to use unsupported instructions, namely CALL, by handcrafting them. Anyone know a way to specify a PC relative offset in inline Pasm2, within FlexC?

    I currently have this:

            long    0x3db00000 | 9    // IF_NC CALL #crc_check
    

    but would like to replace the fixed 9 with a compiler calculated offset based on the crc_check label that is ten longwords later.

  • ersmithersmith Posts: 6,068

    @pilot0315 said:
    I am having an issue adding libraries. Attempting to add the simpleide libraries because when I open up the examples I see
    that the icon for flexprop is there. Assumption that flexprop will run these. Am I missing something.
    Thanks in advance
    Martin

    What do you mean by "adding libraries"? Flexprop doesn't really have anything for libraries, at least not like simpleide does, and it certainly won't be able to use the simpleide libraries.

  • ersmithersmith Posts: 6,068

    @evanh said:
    Got a question myself ... I'm trying to use unsupported instructions, namely CALL, by handcrafting them. Anyone know a way to specify a PC relative offset in inline Pasm2, within FlexC?

    I currently have this:

          long    0x3db00000 | 9    // IF_NC CALL #crc_check
    

    but would like to replace the fixed 9 with a compiler calculated offset based on the crc_check label that is ten longwords later.

    You can write CALL in inline assembly, the reason the documentation say it's "unsupported" is that trying to call functions outside of the inline assembly is undefined. But if you only call things within the same block I think it should work.

  • evanhevanh Posts: 16,029
    edited 2024-09-26 01:27

    Huh, typical, I never tried ...

    Yep, works just fine. :) I've hand coded the RET instruction, ie: long 0xfd64002d, because I know that would be replaced with a JMP if I used the RET mnemonic.

  • @ersmith

    Since there is not an actual list that I can find that tells me what is each of the files that are accessable under "include", I assume that they are libraries because they start with
    "lib" and I am having issues with the simpleide, I wanted to port over all of my code. First of all I am interested in the counters.
    Having opened up each of them I may have missed it.
    Is there a list of what is in each one so as to make it easier to navigate.?

    Thanks.
    Also I am getting used to your gui. Pretty good. I like it so far much easier to navigate.
    Thanks
    Martin

  • ersmithersmith Posts: 6,068

    @pilot0315 There's no need to do anything to add any of the "libraries" or include files under the "include" directory, all of those are automatically accessible by FlexProp. There isn't much documentation about the libraries, I'm afraid, other than what's available under the Help menu item. The BASIC language is the best documented; for Spin2 and C we rely more on Parallax's documentation.

  • @ersmith

    Sorry for the late reply.
    Thanks for the information.
    I found that SimpleIde does not give one any libraries that are full access to the counters in the P1. So I am
    attempting to write from scratch that access. Any suggestions would be appreciated.
    Is that possible with FlexProp?
    Thanks.
    Martin

  • evanhevanh Posts: 16,029
    edited 2024-10-02 11:13

    Access is not really a valid term when hitting the metal in a system that doesn't have memory protection. You just use it.
    The main doc for Prop1 counters is here - https://www.parallax.com/package/an001-propeller-p8x32a-counters/

    EDIT: They're pretty open ended in what they can be used for. Do you have a particular use case?
    I've written one program for the Prop1, it used the counters as DACs. Wiring was simple, as was the code. The Duty counter mode naturally produces PDM pulses on the pin it outputs to. PDM is ideal switching mode for an R-C filter.

  • ersmithersmith Posts: 6,068

    @pilot0315 said:
    I found that SimpleIde does not give one any libraries that are full access to the counters in the P1. So I am
    attempting to write from scratch that access. Any suggestions would be appreciated.
    Is that possible with FlexProp?

    As Evan said, the P1 counters are just registers (named _FRQA, _FRQB, _PHSA and _PHSB in FlexC, and aliased to FRQA, FRQB, PHSA, and PHSB in propeller1.h. There are some simpletools functions to manipulate them, e.g. pulse_in(), pulse_out(), rc_time().

    You could also look in the OBEX to see if there are objects that do what you want. Spin objects can be used directly from FlexC, so there's no need to port them (usually).

  • My Spin P1 programs work with the counters. Based on the tutorials in the P E Kit. Getting them to work in the PropIde C environment for some reason is a No Go.
    I will post the example soon.
    Do not understand why the examples y'all sent me are not working. Again I have tried in both gui's .
    I must be a dummy :D
    Got some family issues right now. Get back to y'all next week.
    Thanks
    Martin
    Maybe I will get lucky and stumble on the fix my self. B)

  • evanhevanh Posts: 16,029

    I assume the P E Kit is for Spin. You're probably a lot better off sticking with Spin. C isn't a particularly easy language to grok. And the build environments are arcane, even with the assistance of an IDE.

  • evanhevanh Posts: 16,029
    edited 2024-10-04 10:21

    Uh-oh, I just went to compile the newly rebuilt driver for the first time and have got a very unexpected blocker:

    error: Unable to combine types
    /home/evanh/hoard/coding/include/filesys/sdfatfs/sdmm.cc:76: error: syntax error, unexpected '*', expecting ',' or ';'
    

    The line in question is this:

    extern register uint32_t 
        *r_param1, *r_param2, *r_param3, *r_param4,
        *r_param5, *r_param6, *r_param7, *r_param8;
    

    Doing that is fine in the stand-alone development code, so I'm guessing I've struck a limitation of the way the driver gets incorporated.
    Suggestions on a fix? Move that line outside the driver maybe?

    EDIT: Never mind. Found it. A missing semi-colon at the first enum{}.

  • evanhevanh Posts: 16,029
    edited 2024-10-25 12:28

    Huh, that's amusing. When I added the clock divider argument to the disk_setpins() function of the driver I'd messed up the declared argument order of _vfs_open_sdsdcard() in include/sys/vfs.h ... but since the data types are all the same and the coded argument order matched with the top level use order there was no error and no bug. The code compiled correctly anyway.

    Basically, because I wrote both ends I knew the correct order. The fact that the interface declaration was wrong was irrelevant.

  • RaymanRayman Posts: 14,755
    edited 2024-11-01 22:24

    Think maybe some kind of bug in FlexProp C when calling a function in Spin2 file.
    So, made this in Spin2 file:

    PUB Root(s):r
    return SQRT(s)

    if call like this it works:

    g = (foreg * foreg * a) + (backg * backg * (256 - a));        
    g = vga.Root(g) >> 4;
    

    if call like this it doesn't:
    g = vga.Root((foreg * foreg * a) + (backg * backg * (256 - a))) >> 4;

  • ersmithersmith Posts: 6,068

    @Rayman said:
    Think maybe some kind of bug in FlexProp C when calling a function in Spin2 file.
    So, made this in Spin2 file:

    PUB Root(s):r
    return SQRT(s)

    if call like this it works:

    g = (foreg * foreg * a) + (backg * backg * (256 - a));        
    g = vga.Root(g) >> 4;
    

    if call like this it doesn't:
    g = vga.Root((foreg * foreg * a) + (backg * backg * (256 - a))) >> 4;

    I need some more context. What are the types of the variables g, foreg, backg, and a? Are they locals or globals? Is the example inside a function, and if so, what does that function look like? What values to the variables have when you find the incorrect values... is it possible they are overflowing?

    If I just write the expressions above using local integer variables, the two expressions produce the same assembly code, so they will do the same thing. If there's a bug, it's somewhere in the interaction of the expression and the environment.

  • ersmithersmith Posts: 6,068
    edited 2024-11-02 02:03

    Incidentally, FlexC has a __builtin_sqrt function which does the same thing as the Spin2 SQRT.

  • RaymanRayman Posts: 14,755
    edited 2024-11-02 02:42

    Ok, here's the full source (and then some, hopefully)...

    Main file is McuFontTest.c

    Is that built in sqrt function documented somewhere. Guess I should have looked...

  • ersmithersmith Posts: 6,068

    Ah, I think I see the problem. foreg and backg are floats, so the expression (foreg * foreg * a) + (backg * backg * (256 - a)) is a float. If you pass that to a Spin2 function, it won't convert it to integer first, it'll just pass the raw bits of the floating point number, which Spin2 SQRT will treat as an integer and give you the wrong answer. However, if you assign it to g first then it will be converted to integer (since g is an int). You could get the same result by casting to (int) in the call to vga.Root.

    Not a compiler bug, just an unexpected interaction between languages.

  • RaymanRayman Posts: 14,755

    Hmm… ok thanks , makes sense

    Would the Spin2 fsqrt have worked then?

  • evanhevanh Posts: 16,029

    Sounds like it should. Give it a try. You'll need to change g into a float though.

  • ersmithersmith Posts: 6,068

    @Rayman said:
    Hmm… ok thanks , makes sense

    Would the Spin2 fsqrt have worked then?

    Yes, but for floats you'd be better off using the standard C sqrt function (defined in <math.h>).

  • ersmithersmith Posts: 6,068

    I've pushed the new file system code to github. There are two main changes:

    (1) The off_t type used for seeking and for reporting file size is 64 bits now, so files can be larger than 2GB;
    (2) Filesystems now use a regular vfs_file_t* pointer (i.e. a C FILE*) for I/O. This means that, in principle, a FAT file system or littlefs file system may be made to work on any underlying device, as long as it is exposed as a regular file. It also means that we can do loopback mounts, e.g. mounting a FAT file system contained in a HOST file system file.

    The code is still a mess and the filesystems still have some built in assumptions (so e.g. mounting a littlfs on top of the SD card flash probably won't work yet, because the flash blocks are bigger than littlefs blocks). It also needs a lot of documentation. Hopefully there won't be any user visible changes (other than the new APIs for mounting filesystem on file).

  • Wuerfel_21Wuerfel_21 Posts: 5,106
    edited 2024-11-03 16:26

    4064 bloat bytes for a read-only filesystem :-1:

    EDIT: Down to 3976 with a one-liner PR

    EDIT 2: It's actually less bad when the full RW configuration is used. 3544 bloat bytes (with the aforementioned fix)

  • Looking at it, using a regular file handle as an abstraction over block storage devices is just a terrible idea (UNIX brain poisioning...). They are just not the same and the adapting layers to make it work are stupid. There should be a separate type for block device handles (that in turn could be backed by a file still if that feature is needed). That's less wasteful adaptering code, less 64-bit types, less bad in general.

  • Wuerfel_21Wuerfel_21 Posts: 5,106
    edited 2024-11-03 17:03

    Also there's still that getc/putc buffering mechanic that really ought to get thrown out. (I just noticed it allocates 1024 (!!!) heap bytes per file (128 on P1 - that's twice as bad proportionally!) that get used only when getc/putc are used and are more-or-less pointless if the actual FS has its own buffer - there may be a minor perf difference, but do you really care when you're using getc/putc? And if you actually did care you really wouldn't want to read the file on the same cog as you're processing, anyways.)

    EDIT: Actually, at least for fatfs, the putc buffering will make the perf worse if it ever gets out of alignement - because reading/writing an unaligned 1K involves two single block writes and 2 memcpy.

    The longer I stare into the VFS the more it stares back.

Sign In or Register to comment.