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.
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.