cancel
Showing results for 
Search instead for 
Did you mean: 

Toggling a GPIO pin at 50 + MHz

con3
Senior
Posted on November 06, 2017 at 16:22

The original post was too long to process during our migration. Please click on the attachment to read the original post.
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on November 07, 2017 at 14:22

Looks very much like you're hitting the limits of your measurement setup, i.e. scope bandwidth and (more probably) probe bandwidth - unless there's some limitation imposed by the PCB and/or connected circuitry, too.

Is it a 1:10 probe?

Also, from which memory are you running? Did you confirm your system clock runs at the frequency you assume it does?

JW

View solution in original post

26 REPLIES 26
S.Ma
Principal
Posted on November 06, 2017 at 16:43

You should use a high speed timer output compare to run a GPIO at this high speed (beware of signal integrity), and make sure the GPIO speed (slew rate) is programmed as appropriate.

With SPI, you can easily get 27 or 54 MHz (with good PCB)

Posted on November 06, 2017 at 17:22

Don't use XOR it will burn a lot of cycles doing reads and writes which can't be pipelined. Do writes to BSRR to set and then clear the GPIO, and unroll the loop.

Use a TIM to output toggling signals.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 06, 2017 at 17:11

Try an unrolled sequence of

while (1)

{

  GPIOC->ODR = GPIO_PIN_9;

  GPIOC->ODR = 0;

  GPIOC->ODR = GPIO_PIN_9;

  GPIOC->ODR = 0;

  GPIOC->ODR = GPIO_PIN_9;

  GPIOC->ODR = 0;

  GPIOC->ODR = GPIO_PIN_9;

  GPIOC->ODR = 0;

  GPIOC->ODR = GPIO_PIN_9;

  GPIOC->ODR = 0;

  GPIOC->ODR = GPIO_PIN_9;

  GPIOC->ODR = 0;

}

Jump at the end of the while(1) loop may take surprisingly long, especially if run out of uncached FLASH. The read-modify-write operation (xor) takes some time, too. 

JW

PS. I wonder what exactly in this post triggered moderation...

Posted on November 07, 2017 at 11:15

Just to double check, something like this:

while (1)

{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

GPIOC->BSRR = (1<<9);

GPIOC->BSRR = (1<<25);

}

I just want to check how fast I can actually do this in the main. 

+

SYSCFG->CMPCR = 0x1;

Cause something seems odd to me, I've tried using an external interrupt, but the fastest I could get it to react to a signal was 800 kHz, so just checking the code execution with the amount of assembler lines.

Posted on November 07, 2017 at 12:03

That's about 200 cycles, not surprising at all.

The inherent entry/exit is two dozen cycles, pending stack is in single-cycle-access memory. Add to that prologue and epilogue added by compiler plus whatever processing happens in the ISR. Can get down to say 3-4 dozens of cycles if you can run it from single-cycle-execution memory like the TCM RAM.

JW

Posted on November 07, 2017 at 12:21

JW thank you for the confirmation and help.

By just doing the above code, with the BSRR, I can do 22Mhz from the main while loop. I just want confirmation that this should indeed be the maximum that I can hit running from the main while? My supervisors have informed me that I should get 50 MHz minimum by doing this due to the fast clock speed. I just want to be 100% sure before returning to them.

After this the question will be closed. 

Posted on November 07, 2017 at 12:24

Both I and Clive told you to unroll, i.e. repeat the set/reset lines 'manually'. The jump at the end of the loop may be costly.

Look at the resulting waveform by a LA or oscilloscope (no excuses accepted).

JW

Posted on November 07, 2017 at 13:16

Hi JW,

My apologies, I did do this, but forgot to show it in the code. Here's what I get with the compensation cell active:0690X00000604CPQAY.jpg

Here's what I get without the compensation cell:

0690X00000604CQQAY.jpg0690X00000604CRQAY.jpg

Without the compensation cell. it definitely looks like its struggling, although the comp cell slows it down to ~6 MHz.

Here's the code 

SYSCFG->CMPCR = 0x1;

while (1)

{

GPIOC->ODR = GPIO_PIN_9;

GPIOC->ODR = 0x0;

GPIOC->ODR = GPIO_PIN_9;

GPIOC->ODR = 0x0;

GPIOC->ODR = GPIO_PIN_9;

GPIOC->ODR = 0x0;

GPIOC->ODR = GPIO_PIN_9;

GPIOC->ODR = 0x0;

GPIOC->ODR = GPIO_PIN_9;

GPIOC->ODR = 0x0;

GPIOC->ODR = GPIO_PIN_9;

GPIOC->ODR = 0x0;

}

Posted on November 07, 2017 at 13:32

Using just the 

while (1)

{

GPIOC->ODR ^= GPIO_PIN_9;

}

I get the following:

0690X00000604CUQAY.jpg