Help! Only 2.6MHz w/RLP, Need 50MHz

I’m working with the STM32F405 microcontroller on the Cerbuino Bee which communicates with another IC in my project through SPI. This IC has a max SPI clock rate of 50MHz. My app does a lot of communication through the SPI and I need to speed up the process. I’m placing the SPI code in RLP but the fastest toggle rate I’ve measured on a GPIO output from the STM32F405 is 2.6MHz using RLP. The STM32F405 spec says that the max GPIO rate is 84MHz. You can see that there’s a lot more IO speed on tap and I’m trying to figure out how to get at it. The 2.6MHz measurement came from using this simple code in a RLP loop which toggles the D0 digital output:
GPIOB ->BSRRL|=(1<<11); // Writes a 1 to the GPIO port bit set register which writes a 1 to the GPIO port output data register
GPIOB ->BSRRH|=(1<<11); // Writes a 1 to the GPIO port bit reset register which writes a 0 to the GPIO port output data register
Does anyone know how to speed up the GPIO output rate faster than 2.6MHz?
Am I doing something wrong? Please help.

@ tdcooper33 - The MCU has a dedicated SPI peripheral which you should be using if you want to achieve the specified speeds. Programmatically bit banging the protocol is not going to be anywhere near the performance if the native peripheral.

If all you require is SPI speed then you should consider using the .NETMF or Gadgeteer SPI classes and then as you identify other areas of the code that are a performance bottleneck you can migrate that code to RLP.

I don’t think the NETMF SPI function with work with SPIs that require 6 address bits and 24 data bits which is what my IC uses. So I was forced to write custom SPI software for this IC. So does anyone know how tho speed up the GPIOs?

@ tdcooper33 - You might need to check the pin configuration, I have not looked what the default speed configuration is for the GPIO peripheral so it might be worth looking into that. If it is using a lower clock speed, configuring it for 100Mhz might do the trick, check the GPIO_InitDef structure.

What chip are you dealing with, I would like to take a look at the protocol, my hope is that you should be able to get it to work with the standard SPI peripheral even if you need to drop down to RLP to use SPI in a way the .NETMF does not/might not support.

I’m using the Cerbuino Bee with the STM32F405RG microcontroller. I’ve read through the data sheet, programming manual, and reference manual and the only setting I could find is to increase the drive level is through a register called GPIOx_OSPEEDR. I didn’t see any difference in toggle rate when I configured the GPIO to max drive level, however the edges looked a little sharper. I think it’s a software issue. I wanted to know if there was a way in RLP to get a faster toggle rate on the GPIO outputs. Why is RLP limiting the output speed of the GPIOs to only 3% of the microcontroller’s specified max output rate?

@ tdcooper33 - At this point I would look at the compiler. Remember the compiler generated code has it’s own overheads.

I would do things in the following order

  1. What optimization level are you using? Make sure you are optimizing for speed. Make sure you are using -O3 which should optimize for maximum speed.

  2. What code is the compiler generating? If all else fails you might need to hand code the toggle routines in Assembly, this is easier than you would expect.

To view the Assembly code, you can pass ‘-save-temps’ which will preserve all the .s files which you can view.

You should be able to find these options in the UI for em:blocks, but I normally use the command line, so I do not know off the top of my head if the -save-temps or equivalent options is available in the UI.

I don’t think SPI has a concept of address. To SPI it’s all just bits on the wire. Are you thinking of I2C?

What chip are you using.
I once also thought that a chip could not be used with builtin SPI.
I tried it anyway and it worked quite well.

A while back I had to interface to a 24 bit SPI device. Here’s a snippet of the code I wrote way back when.

        SPI.Configuration MyConfig = new SPI.Configuration(Cpu.Pin.GPIO_Pin1, false, 0, 0, true, false, 100, SPI.SPI_module.SPI1);
        SPI MySPI = new SPI(MyConfig);

        byte[] txData = new byte[3];
        byte[] rxData = new byte[3];
        byte[] rxDataReverse = new byte[4];

        int MTSPositionUint = 0;
        double MTSOffset = 2 ^ 17;
        //double MTSScale = 5.0 / ((2^18-1)
        double MTSPosition = 0.0;

        while (true)
            MySPI.WriteRead(txData, rxData);
            //Debug.Print("rx 0: " + rxData[0].ToString() + "   rx 1: " + rxData[1].ToString() + "   rx 2: " + rxData[2].ToString() 
            //                + "    In Hex rx 0: " + rxData[0].ToString("X") + "   rx 1: " + rxData[1].ToString("X") + "   rx 2: " + rxData[2].ToString("X"));

That code sets the clock to 100 kHz but I remember testing it at 1 MHz and maybe even faster on a Spider board. If I get a chance, I’ll run it again to see how fast i can go.

Yes thank you these are all great suggestions.
I’m looking into the on-chip SPI in the STM32F405 microcontroller right now. It looks like I’ll get best performance out of the on-chip SPI if I can get it to work. I’ll keep you all posted.
Thanks again

Using the internal SPI peripheral of the STM32F405 microcontroller at max buad rate gave me the highest clock rate I’ve measured on my scope which is 42MHz. This value matches the max value found in the datasheet. This rate is almost ideal as the IC I’m communicating with has a max SPI clock rate of 50MHz. Now let’s see if it’ll communicate with the IC. Thanks for the great suggestions guys! I’ll keep you all posted.