I'm sure I'm doing something wrong here, I just don't know what it is.
I have a test KSDK + PEx project for a FRDM-K22F and I am just tight looping, toggling a single GPIO. I have set my clock configuration to 1 (maximum) and yet my output frequency is just under 780kHz. Is there something I'm missing here?
My test app is literally Create New -> FRDM-K22F -> KSDK + PEx -> add fsl_gpio -> bitbang in while loop.
With default "max speed" clock settings:
FRDM-K22F: 780kHz
FRDM-K64F: 760kHz
under mbed (just as a quick comparison)
FRDM-K64F: 640kHz
已解决! 转到解答。
I am not intimately familiar with the K22F clock-settings; the closest I come is K20, and I do everything 'bare metal' to be in complete control. So I can't give any particular 'hints' as to your supposed factor-of-2, which I think we can trust from your numbers!
So this guy:
Confirming K22F Clock Frequency
was making a bit-banged SPI, and I showed where an IAR-chain high-optimization loop could net 16 half-word instructions per bit in&out. If your 'inner loop' can look anything like this, you should see it cycle about 20 clocks per bit (or better!). As discussed at the end of the thread, a 'dirt simple' sequence of PORTx_PTOR 'toggles' can certainly toggle at full core-clock speed.
Same story we seem to go thru here: Firstly, concoct a means to confirm that your system/bus clock is exactly as expected -- UART0 bit rate is a good way. Then, you have to look at the complete assembly-instruction-level sequence of your 'while loop'..
Unfortunately, I don't use either of those tools, so I can't be any direct help in that fashion!
We don't care WHAT the UART clock rate IS, just that we know the exact source AND divisor. UART0 (and 1) should have the particular advantage of being derived directly from the Bus Clock, so there is 'one less unknown' in the path.
Hi egoodii I still need to read up on the clock configuration in the K22F and K64F to get a better understanding of things. But yesterday, my test of setting UART1 to max baud rate and then sending 0x55 in a tight loop yielded a bitrate of 3.68MHz, which is about half of the expected speed. I suppose one way of looking at this is that it's at least not off by a couple of orders of magnitude. :smileyhappy:
I did look over the assembly code, and the KSDK methods for setting and clearing bits cost about 36 instructions each! 120MHz / 36 * 2 means I should see a toggling frequency of about 1.67MHz. Again, my actual frequency of about 760kHz is roughly half of the expected, and at least this would explain the huge difference in actual speed vs. the expected. Thanks again for suggesting that I dig into the assembly -- it would have taken a bit more convincing on my own before I would have reached that conclusion.
With this information, would you guess that there is an incorrect prescaler setting somewhere? In addition, I take it you wrote an optimized function for doing GPIO operations? Do you think my process outlined here is valid?
I am not intimately familiar with the K22F clock-settings; the closest I come is K20, and I do everything 'bare metal' to be in complete control. So I can't give any particular 'hints' as to your supposed factor-of-2, which I think we can trust from your numbers!
So this guy:
Confirming K22F Clock Frequency
was making a bit-banged SPI, and I showed where an IAR-chain high-optimization loop could net 16 half-word instructions per bit in&out. If your 'inner loop' can look anything like this, you should see it cycle about 20 clocks per bit (or better!). As discussed at the end of the thread, a 'dirt simple' sequence of PORTx_PTOR 'toggles' can certainly toggle at full core-clock speed.
Thanks, Earl. I feel the same way about everything you have said here. I'll likely eventually go the "dirt simple" route and for now I think it makes sense to mark yours as the correct answer!
Hi, Dave,
I do not know if your question has been answered. let's go back to your original question why the GPIO toggling is slower than expected. As you know that the GPIO toggling is not finished in only one assembly instruction, that is the root cause.
for example, the GPIO toggling instruction:
GPIOC_PTOR|=0x200;
asm("nop");
after the compiling, it is compiled as the following instructions:
GPIOC_PTOR|=0x200; | |||
0x1fff0e74: 0x4836 | LDR.N | R0, [PC, #0xd8] | ; [0x1fff0f50] 0x400ff08c (1074786444) |
0x1fff0e76: 0x6800 | LDR | R0, [R0] | |
0x1fff0e78: 0xf450 0x7000 ORRS.W | R0, R0, #512 | ; 0x200 | |
0x1fff0e7c: 0x4934 | LDR.N | R1, [PC, #0xd0] | ; [0x1fff0f50] 0x400ff08c (1074786444) |
0x1fff0e7e: 0x6008 | STR | R0, [R1] | |
asm("nop"); |
That is why the GPIO toggling is slower than your expected.
Hope it can help you.
BR
XiangJun Rong
THAT detail is 'fundamentally flawed' by the |= operation! These direct-output-control "registers" are intentionally WRITE ONLY -- in that a 'read' ALWAYS returns '0', so as you can imagine an 'or' operation is particularly pointless, and will MASSIVELY slow things down waiting for the read-op to process (not to mention, that code is completely unoptimized -- even reloads the GPIO register address for the second-half). I am truly surprised by how many Freescale examples make this error.
As you can see in that aforementioned thread, Mark and I prove that when the port-address is in a register (as they should be in a fully optimized loop!), each 'write' op completes in ONE core clock.
I've got so many fish to fry that I haven't even reached the optimization phase of my project. :smileyhappy: I'll definitely update this post with my results when I get around to it! Thanks for checking in.
Thanks for the info and suggestion, Earl! So if I understand correctly, configure UART0 (or maybe UART2 since that's clearly available on the FRDM-K22F) for max baud rate at that clock configuration setting, and then have it output a bit pattern and check the frequency with the scope?