Shop OBEX P1 Docs P2 Docs Learn Events
This shouldn't work — Parallax Forums

This shouldn't work

rjo__rjo__ Posts: 2,114
edited 2019-03-26 03:18 in Propeller 2
'Hack  from one of Chip's example 
'Sends  any received characters from PST back to PST at 3,000,000 baud 

CON  'Baud and pin settings
        SYS_CLK = 80_000_000
        BAUD_RATE = 3000000

        RX_PIN = 63
        TX_PIN = 62
        
dat             org
                hubset #$FF
                wrpin pm_tx,  #TX_PIN      'set asynchronous tx mode in smart pin 
                wxpin bitper, #TX_PIN      'set tx bit period
                wrpin pm_rx,  #RX_PIN      'set asynchronous rx mode in smart pin 
                wxpin bitper, #RX_PIN      'set rx bit period
                or dirb, #TX_PIN
                or dirb, #RX_PIN 
              

       
.recv		
	        rdpin	y,#RX_PIN		'get data from rx pin
		shr	y,#32-8
.send           wrpin y,#TX_PIN  'send back received character
                jmp     #.recv        


pm_tx           long    %1_11_11100_0000_0000_00_0_0000000000000        'async tx byte mode
pm_rx           long    %1_10_11110_0000_0000_00_0_0000000000000        'async rx byte mode
bitper          long    SYS_CLK/BAUD_RATE                       'number of clocks per bit period, 3..65536
x               long    0
y               long    0


serial at 3MBaud in 4 actual lines of code...wtf?
no ptest or anything:)

BUT that isn't what gets me... what get's me is... (and thank you to Ozpropdev for getting this into my brain):
dat  orgh
            
      file "rjoVGA_640_x_480_8bpp.obj"

      file "simpleserialecho.obj"

This actually works... go figure.


but of course this doesn't work:


DAT orgh
file "simpleserialecho.obj"
file "rjoVGA_640_x_480_8bpp.obj"


As an ex-FBI director recently said...

There are lots of questions.

Rich


Comments

  • evanhevanh Posts: 15,126
    edited 2019-03-26 06:33
    That source code at the top certainly doesn't work. It's broken in many places. The config bits are way off, all three lines. WRPIN in the echo loop doesn't transmit data, it reconfigures the pin. And yes, without a TESTP on the receive, the transmit would be sending out continuous nulls.

    Here's a working version: (reduced to 2 Mbaud for my system)
    'Hack  from one of Chip's example 
    'Sends  any received characters from PST back to PST at 3,000,000 baud 
    
    CON  'Baud and pin settings
            SYS_CLK = 80_000_000
            BAUD_RATE = 2000000
    
            RX_PIN = 63
            TX_PIN = 62
            
    dat             org
                    hubset #$FF
                    wrpin #%01_11110_0, #TX_PIN
                    wrpin #%00_11111_0, #RX_PIN
                    wxpin asynconfig, #TX_PIN
                    wxpin asynconfig, #RX_PIN
    		dirh #TX_PIN
    		dirh #RX_PIN
    
    .recv
    		testp	#RX_PIN		wz
    if_z	        rdpin	y,#RX_PIN		'get data from rx pin
    if_z		shr	y,#32-8
    if_z		wypin	y,#TX_PIN		'send back received character
    		jmp	#.recv
    
    
    asynconfig	long	round(SYS_CLK * 64.0 / BAUD_RATE)<<10 + 7	'bitrate format is 16.6<<10, 8N1 framing
    x               long    0
    y               long    0
    
    EDIT: Updated asynconfig to use floating point so it's not limited to 32-bit maths
  • evanhevanh Posts: 15,126
    Ah, I've discovered Pnut requires all components of a constant to be explicitely cast as floats to use them that way. I've been using unique Fastspin features I see.

    So, universal arrangement should be
    asynconfig	long	round(float(SYS_CLK) * 64.0 / float(BAUD_RATE))<<10 + 7	'bitrate format is 16.6<<10, 8N1 framing
    
    
  • rjo__rjo__ Posts: 2,114
    :)

    tanks

    … I've spent the last few days discovering that I removed a jumper from all but one of my Propcams… and that is why nothing worked. I don't know how I am going to debug my brain. What I currently do is play sudoku and if I don't win I either take a nap or watch Fox business until I can win at sudoku... but I did that and still wasted two days looking in all the wrong places to figure out my issue.


    This is a question straight out of my mythical autonomous wheelchair project:


    I know how to use a serial line to load code into the lut of a running cog…but once I do that how do I change to lut exec to actually execute from there?

    My code in cogexec should end with?







  • Cluso99Cluso99 Posts: 18,066
    Use setq2 and rdlong to load lut from hub and then jump to it.
  • RaymanRayman Posts: 13,800
    Hey, I didn't realize we could load up .obj files with the file directive!
    That's pretty useful actually. The namespace gets crowded with big codes...
  • evanhevanh Posts: 15,126
    ORG becomes a vital part of using lutexec. It acts mostly same as cogexec except it obviously begins at $200. You use ORG $200 or similar to tell the assembler that the following source code is to be treated as if it were in lutram, even though it is built as part of hubram. Then, because of the ORG directive, only after you've copied it into lutram will it be usable.

    Make sure the target copying address matches the specified ORG address. As Cluso mentioned, using SETQ2 is the way to do the copying. Eg:
    '-------- Copy lut code into position --------
    		setq2	#(LUT_end - LUT_code - 1)	'copy length, in longwords
    		rdlong	0, ##@LUT_code			'the "0" is lutRAM zero, or $200 in program memory map
    
    ....
    
    
    ORG  $200					'longword addressing
    '*******************************************************************************
    '  LUT Code  (Has to be copied from hubram to lutram)
    '*******************************************************************************
    LUT_code
    
    .....
    
    LUT_end
    FIT  $400
    
  • rjo__rjo__ Posts: 2,114
    I don't think I understand that or it isn't exactly an answer to what I am asking.

    Either way... time for a drink!!!


    Thanks
  • evanhevanh Posts: 15,126
    ORG, true on all platforms, doesn't tell the tools where the following is initially loaded to but rather what address you are wanting it to be treated as.

    So, it's up to you to make sure the ORG'd code/data actually gets placed in the desired location at run time.

    It maybe that the loaded address and the assembler ORG directive are the same address, in which case there is nothing to copy, but with something like lutram you can be sure you'll be needing to do the copying within your program.

  • rjo__ wrote: »
    :)

    tanks

    … I've spent the last few days discovering that I removed a jumper from all but one of my Propcams… and that is why nothing worked. I don't know how I am going to debug my brain. What I currently do is play sudoku and if I don't win I either take a nap or watch Fox business until I can win at sudoku... but I did that and still wasted two days looking in all the wrong places to figure out my issue.


    This is a question straight out of my mythical autonomous wheelchair project:


    I know how to use a serial line to load code into the lut of a running cog…but once I do that how do I change to lut exec to actually execute from there?

    My code in cogexec should end with?







    A jump to the newly loaded code with address in the $200 to $3FF range.

    https://forums.parallax.com/discussion/165903/how-to-write-lut-exec-assembly-code
  • rjo__rjo__ Posts: 2,114
    edited 2019-04-26 14:15
    org is a compiler directive... I want to keep the compiler out of the picture. I want to download precompiled lut code(over a serial line)... using a cog, which initially is operating in cogexec mode to do the transfer. When the transfer is complete, jump to lut mode to executed the downloaded code... Hopefully when the lut code is done, it should transfer control back to the cogexec space of the same cog. So that the process can be repeated indefinitely.

    This would allows dynamic programming without the need to reboot or reset the P2.

    Maybe it isn't possible.

  • kwinnkwinn Posts: 8,697
    rjo__ wrote: »
    org is a compiler directive... I want to keep the compiler out of the picture. I want to download precompiled lut code(over a serial line)... using a cog, which initially is operating in cogexec mode to do the transfer. When the transfer is complete, jump to lut mode to executed the downloaded code... Hopefully when the lut code is done, it should transfer control back to the cogexec space of the same cog. So that the process can be repeated indefinitely.

    This would allows dynamic programming without the need to reboot or reset the P2.

    Maybe it isn't possible.

    Don't see why that would not be possible unless I missed some serious changes recently. Being able to run code from or store data in lut was possible a while back in the chip design.
  • rjo__rjo__ Posts: 2,114
    That is my thinking, but I don't remember seeing it. It is possible I have already done it and simply don't remember and can't find it:)






  • evanhevanh Posts: 15,126
    How complex the copying/loading process is doesn't change the meaning, nor use of, an ORG in the assembly source code before it gets made into whatever binary blob of choice.

    It's important to be comfortable with using ORG. You're still going to be using it for making explicit lutexec code. That's why I'm making some effort to explain its general use.

  • rjo__rjo__ Posts: 2,114
    edited 2019-04-26 20:43
    I like it. I'm thinking about starting a thread for simple examples. With your permission I'm going to drop your snippet in there.

    I just wanted to make sure you understood what I am trying to do. Start in cog exec... load a binary over a serial line... execute that binary in Lut exec and then switch back to cog exec. It seems like there should be a register or switch somewhere:)


    Thanks
  • There is not much difference in executing from LUT or COG ram and there is no need for a switch or a register, both RAMs are there simultaneously, there is no bank-switching.

    it is just that between COG ram and LUT ram is a small space for the special registers so COG code can not just extend into LUT you need to JMP/CALL into the memory above $1FF.

    So If you compile your snippets with org $200 you can load them anywhere in HUB ram, load them into the LUT with setq2 and rdlong and call #$200 from HUBexec. Running code in the LUT and returning to HUBexec when done.

    All this would run on the same COG.

    Enjoy!

    Mike
  • rjo__ wrote: »
    I like it. I'm thinking about starting a thread for simple examples. With your permission I'm going to drop your snippet in there.

    I just wanted to make sure you understood what I am trying to do. Start in cog exec... load a binary over a serial line... execute that binary in Lut exec and then switch back to cog exec. It seems like there should be a register or switch somewhere:)


    Thanks

    You are overthinking it. Once you have loaded the code into LUT you simply jump to it (or CALL it) in the address range of $200 - $3ff. On completion, the code executing in LUT simply jumps back (or RETs) to the code in COG space. There are some specific limitations on code running in LUT, but kicking off execution is dead simple.
  • rjo__rjo__ Posts: 2,114
    edited 2019-04-26 23:11
    Thanks guys.

    I think we are close enough so that I can tinker a bit. But first … just to be sure:)

    If I combine https://forums.parallax.com/discussion/165903/how-to-write-lut-exec-assembly-code with the answers you and Evanh have offered... it seems like all I have to do is:


    Compile the lut code with org $200 declared. Load the resulting binary into the lut using a serial line from CogExec and then jmp to $200 once it has loaded.

    Does that sound about right?


    When I want to go from LutExec back to CogExec is it just another jmp? (to where)? Maybe issue a coginit at that point from the lut?
  • Exactly!

    well the jmp back can go anywhere you want. The simplest way would be a call into LUT and a ret to return to the line in HUBexec after the call to LUT

    Enjoy!

    Mike
  • Cluso99Cluso99 Posts: 18,066
    Jumping in here...

    Easy to compile a code snippet for LUT. Just ORG $200 (as has been said). Now you can download that, or serial load it, or whatever, directly (if you like - preferred in your example) into LUT.
    Then you can CALL or JMP to LUT to execute it if you are loading it via the same COG,

    Now, if you want to make extra space available (for code and register space) you can run the COG/LUT loading code from HUB in HUBEXEC mode, and then CALL/JMP to COG/LUT.

    BTW DrAcula wrote code to do this sort of thing on P1 for COG called COGLETS IIRC. Try searching for his thread.
Sign In or Register to comment.