Jump to content
43oh

How fast is the IO?


Recommended Posts

The Stellaris GPIOS connect to the core through both the APB and the AHB busses.  The AHB is faster.

 

Use SysCtlGPIOAHBEnable to enable the port you want.  Then for absolute fastest toggle use HWREG(AHB BASE ADDRESS + (pin mask << 2)) = GPIO_PIN_x; // or zero.

 

The pin mask is a feature of stellaris that allows you to add an offset to the base address which becomes a pin mask.  You can then write a single pin of a GPIO port without doing a read modify write.  The hardware only twiddles the pins that set in the mask value.  The right shift by 2 makes each pin mask a unique 32 bit address to write to.

 

I believe with this method you can get a GPIO state change every 2 system clock cycles.  20 Mhz square wave from an 80 Mhz part.

 

Using the Timers in PWM mode is often a better way to make these high speed signals.

 

Also be aware that Stellaris has selectable GPIO drive strength.  Default is 2 milliamps.  Max is 8mA.  To go this fast you may need to up the drive strength.  I know high drive strength is need when doing very high speed SPI signals on the chip.

Link to post
Share on other sites
  • 2 weeks later...

I now got my launchpad, which makes me very excited  :) , especially since I also just got a new scope  :)  :)  so I can see the waveforms. 

 

I've tried setting up the code as you indicated, but I'm not getting more than 4.762MHz. Can you see what I'm doing wrong? 

 

#include <inc/hw_types.h>
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"

int main(void) {

	SysCtlClockSet(SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
	//SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

	SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOF);
	GPIOPinTypeGPIOOutput(GPIO_PORTF_AHB_BASE, GPIO_PIN_3);

	GPIOPadConfigSet(GPIO_PORTF_AHB_BASE,
			GPIO_PIN_3,
			GPIO_STRENGTH_8MA,
			GPIO_PIN_TYPE_STD);

	while (1) {
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_3 << 2)) = GPIO_PIN_3;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_3 << 2)) = 0;
	}
}

 

 

The code uses  GPIOPadConfigSet to set the current draw. I can see the difference in using 2mA and 8mA on the scope's screen. 

 

With 2mA:

 

post-704-14264605173145_thumb.png

 

And with 8mA:
 

post-704-14264605173533_thumb.png

 
And with 8mA+slewratecontrol:
 

post-704-14264605173928_thumb.png

Link to post
Share on other sites

I now got my launchpad, which makes me very excited  :) , especially since I also just got a new scope  :)  :)  so I can see the waveforms. 

 

I've tried setting up the code as you indicated, but I'm not getting more than 4.762MHz. Can you see what I'm doing wrong? 

 

#include <inc/hw_types.h>
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"

int main(void) {

	SysCtlClockSet(SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
	//SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

	SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOF);
	GPIOPinTypeGPIOOutput(GPIO_PORTF_AHB_BASE, GPIO_PIN_3);

	GPIOPadConfigSet(GPIO_PORTF_AHB_BASE,
			GPIO_PIN_3,
			GPIO_STRENGTH_8MA,
			GPIO_PIN_TYPE_STD);

	while (1) {
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_3 << 2)) = GPIO_PIN_3;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_3 << 2)) = 0;
	}
}

To get the CPU to 80 Mhz, you need to set the divisor to 2.5:

SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

 

It looks like the default is 12.5 Mhz (see Table 5-4 in the datasheet)

Link to post
Share on other sites

To get the CPU to 80 Mhz, you need to set the divisor to 2.5:

SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

 

It looks like the default is 12.5 Mhz (see Table 5-4 in the datasheet)

 

Thanks. That helped. The signal became 5MHz. Then I realized I should probably turn on optimization, and then I got 20MHz!  :)

Link to post
Share on other sites

I've now changed the program. The while loop is taking cycles, so without it (I've just repeated up/down a bit inside the while-loop), I'm getting 40MHz output. I can't call it a square wave :-) but it's definitely a fast signal. 4mA drive on this one. There is a noticable delay for the while-loop. Is there a faster way of looping forever?

 

#include <inc/hw_types.h>
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"

int main(void) {

	SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

	SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOF);
	GPIOPinTypeGPIOOutput(GPIO_PORTF_AHB_BASE, GPIO_PIN_3 | GPIO_PIN_4);

	GPIOPadConfigSet(GPIO_PORTF_AHB_BASE,
			GPIO_PIN_3 | GPIO_PIN_4,
			GPIO_STRENGTH_4MA,//GPIO_STRENGTH_8MA, //GPIO_STRENGTH_8MA_SC,
			GPIO_PIN_TYPE_STD);

	while (1) {
		HWREG(GPIO_PORTF_AHB_BASE + ((GPIO_PIN_3 | GPIO_PIN_4) << 2)) = GPIO_PIN_3 | GPIO_PIN_4;
		HWREG(GPIO_PORTF_AHB_BASE + ((GPIO_PIN_3 | GPIO_PIN_4) << 2)) = 0;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_4 << 2)) = GPIO_PIN_4;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_4 << 2)) = 0;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_4 << 2)) = GPIO_PIN_4;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_4 << 2)) = 0;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_4 << 2)) = GPIO_PIN_4;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_4 << 2)) = 0;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_4 << 2)) = GPIO_PIN_4;
		HWREG(GPIO_PORTF_AHB_BASE + (GPIO_PIN_4 << 2)) = 0;
	}
}

 

 

post-704-14264605174321_thumb.png

 

Link to post
Share on other sites

I've now changed the program. The while loop is taking cycles, so without it (I've just repeated up/down a bit inside the while-loop), I'm getting 40MHz output. I can't call it a square wave :-) but it's definitely a fast signal. 4mA drive on this one. There is a noticable delay for the while-loop. Is there a faster way of looping forever?

 

 

attachicon.gif4mA-40MHz.png

 

What is the input capacitance for your scope probes? For fast square waves, I built one of these: http://koti.mbnet.fi/jahonen/Electronics/DIY%201k%20probe/

For this to work, your scope needs to either have a 50 Ohm input mode or you need to use an inline 50 Ohm terminator. This will give you ~1Ghz response for only a couple of $

Link to post
Share on other sites

Interesting topic! I played around with the other direction: reading fast as possible from GPIO and save the values to RAM (see project description http://forum.stellarisiti.com/topic/335-open-nov-dec-2012-stellarisiti-project-of-the-month-contest/?p=1972). I got a maximum sample rate of 10 MHz. Perhaps some of this hints are also useful for reading GPIO instead of toggling!

 

 

Link to post
Share on other sites

Thanks for good input from both.

 

The scope is 200MHz, so would probably partly be the cause of the non-square wave, and the probes are 350MHz. Would be interesting seeing a trace on a faster scope. The max risetime on my scope should be about 1.8ns, which is less than I measure now on the gpio, and much less than the stated chip risetime in the datasheet. So I don't think the scope is the only limiting factor.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...