cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 How to get 50MHz on GPIO

SRobs.1
Associate II

I can only get the GPIO pin to toggle at 8MHz but datasheet indicates 108MHz is possible.

I tried changing OSPEEDRy[1:0] but this did not help, I only get the default 8MHz.

20 REPLIES 20

Agreed :) I'm a hardware guy not very much up on the software

Thanks for the pointers

RMcCa
Senior II

Use a dma channel triggered by a timer with the source a circular ram buffer and the destination the gpio odr. Should do 25MHz no sweat.​

SRobs.1
Associate II

Thanks - that sounds interesting to try​

> I'm not accessing any memory

Yes you do: you are running code which is stored in some memory.

JW

​Ah, yes. I was thinking you meant accessing external memory

Uwe Bonnes
Principal III

0693W000000ThZgQAK.pngWith a long row of similar commands in the while loop like

void RAMFUNC FastToggle(void)
{
    GpioPinConfigSet(NUTGPIO_PORTB, 10, GPIO_CFG_OUTPUT |GPIO_CFG_SPEED_HIGH);
    volatile uint32_t *gpiob_bsrr = &GPIOB->BSRR;
    uint32_t on = (1 << 10);
    uint32_t off = (1 << ( 16 + 10));
    while(1) {
        *gpiob_bsrr = on;
        *gpiob_bsrr = off;
        *gpiob_bsrr = on;
        *gpiob_bsrr = off;
 

I get following scope picture. The one prolonges cycle is when the while loop jumps back:

Running at 216 MHz I get about 202 MHz change rate at the GPIO.

berendi
Principal

> Datasheet simply indicates fast I/Os up to 108MHz is possible

It's possible up to 108MHz as in "Sale! Up to 50% off!". Setting OSPEED ensures that signal rise and fall times are tight enough for 108MHz.

> so I assumed one clock to set and one to clear the state of the pin.

Maybe, if the machine instructions are optimized for that. Data already present in registers, back-to-back str instructions to GPIOx->BSRR.

asm volatile(
    "str %[d1], [%[bsrr]]\n\t"
    "str %[d2], [%[bsrr]]\n\t"
    "str %[d3], [%[bsrr]]\n\t"
    "str %[d4], [%[bsrr]]\n\t"
    :
    :[bsrr]"r"(&GPIOA->BSRR),
     [d1]"r"(0x00000001), // PA0 high
     [d2]"r"(0x00000002), // PA1 high
     [d3]"r"(0x00010000), // PA0 low
     [d4]"r"(0x00020000)  // PA1 low
);

This is as fast as it gets. Using more values than there are registers, counting, looping would slow it down a lot. Oh, and ensure that interrupts are disabled. Put one or more __NOP() calls before it to change alignment. It can work for a few cycles, but not really practical.

> I'm not accessing any memory so I don't know why the ITCM helps me.

Where is your program stored? How does the CPU core know what instruction to execute next? Yes, it has to fetch program instructions from memory.

Sorry for highjacking - this is not pertinent to the topic, but:

volatile uint32_t *gpiob_bsrr = &GPIOB->BSRR;

Why? What's wrong (in context of your program/snippet) with

GPIOB->BSRR = on;

GPIOB->BSRR=off;

?

Thanks,

JW

berendi
Principal

> Use a dma channel triggered by a timer with the source a circular ram buffer and the destination the gpio odr. Should do 25MHz no sweat.​

As long as nothing is holding up the bus, e.g. accessing a slower APB peripheral from the MCU through the AHB-APB bridge.

To eliminate any jitter, it has to bypass the GPIO registers somehow. Maybe abusing the LTDC of FMC for the purpose.

LTDC would be ideal if you don't have an actual display, after all it is designed to put the contents of the framebuffer memory out to a parallel interface at an adjustable rate. The only problem is that it thinks in terms of scanlines and frames, and it might enforce some minimal horizontal and vertical blanking periods.

Using FMC might be possible if there is no memory or other peripheral connected to it, it should be possible to work out the FMC timings for 25 MHz, and copy data using DMA2 from SRAM2 to FMC.

Great support, thanks

I inherited the firmware and just use a python API to stream data to the GPIO.

This is a new MCU for us.

Seems I need some hep at the low level to modify the firmware.

I appreciate all the pointers and I'll pass on suggestions to my firmware team.