Shop OBEX P1 Docs P2 Docs Learn Events
I/O glitch when setting pin direction? — Parallax Forums

I/O glitch when setting pin direction?

agsags Posts: 386
edited 2013-08-07 09:31 in Propeller 1
I'm debugging an intermittent problem communicating to an external (SPI) device. I'm seeing a ~16us glitch on an IO pin. That pin has a 50kOhm pullup.
I'm just prototyping and am using SPIN (eventually to be converted to PASM for speed). I'm first setting the outa[pinNum] to 1, then setting dira[pinNum] to 1. I expected that this would drive pinNum high immediately. Is there some delay between setting the pin direction to output and when it is actually driven high, even if the output value is set high before the pin direction is set to output?

In other words, with this code:
outputPinMask:= |<clkPin | |<mosiPin | |<csPin
outa |= |<mosiPin | |<csPin
dira |= outputPinMask
and a 50k pullup on csPin, can I expect that the csPin would not experience any glitch (low) when changed from being an input to an output, if the output register is "preset" with a high value for that pin?

Comments

  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-08-03 12:46
    If you're using a pull-up you may want to stick with manipulating the dira bit for that pin. As a fan of the KISS principle, I would do this:
    [b]pub[/b] select(cs)
    
      outa[cs] := 0
      dira[cs] := 1
    
    
    [b]pub[/b] deselect(cs)
    
      dira[cs] := 0
    


    I find it best to start with overtly-obvious code in the beginning, then optimize once things are working.
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-03 12:49
    There's nothing wrong with these statements by themselves. What's going on before these get executed? What's the state of the I/O pin prior to this?
  • agsags Posts: 386
    edited 2013-08-03 15:47
    Mike Green wrote: »
    There's nothing wrong with these statements by themselves. What's going on before these get executed? What's the state of the I/O pin prior to this?

    Almost nothing else. I do test ina to see if the csPin pullup is present (to detect the external device).
    ifnot ina[csPin]
      'stop execution
    

    I may have some noise, this is a messy prototype on a breadboard with jumpers. I'll have to see if I can capture this with a scope to see if it's really a clean signal driving low or noise. That won't be easy, so I thought I'd check my understanding of ina and dira before beginning that headache of a task.
  • FernandFernand Posts: 83
    edited 2013-08-05 18:26
    I'm no prop guru, but I had a head-scratcher which suggests a thought. I was setting the I/O direction register with dira in one cog, and starting up another cog to do some of the dirty work, with the surprising (to me) result that the code in that cog could not drive the outgoing pins. Set 'em high, set 'em low, no nothin', nada, no way. Turns out that the pins' direction are local to each cog. Direction has to be set (or repeated) in the initialization code for every cog. What that suggests then is that the I/O register is indirectly mapped for each cog, and will only be flipped at its turn in the Grand Revolver. Could that explain what ags is seeing?
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-05 21:09
    ags is setting dira and outa in the same cog. The Propeller datasheet and the Propeller Manual both have diagrams that show how the I/O pins are connected to the cogs. Essentially, the dira bits are or'd together for all the cogs so, if any cog sets its dira bit to a 1, the I/O pin becomes an output. All cogs have to have their dira bit set to 0 for the I/O pin to work as an input. Similarly, if any cog sets its outa bit to a 1, the corresponding output is set to 1. The ina bit for all cogs reflects the state of the I/O pin whether that pin is set as an output or an input.
  • FernandFernand Posts: 83
    edited 2013-08-05 22:16
    Yes, I understand he's working in one cog. But if the direction registers are actually set on the Hub cycle, and not directly, might it explain his delay?

    As to the direction reg being OR'ed, that's what I thought from the specs. Let me see if I can set up an example for you of what I was getting, much to my surprise, where I could not toggle an out pin after it had been set as an output in another cog. We agree it shouldn't be this way? Maybe I was doing something wrong, but let me see.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-05 23:18
    Fernand,

    No, setting pins and directions is not a HUB operation. They happen as soon as they are executed at normal PASM instruction speed. If they were dependent on HUB timing then handling I/O pins would be 8 times slower which would be a disaster.
    ...example for you of what I was getting, much to my surprise, where I could not toggle an out pin after it had been set as an output in another cog. We agree it shouldn't be this way?

    No we don't agree. You have to set DIR from the same COG has you are doing OUT from That is clearly explained with nice diagrams in the manual.

    If you have a 16us delay in there somewhere that is a lot. Like 320 instructions worth. Even if things were tied to HUB timing that would be huge. You have some other problem going on here.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-05 23:28
    ags,
    I'm seeing a ~16us glitch on an IO pin. That pin has a 50kOhm pullup.....I'm first setting the outa[pinNum] to 1, then setting dira[pinNum] to 1. I expected that this would drive pinNum high immediately.
    How are you measuring that 16us "glitch"? Looks like your problem is there.

    Of course Spin is slow so those 3 lines of code will take 100's of instruction cycle times. Perhaps your code really does take 320 instructions (16us) to execute.
  • FernandFernand Posts: 83
    edited 2013-08-06 01:55
    @Heater, No idea what ags' delay is, but Mike seems to be saying something a little different than you. What I was surprised to observe is that the dira[ ] operations are completely local to each cog. If I set a pin as output in one cog it has no bearing on other cogs, they could set it either way. Same with setting a pin to input in cog B that cog A has set as output : it doesn't change anything in cog A. They are independent.

    But bear with me, for that bit of a miracle to be possible, in the end it's easy for multiple cogs to read a pin, but for output it seems that something like a semaphore, latch, or exclusivity lock would be in place for the operation to atomically complete, especially if dira[ ] is being changed, hence my naive thinking that it could be Hub-related. Are you saying that all the I/O registers, timers etc are shared by 8 cogs with everything taking place at gate propagation speed - no latches, no clocked sequencing? Thanks.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-06 02:54
    Fernand,

    For "that bit of a miracle to be possible" it does not require any semaphores, latches, or exclusivity locks (Apart from the latches that are the DIR and OUT registers). All that is needed is AND and OR gates.
    Are you saying that all the I/O registers, timers etc are shared by 8 cogs with everything taking place at gate propagation speed - no latches, no clocked sequencing?

    Yes.

    If we look at page 20 of the Propeller Manual (v1.2) we see that there is an I/O output and direction register in each cog. It shows how each bit of a COGs output and direction registers are ORed together with those corresponding bits of every other COG to determine the final pin direction and output drive.

    Clearly there is no need to go through the HUB round robin access scheme to use those.

    On page 21 we see another diagram again showing the same I/O logic. Again there is no interaction with the HUB timing here either.

    This is spelled out in the text on page 26:
    In essence, each I/O pin’s direction and output state is the “wired-OR” of the entire cog collective. This allows the cogs to access and influence the I/O pins simultaneously without the need for any resource arbiter and without any possibility of electrical contention between the cogs.

    Why do we have to set DIR from the same COG that is driving an output then?

    Have a look at the diagrams again. In that logic tree driving each final output and direction we see that in each COG the is an AND gate. It ANDs the bits from the COGs direction register with the bits of the output register.

    So, if a COG does not set it's DIR it cannot drive any outputs into the OR logic that combines direction and outputs from all the other COGs.

    I think that is all clear enough.
  • FernandFernand Posts: 83
    edited 2013-08-06 03:31
    Thanks, Heater.
  • agsags Posts: 386
    edited 2013-08-06 10:02
    Back to the problem at hand - I'm seeing the glitch when sampling the IO pins with a logic analyzer. The glitch is pretty long, and I can't explain it. There are no other cogs that are driving the "glitching" pin (that I know of). Additionally, the glitch is a transition from high-to-low. The only way for the line to be driven low (by the Propeller) would be for the direction to be set to output and the value set to low in this cog.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-06 12:00
    ags,

    I have to repeat my question: "How are you measuring that 16us "glitch"?"

    The code you show us so far is not enough. If you are using an LSA you must be watching some pin changing state that is the eventual cause of the output you expect. And I guess there is some other code involved to at least read that input.
  • agsags Posts: 386
    edited 2013-08-06 20:37
    Heater: I'm using a standalone Logic Analyzer probing the Propeller IO pins. I'm triggering on a rising edge of a chip select signal, driven by SPIN bit banging. I am able to store values before the trigger as well. I'm able to measure the time of all edges/samples. I'm looking at the uploaded samples.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-07 00:54
    ags,

    OK, so you drive an output, some kind of CS, then you drive some other pin and the LSA shows you want is happening. Good stuff. Now all we need to know about is all the code you have between those two pin events.
    We also need to be sure there is no other code, on other COGs, accidentally tweaking those same pins.
    As both these events are driven my your code they should be 100% predictable.
  • MJBMJB Posts: 1,235
    edited 2013-08-07 01:34
    ags,

    why don't you just post the complete minimum code to produce the effect?
    Then others either can reproduce or find the problem in the code ...
  • agsags Posts: 386
    edited 2013-08-07 08:59
    I hear and understand the perfectly reasonable calls for minimized code that exhibits the problematic behavior. Unfortunately, I am unable to provide that because I can't isolate the problem. I am using every IO pin and every cog. Of course I don't think there is any pin interference, but I never think I've intentionally coded improperly. What I found most unusual was that the so-called "glitch" was driving low (not high). If there was contention from another cog, it could never force a pin low, only high (due to the wire-or nature of the IO control architecture).

    I started from scratch and reimplemented this section of code and I no longer see this problem. So I'm going to remove the unsolved notation from this post (still not solved, though, since I can't explain the cause). I'd still like confirmation, if possible, of what I've come to take for granted regarding control of output pins (even in SPIN). That is, if a pin is configured as an input (high impedance), when dira is modified to configure that pin to an output, there will only be one transition on that pin, either directly to a high or low state (based on the value of outa). In other words, for pin 0, if outa[0]==0, then when dira[0]:=1, pin 0 will not drive high and then settle to a low state, it will move from hiZ to low state direclty; similarly, if outa[1]==1, when dira[0]:=1, pin0 will not drive low then settle to a high state, it will move from hiZ to high state directly.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-07 09:09
    I think this thread and the manual are confirmation enough.
    If you are still not convinced then a simple test program, your external circuit, and an LSA are sufficient to demonstrate it for yourself.

    Without a glimpse at your code we are unable to diagonse anything.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-07 09:17
    Of course when moving a pin from a high Z state to a low there may or may not be any transision on the pin depending on what the external circuitry was pulling it to initially.

    Given that you seem to have code that "works" now and code that does not I don't see why you cannot post that little part.

    And it would help to know what is connected externally.
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-07 09:31
    When an I/O pin is configured as an input and the corresponding OUTA bit is pre-set to either 0 or 1, when the corresponding DIRA bit is changed from 0 to 1, the I/O pin is driven to the state set in the OUTA bit using a low impedance MOSFET. The speed of the transition to the specified state depends on what's connected to the I/O pin, but, since the output MOSFETs can source or sink on the order of 40mA, this transition is normally on the order of nanoseconds.

    If OUTA[n] is 1 and DIRA[n] is changed from 0 to 1, the I/O pin will go from a hiZ state to a high state without any other transitions. Similarly, if OUTA[n] is 0, the I/O pin will go directly to a low state. Depending on what's connected to the I/O pin, there may be RC delays or reflected pulses that may distort the waveform seen at the I/O pin, but it doesn't sound like that's what you're seeing. I suspect a software problem.

    There are several commonly used objects that use this technique including some that I've written and have been in use for years. Occasionally people have looked at the output signals using a scope and they don't behave the way you describe. In addition, they would likely not work correctly.
Sign In or Register to comment.