Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: Direct port manipulation on Teensy 3.6

  1. #1

    Direct port manipulation on Teensy 3.6

    I've sort of bumbled onto the fact that unless I use pinMode() at least once, my direct port manipulation code doesn't work.

    So for example, I've got code like

    Code:
    GPIOC_PDDR = GPIOC_PDDR & 0xff00;
    that in theory ought to turn the bottom 8 pins of port C to INPUT mode, but unless I've run pinMode() invocations (either INPUT or OUTPUT), it doesn't seem to do anything.

    I'm guessing there's something under the covers that pinMode() does that I'm unfamiliar with. While I tried to dig into pinMode()'s code to figure out what's going on, it's a rather complex block of code, and I'm not quite following what it's doing.

    Is there a *canonical* description (or better yet, code example) of how to do direct port manipulation (both input and output) on Teensy 3.6 somewhere? I read the MK66FX1M0 chip documentation, but it's a bit overwhelming as well, or at least it's not obvious to me how I turn the descriptions there into working C code.


    Also, if I've got a function I want to call say 40 times a second (25 mS intervals), and I've also got a bunch of input pin driven interrupts, what's the best way to set up the code so they don't interfere with each other? That is to say, I need both the clock driven interrupts and the pin driven interrupts to wait until their code block is complete before "interrupting" each other. I was using the Metro library in my loop() function, but that seems unlikely to work, since that loop gets interrupted by the pin interrupts.

  2. #2
    Senior Member
    Join Date
    Feb 2017
    Posts
    271
    Quote Originally Posted by calphool View Post
    I've sort of bumbled onto the fact that unless I use pinMode() at least once, my direct port manipulation code doesn't work.
    While I tried to dig into pinMode()'s code to figure out what's going on, it's a rather complex block of code, and I'm not quite following what it's doing.
    So, let pinMode() do the setup for you and then use your direct port input / output.

  3. #3
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,329
    pinMode() is needed to configure the pins (which are hi-z and/or analog by default) as GPIO pins by changing the pinMUX configuration for each pin from ALT0 to ALT1.

    This might be confusing, since on the old AVR processors, pins were GPIO by default. But this isn’t the case for the Kinetis K processors.

  4. #4
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,515
    Yes pinmode is only needed once.

    Quote Originally Posted by calphool View Post
    Also, if I've got a function I want to call say 40 times a second (25 mS intervals), and I've also got a bunch of input pin driven interrupts, what's the best way to set up the code so they don't interfere with each other? That is to say, I need both the clock driven interrupts and the pin driven interrupts to wait until their code block is complete before "interrupting" each other.
    Two thoughts:
    - 25ms is not much for Teensy T3.6. If that's your interval, stay with digitalRadFast/WriteFast. They need one cpu-cycle if called with a constant pin-number. 8 Pins - 8 cycles. Keep it simple, at least for a first try.
    - If the interrupts have the same priority (by default yes) they will not interfere with each other. They will be called one after the other, if both get triggered.

  5. #5
    Quote Originally Posted by Frank B View Post
    Yes pinmode is only needed once.



    Two thoughts:
    - 25ms is not much for Teensy T3.6. If that's your interval, stay with digitalRadFast/WriteFast. They need one cpu-cycle if called with a constant pin-number. 8 Pins - 8 cycles. Keep it simple, at least for a first try.
    - If the interrupts have the same priority (by default yes) they will not interfere with each other. They will be called one after the other, if both get triggered.
    So you're saying don't use Metro in the loop() for the clock driven code. Use something else. IntervalTimer I'm guessing?

  6. #6
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,515
    Yes, try IntervalTimer.

  7. #7
    That's what I needed. Thanks. Docs sort of encourage you to use Metro, but it really depends on what you're doing. Metro sort of gets in the way if you're trying to combine interrupts and timing stuff.

  8. #8
    Quote Originally Posted by Theremingenieur View Post
    pinMode() is needed to configure the pins (which are hi-z and/or analog by default) as GPIO pins by changing the pinMUX configuration for each pin from ALT0 to ALT1.

    This might be confusing, since on the old AVR processors, pins were GPIO by default. But this isnít the case for the Kinetis K processors.
    Yeah, I found that kind of stuff in the processor documentation, but what exactly one needs to code to "change the pinMux configuration" isn't obvious to me.

  9. #9
    Senior Member
    Join Date
    Feb 2017
    Posts
    271
    Quote Originally Posted by calphool View Post
    Yeah, I found that kind of stuff in the processor documentation, but what exactly one needs to code to "change the pinMux configuration" isn't obvious to me.
    Section 12.5.1 of the Datasheet.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •