#define LED0_PORT 0
#define LED0_PIN 8
int main(void)
{
LPC_GPIO_T *pGPIO=(LPC_GPIO_T *)0x400F4000;
SystemCoreClockUpdate();
Board_Init();
while (1)
{
pGPIO->B[LED0_PORT][LED0_PIN] = 1;
pGPIO->B[LED0_PORT][LED0_PIN] = 0;
}
return 0;
}
Setting -O3 optimization, this generates a 50.5MHz toggle on the LPCLink2.Code: [Select]#define LED0_PORT 0
#define LED0_PIN 8
int main(void)
{
LPC_GPIO_T *pGPIO=(LPC_GPIO_T *)0x400F4000;
SystemCoreClockUpdate();
Board_Init();
while (1)
{
pGPIO->B[LED0_PORT][LED0_PIN] = 1;
pGPIO->B[LED0_PORT][LED0_PIN] = 0;
}
return 0;
}
C vs Assembly vs Verilog:
In other words, use hardware not software
Edit: I can get 80MHz using a clock instance module (controlled by software) and using an external precise clock
http://www.cypress.com/file/127816/download
on this prototyping board:
http://www.cypress.com/documentation/development-kitsboards/cy8ckit-059-psoc-5lp-prototyping-kit-onboard-programmer-and
C vs Assembly vs Verilog:
In other words, use hardware not software
Edit: I can get 80MHz using a clock instance module (controlled by software) and using an external precise clock
http://www.cypress.com/file/127816/download
on this prototyping board:
http://www.cypress.com/documentation/development-kitsboards/cy8ckit-059-psoc-5lp-prototyping-kit-onboard-programmer-and
That 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.
I would like this to be done with a program, rather than assembly code, and look like:
while (1) {
PORT_INV = 1; //flip the pin
PORT_INV = 1; //flip the pin
PORT_INV = 1; //flip the pin
...
PORT_INV = 1; //flip the pin
PORT_INV = 1; //flip the pin
PORT_INV = 1; //flip the pin
}
Not sure about other ARM architectures but on ARMv7-M data write asm("str") to dbus always takes two clocks.
1400032a: 0x7219 strb r1, [r3, #8]
1400032c: 0x721a strb r2, [r3, #8]
1400032e: 0xe7fc b.n 0x1400032a <main+18>
84 pGPIO->B[LED0_PORT][LED0_PIN] = 1;
14000392: 0x687b ldr r3, [r7, #4]
14000394: 0x2201 movs r2, #1
14000396: 0x721a strb r2, [r3, #8]
85 pGPIO->B[LED0_PORT][LED0_PIN] = 0;
14000398: 0x687b ldr r3, [r7, #4]
1400039a: 0x2200 movs r2, #0
1400039c: 0x721a strb r2, [r3, #8]
86 }
1400039e: 0xe7f8 b.n 0x14000392 <main+18>
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 cheat
Disassembled version...
-O3 code on M4F, 51MHz toggle with 204MHz clock.Code: [Select]1400032a: 0x7219 strb r1, [r3, #8]
1400032c: 0x721a strb r2, [r3, #8]
1400032e: 0xe7fc b.n 0x1400032a <main+18>
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 cheat
Disassembled version...
-O3 code on M4F, 51MHz toggle with 204MHz clock.Code: [Select]1400032a: 0x7219 strb r1, [r3, #8]
1400032c: 0x721a strb r2, [r3, #8]
1400032e: 0xe7fc b.n 0x1400032a <main+18>I guess r1 holds #1 and r2 holds #0
strb 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%)
Operation Description Assembler Cycles
Store 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 cycle
STR Rx,[Ry,#imm] is always one cycle. This is because the address generation is performed
in the initial cycle, and the data store is performed at the same time as the next instruction
is 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 store
buffer, for example to the Code segment, and that transaction stalls, the impact on timing
is only felt if another load or store operation is executed before completion.
But why use a full core anyways?
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;
}
How fast can the PWM in the chip be driven at?
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 M0
So 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
#include "board.h"
#define LED0_PORT 0
#define LED0_PIN 8
int 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 time
while (1)
{
pGPIO->B[LED0_PORT][LED0_PIN] = 1;
pGPIO->B[LED0_PORT][LED0_PIN] = 0;
}
return 0;
}
Scope is Agilent/Keysight MSO7104B 1GHz @ 4GSa/s real time sampling.
Scope is Agilent/Keysight MSO7104B 1GHz @ 4GSa/s real time sampling.
Must be nice to have a $30K scope.
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.pdf
Also the price for that Link2 board looks great
http://www.findchips.com/search/OM13054
Are there any limitations on the free LPCXpresso other than been able to debug past 256K?
For example do they restrict things like using -O3?
#include "board.h"
#define LED0_PORT 0
#define LED0_PIN 8
int 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 time
while (1)
{
pGPIO->B[LED0_PORT][LED0_PIN] = 1;
pGPIO->B[LED0_PORT][LED0_PIN] = 0;
}
return 0;
}