Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teensy 4: Default FlexIO clock configuration is invalid #156

Open
ardnew opened this issue Sep 12, 2021 · 6 comments
Open

Teensy 4: Default FlexIO clock configuration is invalid #156

ardnew opened this issue Sep 12, 2021 · 6 comments

Comments

@ardnew
Copy link

ardnew commented Sep 12, 2021

In the Teensy 4 sources, the code that initializes the FLEXIO2 peripheral configures an invalid clock setting according to the IMXRT1062 reference manual. I'm curious if this setting is intentional and is actually being accepted, or if its code that has just always been there and hasn't really been verified.

The code in question is from MatrixTeensy4Hub75Refresh_Impl.h:

template <int refreshDepth, int matrixWidth, int matrixHeight, unsigned char panelType, uint32_t optionFlags>
FLASHMEM void SmartMatrixRefreshT4<refreshDepth, matrixWidth, matrixHeight, panelType, optionFlags>::hardwareSetup() {
    // ...

    // Configure FlexIO clock source
    // FlexIO clock is independent from CPU and bus clocks (not affected by CPU overclocking)
    pFlex->setClockSettings(3, 0, 0); // 480 MHz PLL3_SW_CLK clock

    // ...
}

The problem is with the two clock dividers, given the 480 MHz PLL3_SW_CLK mux selection. A value of 0 means a divider of 1, so altogether this is attempting to configure FLEXIO2 clock root as: 480MHz / (1 * 1) = 480MHz.

However, according to the i.MX RT1060 Processor Reference Manual, Rev. 2, 12/2019, Table 14-5. System Clock Frequency Values, page 1032, the maximum clock frequency for all three FlexIO peripherals is 120 MHz (FLEXIO2 and FLEXIO3 share the same clock source):

flexio-maxfreq

This means the minimum allowable dividers — with 480 MHz source clock frequency — must have a product no less than 4, so they must be either 1 * 4 or 2 * 2. The code could thus be changed to:

    // Configure FlexIO clock source (120 MHz)
    // FlexIO clock is independent from CPU and bus clocks (not affected by CPU overclocking)
    pFlex->setClockSettings(3, 1, 1); // 480 MHz PLL3_SW_CLK clock, CLK_PRED=2, CLK_PODF=2

The original FlexIO driver from KurtE, as noted in its comments, makes no attempt to verify the given clock settings, so it will happily try to use invalid settings.

@ardnew ardnew changed the title Default FLEXIO clock configuration is invalid Teensy 4: Default FlexIO clock configuration is invalid Sep 12, 2021
@embedded-creations
Copy link
Contributor

@easone do you have any thoughts on this?

@easone
Copy link
Collaborator

easone commented Sep 14, 2021

The FlexIO peripheral seems to run happily with a 480 MHz clock as far as I can tell. From my testing, increasing the FlexIO clock increases the speed at which the shifters trigger when data is copied into their buffers, which reduces delays and improves display speed slightly. I guess the manual lists a conservative maximum speed for FlexIO and it can actually be overclocked.

I will say that the 480 MHz clock doesn't seem to work perfectly with the CPU speed below 600 MHz. Some other folks have had issues as documented here: https://forum.pjrc.com/threads/67815-FlexIO-quot-Extra-quot-clock-cycle-on-8080-parallel-setup

I don't know whether a lower FlexIO clock speed would enable running the CPU slower but it seems possible... If for some reason you wanted to reduce the FlexIO clock speed, you would need to adjust the timing constants in the MatrixHardware header accordingly.

@easone
Copy link
Collaborator

easone commented Sep 14, 2021

Just confirmed that reducing the FlexIO clock speed from 480 to 240 MHz works as expected and allows the CPU speed to be reduced as low as 396 MHz. Apart from some low power application, I don't see why this provides any benefit...

For posterity: to use the 240 MHz clock speed, make the following changes:

  • Clock setting in MatrixTeensy4Hub75Refresh_Impl.h should be changed to:pFlex->setClockSettings(3, 1, 0)
  • Shift clock divider in MatrixHardware_Teensy4_ShieldV5.h should be changed to: #define FLEXIO_CLOCK_DIVIDER 12
  • Timing constant in MatrixHardware_Teensy4_ShieldV5.h should be changed to: #define PANEL_32_PIXELDATA_TRANSFER_MAXIMUM_NS ((32*FLEXIO_CLOCK_DIVIDER*1000/240) + 200)

@ardnew
Copy link
Author

ardnew commented Sep 14, 2021

I think by you comparing the behavior of FlexIO timers relative to how they behave when configured with a valid clock (per RM) is a legitimate test, verifying it is indeed using the 480 MHz its configured with. You verified this with FLEXIO2 only? Curious then where the 120 MHz comes from — perhaps one of the FlexIO functional modes, or maybe one of the possible input trigger sources, or its outputs, are the bottleneck?

I discovered the 120 MHz limitation by using NXP's MCUXpresso SDK (Eclipse IDE) while trying to configure a project equivalent to the settings used in this repo. Their "Clocks" configuration tool refuses to accept — in every way I know to try — the FlexIO PRED/PODF prescalars equal 1; or, if you hardcode any value greater than 120 MHz as a FlexIO clock root, it will flag it as an error and refuse to generate code for you. Pretty helpful tool, huh? 👎🏻

I am intending to mimic much of this project in terms of its DMA-driven FlexIO config, so I too will try using a 480 MHz clock and hope for the best.

Anyway, thanks for verifying this on a real device @easone. Sounds like this issue can probably be closed.

@ardnew
Copy link
Author

ardnew commented Sep 14, 2021

Also, considering this project is using a completely undocumented extra FlexIO shifter, it really shouldn't be surprising that the FlexIO clock roots are capable of a greater-than-documented frequency...

@easone
Copy link
Collaborator

easone commented Sep 15, 2021

There are many things undocumented about FlexIO, unfortunately. For example if you read the FLEXIO2_PARAM register after enabling FlexIO2, the value stored there indicates that there are 8 timers and 8 shifters on the chip rather than 4 as stated in the manual. As far as I'm aware, the extra four shifters function normally in most respects, except I think they cannot be used with DMA. It was a bit of a happy accident to discover that we could use this for SmartMatrix addressing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants