Shop OBEX P1 Docs P2 Docs Learn Events
easy way to tell PASM-code HUB-RAM-variables adresses — Parallax Forums

easy way to tell PASM-code HUB-RAM-variables adresses

StefanL38StefanL38 Posts: 2,292
edited 2012-03-20 13:52 in Propeller 1
I played around a little bit with the capswitch-code (capacitive proximity sensor).
Code is attached.

When I analysed the code first I wondered where the heck gets this variable "reslt" updated??

Then I discovered in the PASM-DAT-section of the code a "PASM"-variable "reslt_ptr" is defined.

First thing that is done in the SPIN-code is assigning
reslt_ptr := @reslt

After this assigning the PASM-code can use this "PASM"-variable "reslt_ptr" to do HUB-RAM-writes to the SPIN-variable "reslt"
Wow cool so this is a second way how to tell PASM-code HUB-RAM-adresses. First way is the second parameter of cognew which starts PASM-code

Do I understand right that the assigning has to be done before starting the PASM-cog? The cognew(@PASM-entry..) copies the DAT-section to the cog-RAM
and this means all initialisation

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-03-20 10:45
    The problem with assigning location from Spin is the object can't be used by other languages besides Spin.

    The perferred method of passing location is to use the address passed to par and use that address as the starting point and add 4 to get the next long location in hub (only pass long locations with par).

    Poking the values in with Spin prior to lanching the code is easier though (which is why I usually do it that way).

    If you want your code to be C friendly, you shouldn't go poking around in Spin.
  • Mike GreenMike Green Posts: 23,101
    edited 2012-03-20 11:00
    The main reason for these ways to supply hub addresses to PASM code is that the Spin compiler/assembler doesn't know where the hub variables will be placed at the time the PASM code is assembled and, as the various sections of the program are laid out in memory by a later phase of the compiler, there's no provision to "fix them up" to their absolute addresses. The Spin code can get an absolute address when it's running and can either modify the PASM code in hub memory before it's copied to a cog for execution or pass an address in PAR via the COGNEW call or build a table of addresses and pass the address of the table in PAR.
  • JonnyMacJonnyMac Posts: 9,236
    edited 2012-03-20 12:49
    Do I understand right that the assigning has to be done before starting the PASM-cog?

    Yes, because the code resides in the hub at that point and your Spin code can get to it; once it's in the cog it's beyond reach.

    An argument has been made -- and I have come to agree -- that the interface code should not modify the assembly code. While this is possible in Spin, it limits that object and the assembly code used in it to Spin projects. With PropGCC coming this is considered bad form (my opinion), and I just chastised myself in print no less (May Nuts & Volts column) for doing this in past projects.

    I'm not a big C programmer but I do write objects that many find useful. My goal, then, is to have any PASM code I write be useful in my Spin projects, as well as be compatible with PropGCC (and other languages that support launching PASM code into its own cog). I realize that this can create some small redundancies, but it's worth it.

    For example, in an AC phase dimmer I'm working on now, here is the interface and the associated PASM. Note that variables in the object are modified and then the first in the group is passed via the PAR register to the PASM code that knows how deal with things from there.
    var
    
      long  cog                                             ' cog running driver
    
      long  ch0pin                                          ' io pins for AC
      long  ch1pin
      long  ch2pin
      long  ch3pin
      long  zcpin
      long  brpntr                                          ' pointer to brightness array
      
      byte  brightness[4]                                   ' dimmer levels, 0 to 255
      
    
    pub start(ch0, zc)
    
    '' Start 4-channel AC dimmer
    '' -- user responsible for correct pin assignments
    ''    * no error checking!
    '' -- assumes ch0..ch3 contiguous and in ascending order
    
      return startx(ch0+0, ch0+1, ch0+2, ch0+3, zc)
      
    
    pub startx(ch0, ch1, ch2, ch3, zc) | ok
    
    '' Start 4-channel AC dimmer
    '' -- user responsible for correct pin assignments
    ''    * no error checking!
    
      stop
    
      longmove(@ch0, @ch0pin, 5)                                    ' copy pins
      brpntr := @brightness                                         ' point to levels array
      
      ok := cog := cognew(@dimmer, @ch0pin) + 1                     ' start the dimmer cog
    
      return ok
    

    dat
    
                            org     0
    
    dimmer                  mov     outa, #0                        ' all outputs off
                            mov     dira, #0                        ' clear all outputs
    
                            mov     t1, par                         ' start of structure
                            rdlong  t2, t1                          ' read ch0 pin
                            mov     ch0mask, #1                     ' convert to mask
                            shl     ch0mask, t2
                            or      dira, ch0mask                   ' make output
                            
                            add     t1, #4
                            rdlong  t2, t1
                            mov     ch1mask, #1
                            shl     ch1mask, t2
                            or      dira, ch1mask
    
                            add     t1, #4        
                            rdlong  t2, t1        
                            mov     ch2mask, #1   
                            shl     ch2mask, t2   
                            or      dira, ch2mask
    
                            add     t1, #4        
                            rdlong  t2, t1        
                            mov     ch3mask, #1   
                            shl     ch3mask, t2   
                            or      dira, ch3mask
    
                            add     t1, #4        
                            rdlong  t2, t1        
                            mov     zcmask, #1   
                            shl     zcmask, t2   
    
                            add     t1, #4
                            rdlong  hubch0, t1                      ' read hub addr of levels array
    
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-03-20 13:52
    The only disadvantage coming into my mind is that you can't start the same code one after the other. You have to wait until the COGNEW is done with loading the code up to the 'injection variable' before you can inject the next and call a COGNEW again.

    And to be honest that's what you should be allowed to do with most of the objects! Say you instanciate 3 full duplex serial interfaces. You'd have to wait until the first one is loaded into the COG before you can start the next one. Using PAR you can fire all three up in parallel which means call the start methods directly one after the other. (COGNEW does not wait for the COG to be loaded completely, it immediately returns and you can continue)
Sign In or Register to comment.