I am using LPC11C14 board with 12Mhz crystal. Most of ASM instructions are 1 cycle, with entering C function takes 3 cycles and exiting takes 3 cycles.
__asm void test () { //3 cycles MOVS R1, #1 //1 cycle SUBS R1, R1, #1 //1 cycle CMP R1, #0 //1 cycle BEQ endf //3 cycles endf BX lr }
So this function should take exactly 12 cycles which means it should take 1us to execute, but if I use oscilloscope and put gpio turn on-off i get around 3-4uS toggle. Although simulator says that for gpio set/clear it takes 10 cycles, it is still missing some 20 cycles.
LPC_GPIO0->DATA |= (1<<0); test (); LPC_GPIO0->DATA &= ~(1<<0); test (); LPC_GPIO0->DATA |= (1<<0);
I guess issue is somewhere in crystal settings or ? I was looking at settings for main clock, but I couldnt figured out whether it is defaulted to IRC oscillator and how to change it to use external crystal.
If you want to verify crystal frequency, you shouldn't go for this tiny function.
Either configure a timer and set it to 1Hz and let it drive a LED. Then you know if the timer gets the correct input frequency or not.
If you really want to count processor cycles, then you could have a function contain a huge number of nop intrinsics after each other to minimize the relative time spent by the actual loop construct.
Another thing to consider - what speed is the flash running at? The LPC chips have settings to control the MAM feature, i.e. controlling acceleration of flash accesses. You only get one clock cycle per instruction if the memory supplies the machine code data at the full speed the core consumes it.
Another thing to think about when timing is important.
You do:
LPC_GPIO0->DATA |= (1<<0); LPC_GPIO0->DATA &= ~(1<<0); LPC_GPIO0->DATA |= (1<<0);
These are read/modify/write operations requiring multiple machine instructions. And the machine instructions needs to synchronize with the actual GPIO block - the modify can't happen until the read supplies data. The processor has a write queue to allow multiple in-flight writes of GPIO data but that doesn't help on the read.
If you look closer at the GPIO block, you'll notice that the processor has special registers available to set or clear bits. So you don't need any read/modify/write but can just do a single write to set or clear one or more bits of the GPIO port. Without need to synchronize with the read access, you can do the port output at full core speed as long as the write queue has room to cache one more write.
Another advantage is that the write-only route saves code space, since you don't need the read instruction and the modify instruction.
I have measured delay which I achieved by setting the Timer0 to prescale with 12000 and wait until match result is equal to 500. With oscilloscope I saw delay of ~490ms. Which is within few % of error. Which is not that bad, but then if clock is working fine why do I get so much difference when toggle GPIO. I also tested direct assignment to GPIO port instead of append. Generally i achieve better result, but still not that good.
Now it takes 2.5uS to toggle P3.0
LPC_GPIO3->DATA = (1<<0); test(); LPC_GPIO3->DATA = 0; test();
I also maid test10 function which by simulator takes 123 cycles to execute but toggle takes 15.3uS but it should be 10.3uS on 12MHz clock.
I set PLL clock to use crystal, but without effect on timing
LPC_SYSCON->SYSPLLCLKSEL = 0x01; LPC_SYSCON->SYSPLLCLKUEN = 0x00; LPC_SYSCON->SYSPLLCLKUEN = 0x01;
Also, I played with power setting for GPIO, Flash and ROM without any effect as well
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6) | (1<<1)| (1<<3);
As Per mentioned in an earlier post, you should look at the flash timing. The default flash access time is 3 clocks for this device. The default value allows you to run the processor up to 50 Mhz. Since you are only running at 12Mhz, you can set this to 1 clock. Take a look at the Flash Programming chapter in the user manual. Once you set the flash access to 1 clock your timings should be closer to what you are expecting.