I have code that aligns the timing of two PWMs so that one has a specific offset from the other. My project has optimizations disabled. I thought that it was working well until I discovered that the offset necessary for proper timing had changed. I was able to reproduce the problem by adding a function call (Test function commented out) well before the time critical functionality of restarting the two timers. The difference between the timing for this example is ~72ns but I've found that other code changes result in larger or smaller differences. Calling the AlignPWMs function again with the default value, using our device's command line interface, produces the same timing. Calling the AlignPWMs function with other values produces offset changes that are consistent with the default value. In summary, until I change the code again, values passed to the AlignPWMs function produce offsets that are consistent with the default value through reset and loss of power.
I've made a number of attempts to determine the cause of the problem hence the use of "__attribute__((aligned(32)))", "__DSB()", "__ISB()" and "__DMB()". Which I've used to attempt to align the code, synchronize instructions and data, and control the order of explicit memory operations. I've also reviewed the disassembly and found that, other than the change for the function call, that the same assembly code is produced.
I believe that there must be something different in the way ARM is handling the two CTIMER_StartTimer function calls that is causing something to change with code changes, but I'm at a loss as to what could be causing it or what I should be doing to correct the problem. Any suggestions would be appreciated. I would also be open to other ways to align the two PWMs.
void Test( void )
{
}
__attribute__((aligned(32)))
void AlignPWMs( uint16_t nOffset )
{
// Test();
/* Disable the global interrupt to guarantee timing */
uint32_t primaskValue = DisableGlobalIRQ();
CTIMER_StopTimer( CTIMER0 );
CTIMER_Reset( CTIMER0 );
CTIMER_StopTimer( CTIMER3 );
CTIMER_Reset( CTIMER3 );
CTIMER0->TC = nOffset;
__DSB(); // Data Synchronization Barrier - completes all explicit memory accesses
__ISB(); // Instruction Synchronization Barrier - flushes the pipeline in the processor
__DMB(); // Data Memory Barrier - Ensures the apparent order of the explicit memory operations
CTIMER_StartTimer( CTIMER0 );
__DMB(); // Data Memory Barrier - Ensures the apparent order of the explicit memory operations
CTIMER_StartTimer( CTIMER3 );
__DMB(); // Data Memory Barrier - Ensures the apparent order of the explicit memory operations
EnableGlobalIRQ( primaskValue );
}