What's the fastest clock you have generated on a GPIO pin of an ARM dev board - Page 1
Forum section: electronics / general

author: photon
author_rank: Frequent Contributor
timestamp: December 30, 2015, 02:53:54 am
content: Has anyone been able to bit bang a 20 MHz clock on any arm dev board ? If so, could you share your arm board. I would like this to be done with a program, rather than assembly code, and look like:while(1) {write GPIO 1;write GPIO 0;}

author: miguelvp
author_rank: Super Contributor
timestamp: December 30, 2015, 03:43:52 am
content: C vs Assembly vs Verilog:In other words, use hardware not softwareEdit: I can get 80MHz using a clock instance module (controlled by software) and using an external precise clockhttp://www.cypress.com/file/127816/downloadon this prototyping board:http://www.cypress.com/documentation/development-kitsboards/cy8ckit-059-psoc-5lp-prototyping-kit-onboard-programmer-and

author: Howardlong
author_rank: Super Contributor
timestamp: December 30, 2015, 04:41:11 am
content: On the LPCLink2 you can toggle GPIO at core speed (ie, above code compiles to three instructions/four cycles in the loop then 204MHz/4) from recollection if you run your code from RAM and ensure instructions are word aligned. You can also see the 204MHz clock frequency if you configure the clock routing appropriately.

author: Howardlong
author_rank: Super Contributor
timestamp: December 30, 2015, 07:11:25 am
content: Setting -O3 optimization, this generates a 50.5MHz toggle on the LPCLink2.Code:#define LED0_PORT 0#define LED0_PIN 8int main(void){LPC_GPIO_T *pGPIO=(LPC_GPIO_T *)0x400F4000;SystemCoreClockUpdate();Board_Init();while (1){pGPIO->B = 1;pGPIO->B = 0;}return 0;}

author: photon
author_rank: Frequent Contributor
timestamp: December 30, 2015, 07:55:45 am
content: Quote from: Howardlong on December 30, 2015, 07:11:25 amThat is the fastest I have heard of with a C program. What was the speed difference between -O0 (default) and -O3? I assume gcc compiler?

author: photon
author_rank: Frequent Contributor
timestamp: December 30, 2015, 08:05:22 am
content: Quote from: miguelvp on December 30, 2015, 03:43:52 amThat is a good video and interesting technique! I have heard of FPGA compilers for C programs but did not know if the implementations were far enough along to be useful. Is there a way in PSOC to express the RTL in C? I am wondering how to run something that is expressed partially in C and partially in RTL.

author: miguelvp
author_rank: Super Contributor
timestamp: December 30, 2015, 08:42:07 am
content: Quote from: photon on December 30, 2015, 08:05:22 amMaybe not with the flipflop and the not gate, but they do have frequency dividers or the clock that is totally programmable.It's not a full FPGA, it's pretty mundane even comparing to CPLDs but more than capable for doing pulse trains at the full CPU clock and you can make custom components with APIs exposing the functionality to C and the ARM Cortex M3 processor.For example you can implement a full PLL to sync signals:http://www.edn.com/design/analog/4411037/1/Demystifying-the-PLLEdit: changed link to point to the first page instead of the 4th page.or my current project of driving a VGA monitor with a 40 MHz pixel clock:https://www.eevblog.com/forum/projects/no-bitbanging-necessary-or-how-to-drive-a-vga-monitor-on-a-psoc-5lp-programmabl/I have not done the C API yet because it does require doing custom datapaths within verilog, but they have components that are fully C accessible already.Not a cheap chip at $10 quantity 1000 but the prototyping board at $10 is a steal.Again I would use at least a Ceramic Oscillator instead of the built it Oscillator like this one:https://www.sparkfun.com/products/92That would give you an accuracy hopefully better than 50,000 PPM.A Crystal Resonator will be better at 1,000 PPM but they didn't leave space for the load capacitors, but you can bodge them in the part.The best the built in oscillator can do is 1% or 100,000 PPMSo depending on how much clock drift you can live with, then again they do have full USB support with the internal oscillator and that works fine, so it's not that bad.

author: photon
author_rank: Frequent Contributor
timestamp: December 30, 2015, 08:59:20 am
content: Cool project post and chip.

author: dannyf
author_rank: Super Contributor
timestamp: December 30, 2015, 11:52:01 am
content: QuoteOn ARM chips that support bitbanding or port inversion, flipping a pin is a one-instruction operation so it should approach 1/2 of the bus speed.However, the loop overhead will be significant in your code so the best is to repeat the code sequence, like this:Code:while (1) {PORT_INV = 1; //flip the pinPORT_INV = 1; //flip the pinPORT_INV = 1; //flip the pin...PORT_INV = 1; //flip the pinPORT_INV = 1; //flip the pinPORT_INV = 1; //flip the pin}

author: 0xdeadbeef
author_rank: Super Contributor
timestamp: December 30, 2015, 11:59:48 am
content: Better use DMA. On e.g. an LPC1768 you can create linked DMA transfers that can be also cyclic without further CPU intervention.

author: Brutte
author_rank: Frequent Contributor
timestamp: December 30, 2015, 10:38:51 pm
content: Not sure about other ARM architectures but on ARMv7-M data write asm("str") to dbus always takes two clocks. However, if the access is consecutive then it can fold to one clock. So str+str takes three, not four clocks, and so on.Then, once in a while you have to roll over the str loop ( branch takes at least 2 clocks, if taken).So you will never get a true square PWM faster than HCLK/8 from ARMv7-M as there are 4 clocks needed from time to time. However, if that is a "cheated square" you are asking about then you can go with HCLK/2 max on this architecture.These are core constraints. That does not mean you cannot get a lower max PWM frequencies when for example slow memory is overloaded with str, filled with extra nops or when a GPIO is wired to APB.

author: andersm
author_rank: Super Contributor
timestamp: December 30, 2015, 11:09:19 pm
content: Quote from: Brutte on December 30, 2015, 10:38:51 pmIsn't that's down to the core, not the architecture?The Cortex-M0+ has an optional single-cycle I/O port, on those you can change a pin every cycle (ignoring loop overhead). Of course, they're not clocked very high.

author: Howardlong
author_rank: Super Contributor
timestamp: December 30, 2015, 11:44:36 pm
content: Regarding using programmable logic, DMA, loop unrolling and other fancy stuff, may I remind folks that the OP asked a specific question about a specific loop in C. It's even easier than all of those methods to produce 204MHz by presenting the basic clock on a GPIO if you want to on an LPC4370, and many other devices I am sure if you want to cheatDisassembled version...-O3 code on M4F, 51MHz toggle with 204MHz clock.Code:1400032a: 0x7219 strb r1, [r3, #8]1400032c: 0x721a strb r2, [r3, #8]1400032e: 0xe7fc b.n 0x1400032a <main+18>-O0 18.5MHz, looks like 11 cycles at 204MHz, so there's a stall in three of these instructions:Code:84pGPIO->B = 1;14000392: 0x687b ldr r3, [r7, #4]14000394: 0x2201 movs r2, #114000396: 0x721a strb r2, [r3, #8]85pGPIO->B = 0;14000398: 0x687b ldr r3, [r7, #4]1400039a: 0x2200 movs r2, #01400039c: 0x721a strb r2, [r3, #8]86}1400039e: 0xe7f8 b.n 0x14000392 <main+18>

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: December 31, 2015, 12:16:55 am
content: The achievable rate will depend on the actual device family - one way in which all the vendors of ARM based chips differentiate themselves is in IO implementation as well as other factors that affect I/O performance, like flash read speed etc.e.g. the early NXP(Then Philips) ARMs had very slow IO due to the bus it was placed on, which was then upgraded to be faster in later devices but putting it in the CPU bus.I believe the Cortex parts have pulled in some of the basic IO stuff into the core specification so there is less difference, but there are still likely to be some variations due to other differences.And of course that's before you start looking at the actual code, and compiler differences.Of course if all you want to do is produce a fast clock, you'd use a peripheral to do it in hardware - timer, PWM or whatever, and of course these vary widely between parts.

author: miguelvp
author_rank: Super Contributor
timestamp: December 31, 2015, 12:29:58 am
content: Quote from: Howardlong on December 30, 2015, 11:44:36 pmI guess r1 holds #1 and r2 holds #0strb is 2 clock cycles on the M0 cores as well as in the M4 core.The branch is 1 clock cycle plus the time to refill the pipeline, on the M0 core is 3 cycles, probably the same on the M4 core.That gives you 7 cycles per loop, 2 cycles on, 5 cycles off. Not sure if not having a 50% duty cycle matters to the OP.But that code seems it will provide a 29.142857 MHz signal at 200/7 duty cycle (28.57%)To get 50% you'll need to add 3 nop in between the store instructions giving you a 20.4MHz clock at 50% duty cycle.I guess the nice thing about the LP4370 is that it has 3 total cores, maybe the M0 subsystem core can talk directly to the pins.But why use a full core anyways? How fast can the PWM in the chip be driven at?

author: Howardlong
author_rank: Super Contributor
timestamp: December 31, 2015, 10:02:59 am
content: Quote from: miguelvp on December 31, 2015, 12:29:58 amBefore posting, I specifically physically measured both the -O3 and -0O on real hardware on the scope and they were 51MHz and 18.5MHz respectively with a 204MHz clock. I was going to post the scope screen shots but felt I could be trusted with my findings, maybe notSTRB instructions on M4 are 1 cycle if adjacent. From the M4 Tech Ref:Code:Operation Description Assembler CyclesStore Byte STRB Rd, [Rn, <op2>] 2(b)b. Neighboring load and store single instructions can pipeline their address and data phases.This enables these instructions to complete in a single execution cycleand for our case with an immediate operand:Code:STR Rx,[Ry,#imm] is always one cycle. This is because the address generation is performedin the initial cycle, and the data store is performed at the same time as the next instructionis executing. If the store is to the store buffer, and the store buffer is full or not enabled,the next instruction is delayed until the store can complete. If the store is not to the storebuffer, for example to the Code segment, and that transaction stalls, the impact on timingis only felt if another load or store operation is executed before completion.

author: miguelvp
author_rank: Super Contributor
timestamp: December 31, 2015, 10:29:07 am
content: Ok, but how about the duty cycle?If the strb takes just one clock that means the branch on your measured physical signal is 2 clocks and still unclear if you are using the Cortex M4 or one of the Cortex M0So the duty cycle in that case is 25%, meaning that to get a 50% duty cycle you will need two nops in between the strbs, so it will be 6 cycles per period, of course if the OP requires 50% duty cycle.So to achieve 50% duty cycle you'll end up with 1/6 of 204MHz or 94 MHz.Still pretty good if the I/O pins can switch that fast

author: Howardlong
author_rank: Super Contributor
timestamp: December 31, 2015, 10:30:33 am
content: Quote from: miguelvp on December 31, 2015, 12:29:58 amBecause that's what the OP asked forQuote from: photon on December 30, 2015, 02:53:54 amQuote from: miguelvp on December 31, 2015, 12:29:58 amIndeed. SPIFI clock can toggle at up to 104MHz (max clock), SSP clock at 51MHz. Or, as I mentioned earlier, just route CLKOUT to one of the CLKn or GPIO pins for 204MHz.

author: Howardlong
author_rank: Super Contributor
timestamp: December 31, 2015, 10:34:12 am
content: Quote from: miguelvp on December 31, 2015, 10:29:07 amI may have misunderstood or missed something, but I wasn't aware that control of the duty cycle was a requirement?I am using the M4 core, it's the default core on the LPC4370. Getting one of the M0 cores up and running on an LPC4370 involves quite a bit more fiddling about than I wanted to do for a proof of concept post ;-)

author: Howardlong
author_rank: Super Contributor
timestamp: December 31, 2015, 08:29:08 pm
content: Board is LPC Link2. Scope is Agilent/Keysight MSO7104B 1GHz @ 4GSa/s real time sampling. Probe is Agilent N2874A 1.5GHz 10:1 resistive probe, 500 ohm // 2pF load with spring ground.Code:#include "board.h"#define LED0_PORT 0#define LED0_PIN 8int main(void){LPC_GPIO_T *pGPIO=(LPC_GPIO_T *)0x400F4000;SystemCoreClockUpdate();Board_Init();Chip_SCU_PinMuxSet(1,1,SCU_PINIO_FAST | SCU_MODE_FUNC0); // Setup LED pin for fast rise/fall timewhile (1){pGPIO->B = 1;pGPIO->B = 0;}return 0;}204MHz clock output on CLK0 pin measured at TP_CLK0:18.55MHz on pin P1_1(GPIO0) measured at R45, -O0 gcc optimisation:51MHz on pin P1_1(GPIO0) measured at R45, -O3 gcc optimisation:

author: photon
author_rank: Frequent Contributor
timestamp: December 31, 2015, 10:49:53 pm
content: Nice.

author: Sal Ammoniac
author_rank: Super Contributor
timestamp: January 01, 2016, 09:25:39 am
content: Quote from: Howardlong on December 31, 2015, 08:29:08 pmMust be nice to have a $30K scope.

author: Howardlong
author_rank: Super Contributor
timestamp: January 01, 2016, 12:33:10 pm
content: Quote from: Sal Ammoniac on January 01, 2016, 09:25:39 am... especially when it "only" cost $5.7k on an offer made to Keysight's eBay store (171772308652) plus a bit of liberation. N2874A 10:1 1.5GHz resistive probe was $75 on eBay (151761749582).Here are the 204MHz and 51MHz traces with an Agilent 1130A 1.5GHz FET probe with E2676A single ended browser, 25k ohm // 0.67pF ($75 on eBay 151754375999).

author: miguelvp
author_rank: Super Contributor
timestamp: January 01, 2016, 11:37:11 pm
content: That's impressive GPIO switching performance at normal drive.I wonder how low (rise and fall) can you get it if you configure the output pin to be High Speed (page 109)http://www.nxp.com/documents/data_sheet/LPC4370.pdfAlso the price for that Link2 board looks greathttp://www.findchips.com/search/OM13054Are there any limitations on the free LPCXpresso other than been able to debug past 256K?For example do they restrict things like using -O3?

author: Howardlong
author_rank: Super Contributor
timestamp: January 02, 2016, 08:13:01 am
content: Quote from: miguelvp on January 01, 2016, 11:37:11 pmHmm, sorry I thought I'd posted the code in that last post. I did indeed have the high speed on on that pin.Code:#include "board.h"#define LED0_PORT 0#define LED0_PIN 8int main(void){LPC_GPIO_T *pGPIO=(LPC_GPIO_T *)0x400F4000;SystemCoreClockUpdate();Board_Init();Chip_SCU_PinMuxSet(1,1,SCU_PINIO_FAST | SCU_MODE_FUNC0); // Setup pin for fast rise & fall timewhile (1){pGPIO->B = 1;pGPIO->B = 0;}return 0;}Without setting fast IO, you get this:There are no restrictions on the free version other than the 256kB code limit, which is a pretty big program in this end of the embedded world.To develop, note that there is no integrated debugger on the LPC Link2, so to get started, you actually need two, one that acts as debugger and the other that's the target. Each LPC Link2 comes with the appropriate debugging cable. The fine pitch headers are a bit of a PITA as inevitably you have to make your own breakouts, and if you wanted to integrate this board into your own product the cost of the mating connectors for a daughter board isn't cheap.

author: tggzzz
author_rank: Super Contributor
timestamp: January 02, 2016, 09:17:40 am
content: Quote from: photon on December 30, 2015, 02:53:54 amI may be a purist, but that techinque is not useful for determining thefrequencyof aclock. It is useful for determining theminimumintervalbetweentwotransitions.Why?the CPU cannot be doing anything else at all. If interrupts cause it to do something else, then the intervals will obviously be extended. If the clock is only intermittent then there will extra tests in the while clause. If data is to be transmitted then there will be extra statements in the loop body.depending on the CPU, what is/isn't in a cache will cause timing variations, resulting in jitter

author: photon
author_rank: Frequent Contributor
timestamp: January 02, 2016, 08:51:36 pm
content: I opened this thread to find out if it were possible to bit bang a SPI bus at 20 MHz using one of the arm dev boards. I decided to first ask an easier question to find out how fast you can toggle a pin. But, now that this question is answered and you bring up the issues involved, is it possible to bit bang a SPI bus at 20 MHz? Has anyone done this? Even though arm boards have hardware SPI it might be useful to have a software SPI if you want to debug or test another SPI interface by injecting problem cycles, or be able to use a mode of the SPI bus not implemented by the hardware.

author: Brutte
author_rank: Frequent Contributor
timestamp: January 02, 2016, 09:33:06 pm
content: Quote from: photon on January 02, 2016, 08:51:36 pmYes, it is possible. But I doubt anyone tried that when a $2 chip has three hardware SPI modules. If you need fourth SPI, then these are present in $3 chips.

author: Howardlong
author_rank: Super Contributor
timestamp: January 03, 2016, 08:38:46 am
content: Quote from: Brutte on January 02, 2016, 09:33:06 pmI'd tend to agree, if I need to generate time critical 20MHz SPI, then I'd be unlikely to be doing it by bitbanging. That said, if the bitstream was constant and you chose the right GPIO pins on the same port, you could generate 100MHz SPI with bitbanging.

author: photon
author_rank: Frequent Contributor
timestamp: January 03, 2016, 10:08:37 am
content: Quote from: tggzzz on January 02, 2016, 09:17:40 amFor an OS like a PC or Linux, then I agree. For a real-time system interrupts can be masked and latencies controlled. A SPI clock only has to run during a bus transaction. Otherwise it is off. There are no caches, data or instruction, in a Cortex M micro. The term "bare metal" compiler means something here.

author: Howardlong
author_rank: Super Contributor
timestamp: January 03, 2016, 10:24:28 am
content: You need to be a little careful when running from SPIFI flash on the LPC4300 series, except for very trivial things (like the example provided), there is some indeterminism due to the proprietary mechanism used to make the quad SPI flash appear in the memory map like normal memory. There is some caching going on as well as occasional significant wait states on cache misses. The simple way to avoid this is to put the code into one of the RAM segments on a dedicated bus, where the memory runs at core speed (using the RAMFUNC modifier).

author: tggzzz
author_rank: Super Contributor
timestamp: January 03, 2016, 10:27:25 am
content: Quote from: photon on January 03, 2016, 10:08:37 amI agree about the CPU, hence my prefixing the statement with "depending on the CPU". Ditto "If" in the statement about interrupts. I'm fully aware of the implications of bare metal; I've even declined to use the Arduino environment for an atmega328, since I knew I couldn't predict whatassumptionswere in the librariesThe other, more important, points about the CPU not being able to do anything else stands, for the reasons given.Hence this technique is only useful for determining the minimum interval between two transitions - it is not useful for determining the frequency of a clock.

author: jimon
author_rank: Regular Contributor
timestamp: January 03, 2016, 12:30:12 pm
content: Easy to get 120 MHz from stm32f407 by overclocking it to 240 MHz, a bit pointless though.On other hand it's possible to run transmission "bursts" like this - you generate transmission code in RAM, and then jump to it. This could be useful for simpler MCU that doesn't have ability to transmit with DMA.