This is a very open question, but will give my .02$ worth
Timing code options (I use all of these different approaches)
1) Count instructions - If I am using C I either disassemble or find listing of actual assembly. This gets complicated as you may have several different code paths with different times. Also depending on processor, timing of instructions depends on if the instructions are already in the pipeline... I use this approach on Basic Atom Pros, when I am doing in-line assembly language.
2) Use a system timer. I grab the start time at the beginning of the code I wish to time and grab the end time when it finishes and then print out the time... Often will do this multiple times and get averages, Min's, maxs...
3) Use Logic Analyzer (My favorite way): Depending on what you are timing. If you are wanting to check on timing of specific output, just hook it up and time it. If you are wanting to time code, I use some unused IO pins and at the start of the code change the IO state of 1 (could set high or low or toggle) and at the end change the state (low, high or toggle). If the code has different paths or error conditions, I setup toggles of different IO pins in those paths and then start up the analyzer and run the code.
Making code run at an accurate timing
1) If this is the sole thing that your processor is doing, you would probably get the most accurate and consistent results, if all devices were polled and there were no interrupts. This removes all issues about interrupt propagation delays or unexpected delays while processing your time critical code. You then need to organize your code such that you always start your critical code at the right time. Have it spin until the system timer is at the appropriate value... You then organize the rest of the code, such that you call it every pass or every N passes or queued, such that none of the parts get starved... Lots of options here.
2) Depending on the type of code and the like, run your time time critical code on an interrupt, like lets say a timer interrupt. Depending on how this is setup you can often make this code be uninterruptable... But depending on how long your code runs, this could causes issues like missing characters from USARTS... If you run into issues that with this interrupt the start up time is not accurate enough as it depends on how long it takes for the interrupt to be handled (what instruction was being processed, in another interrupt, in critical section with interrupts disabled). In cases like this I have heard of people who setup their next timer interrupt to interrupt before they actually want their code to start, and then in the interrupt handler, spin until the system timer is at the appropriate time...
That is all for now
Kurt