Curious dira outa behavior in assembly!
bill190
Posts: 769
I·noticed some strange behavior with my LED's when coding them in assembly. Problems I have not had with spin, so I decided to do a bit of experimenting as to what exactly turned my LEDs on and what did not...
I learned that what works in spin to turn on two separate LED's does not work the same with the assembly commands I am using to try to do the same thing. (This made perfect sense once I understood what was happening!)
Spin...
'P0 and P1 LEDs light· (No problem)
dira[noparse][[/noparse]0] := 1···········
outa[noparse][[/noparse]0] := 1
dira[noparse][[/noparse]1] := 1···········
outa[noparse][[/noparse]1] := 1
Assembly, trying to turn on LED 0 and LED 1...
'Only P1 LED lights ****************************
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0010
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0010
What is happening is that the second mov commands·are overwriting the first two mov commands and turning off LED 0.
So the question is, what is the same as·"dira[noparse][[/noparse]1] := 1" in assembly?
(I tried dira[noparse][[/noparse]1] and the compiler yelled at me!)
I learned that using "or" instead of "mov" for at least the second commands will solve this problem. This would look at the existing bits and keep them a 1 if they were already a 1. Or "xor" would·work the same, but I assume would not overwrite·an existing 1 with another 1?
So the lesson is to always use "or" or "xor" to set bits with dira and outa in assembly. Never mov. Or you risk overwriting previously turned on bits!
Here is my testing results for spin and assembly. Note the tests in red are not doing what is intended...
Spin outa dira...
'P0 LED lights
dira[noparse][[/noparse]0] := 1···········
outa[noparse][[/noparse]0] := 1
'P1 LED lights
dira[noparse][[/noparse]1] := 1···········
outa[noparse][[/noparse]1] := 1
'P0 and P1 LEDs light· (No problem)
dira[noparse][[/noparse]0] := 1···········
outa[noparse][[/noparse]0] := 1
dira[noparse][[/noparse]1] := 1···········
outa[noparse][[/noparse]1] := 1
Assembly outa dira....
'P0 LED lights
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
'P1 LED lights
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0010
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0010
'Only P1 LED lights ****************************
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0010
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0010
'Only P0 LED lights ****************************
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0010
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0010
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
'P0 and P1 LEDs light (Note the use of "or" for the second set)
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
or dira, #%0000_0000_0000_0000__0000_0000_0000_0010
or outa, #%0000_0000_0000_0000__0000_0000_0000_0010
'Only P0 LED lights ****************************
or dira, #%0000_0000_0000_0000__0000_0000_0000_0010
or outa, #%0000_0000_0000_0000__0000_0000_0000_0010
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
'P0 and P1 LEDs light (Note the use of "or")
or dira, #%0000_0000_0000_0000__0000_0000_0000_0010
or outa, #%0000_0000_0000_0000__0000_0000_0000_0010
or dira, #%0000_0000_0000_0000__0000_0000_0000_0001
or outa, #%0000_0000_0000_0000__0000_0000_0000_0001
The following is interesting....
' Nothing lights
mov dira, #0
mov outa, #0
'P0 LED lights
mov dira, #1
mov outa, #1
'P1 LED lights
mov dira, #2
mov outa, #2
'P0 and P1 LEDs light
mov dira, #3
mov outa, #3
'P2 LED lights
mov dira, #4
mov outa, #4
'Only P1 LED lights ********
mov dira, #1
mov outa, #1
mov dira, #2
mov outa, #2
'P0 and P1 LEDs light (Using "or" for 2nd set)
mov dira, #1
mov outa, #1
or dira, #2
or outa, #2
I learned that what works in spin to turn on two separate LED's does not work the same with the assembly commands I am using to try to do the same thing. (This made perfect sense once I understood what was happening!)
Spin...
'P0 and P1 LEDs light· (No problem)
dira[noparse][[/noparse]0] := 1···········
outa[noparse][[/noparse]0] := 1
dira[noparse][[/noparse]1] := 1···········
outa[noparse][[/noparse]1] := 1
Assembly, trying to turn on LED 0 and LED 1...
'Only P1 LED lights ****************************
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0010
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0010
What is happening is that the second mov commands·are overwriting the first two mov commands and turning off LED 0.
So the question is, what is the same as·"dira[noparse][[/noparse]1] := 1" in assembly?
(I tried dira[noparse][[/noparse]1] and the compiler yelled at me!)
I learned that using "or" instead of "mov" for at least the second commands will solve this problem. This would look at the existing bits and keep them a 1 if they were already a 1. Or "xor" would·work the same, but I assume would not overwrite·an existing 1 with another 1?
So the lesson is to always use "or" or "xor" to set bits with dira and outa in assembly. Never mov. Or you risk overwriting previously turned on bits!
Here is my testing results for spin and assembly. Note the tests in red are not doing what is intended...
Spin outa dira...
'P0 LED lights
dira[noparse][[/noparse]0] := 1···········
outa[noparse][[/noparse]0] := 1
'P1 LED lights
dira[noparse][[/noparse]1] := 1···········
outa[noparse][[/noparse]1] := 1
'P0 and P1 LEDs light· (No problem)
dira[noparse][[/noparse]0] := 1···········
outa[noparse][[/noparse]0] := 1
dira[noparse][[/noparse]1] := 1···········
outa[noparse][[/noparse]1] := 1
Assembly outa dira....
'P0 LED lights
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
'P1 LED lights
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0010
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0010
'Only P1 LED lights ****************************
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0010
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0010
'Only P0 LED lights ****************************
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0010
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0010
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
'P0 and P1 LEDs light (Note the use of "or" for the second set)
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
or dira, #%0000_0000_0000_0000__0000_0000_0000_0010
or outa, #%0000_0000_0000_0000__0000_0000_0000_0010
'Only P0 LED lights ****************************
or dira, #%0000_0000_0000_0000__0000_0000_0000_0010
or outa, #%0000_0000_0000_0000__0000_0000_0000_0010
mov dira, #%0000_0000_0000_0000__0000_0000_0000_0001
mov outa, #%0000_0000_0000_0000__0000_0000_0000_0001
'P0 and P1 LEDs light (Note the use of "or")
or dira, #%0000_0000_0000_0000__0000_0000_0000_0010
or outa, #%0000_0000_0000_0000__0000_0000_0000_0010
or dira, #%0000_0000_0000_0000__0000_0000_0000_0001
or outa, #%0000_0000_0000_0000__0000_0000_0000_0001
The following is interesting....
' Nothing lights
mov dira, #0
mov outa, #0
'P0 LED lights
mov dira, #1
mov outa, #1
'P1 LED lights
mov dira, #2
mov outa, #2
'P0 and P1 LEDs light
mov dira, #3
mov outa, #3
'P2 LED lights
mov dira, #4
mov outa, #4
'Only P1 LED lights ********
mov dira, #1
mov outa, #1
mov dira, #2
mov outa, #2
'P0 and P1 LEDs light (Using "or" for 2nd set)
mov dira, #1
mov outa, #1
or dira, #2
or outa, #2
Comments
Do remember that an immediate source operand (#...) only has 9 bits.
or outa, #%0000_0000_0000_0000_0000_0000_0000_0001
...will not work up to 32? I only tested up to P8.
(I'm going by the Propeller Manual example which is in the spin section...)
·
Not directly related to the OP, but I struck a peculiar case while writing XMM drivers for Bill's Morhpheus platform. A particular set of apparently valid PASM instructions (from memory, involving just MOV, ANDN & OR on the special register OUTA) resulted in a bit in the OUTA register being set and then reset by two consecutive PASM instructions. This is what I wanted, and my assumption was that this would result in the output pin going high for one full instruction cycle - but in fact what apparently happened was that the external pin either did not go high at all, or went high only for a fraction of the expected time - and in my particular case it was not going high long enough for the external SRAM hardware.
With a bit of help from Bill I got it sorted out. Substituting a different combination of logically identical instructions worked - but I still wonder what the rules actually are. I know it has something to do with the different timing of the various instructions through the instruction pipeline, which means the state of a bit can be "clobbered" before it actually makes it to the pins - but it can be really nasty to track problems like this down.
Is there a reference you can point us to where the cases or combinations of instructions that might have this problem are documented?
Ross.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Catalina - a FREE C compiler for the Propeller - see Catalina
Yes, to set bits beyond bit 9 you cannot use an immediate mode instruction - instead, set the mask up in a cog location and use the address of that cog location instead.
Ross.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Catalina - a FREE C compiler for the Propeller - see Catalina
Figuring the particular combination again would not be that easy - I don't have the tools required to measure the actual timing, which is why finding it in the first place was almost impossible. To reproduce it now I would just be doing trial and error. But I believe it is a reasonably well known issue, which someone with a decent oscilloscope should be able to verify. Bill may be able to help narrow it down.
Ross.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Catalina - a FREE C compiler for the Propeller - see Catalina
TestPin0 long |< 0
TestPin1 long |< 1
TestPin2 long |< 2
TestPin3 long |< 3
TestPin4 long |< 4
TestPin5 long |< 5
TestPin6 long |< 6
TestPin7 long |< 7
TestPin8 long |< 8
etc.
Then...
or dira, TestPin0
or outa, TestPin0
or dira, TestPin1
or outa, TestPin1
etc.
TestPin27 long %0000_1000_0000_0000__0000_0000_0000_0000
······· or dira, TestPin27
······· or outa, TestPin27
Note: When I tried using·what I listed in·the first post above for a higher number pin like this...
mov dira, #%0000_1000_0000_0000__0000_0000_0000_0000
...then the compiler did "yell" at me and say that was a no no (as mike pointed out above). Thanks!