I need to read the conversion data from three fast AD converters very quickly one after another so I have implemented a bit of assembly code to do that. (see below).
I have set up the three available external Chip select signals to address each of those AD converters and use the TIP signal to drive an overall enable signal for the combined AD converters.
To make sure The routine always executes without interruption I call USER_ENTER_CRITICAL() before calling the function and call USER_EXIT_CRITICAL() afterwards.
When I observe the TIP signal with my oscilloscope I see a gap of +/- 400 nanoseconds between the first and the second chip select and a gap of +/- 112 nanoseconds between the second and the third chip select signal.
That is really surprising: if the MCF54115 chip runs at 250MHz it should only take 4 nanoseconds for single cycle instructions so where is the 400 nanoseconds coming from ? Even stranger is that if I have full processor time there should not be the slightest difference on the timing between chip selects 1/2 and 2/3 but there is a difference of nearly a factor 4.
Any suggestions on what might be causing this or what else the processor is doing in between the chip select signals?
PS: In the mean time I tried putting the code right between the USER_ENTER_CRITICAL and USER_EXIT_CRITICAL calls and not calling it as a subroutine (just like in the pulse GPIO pin example). Unfortunately that does not make a difference, I am not getting anywhere near the 16 nanosecond toggle speed mentioned in that example. +/- 120 nanoseconds between chip selects Is the best I can get.
Code: Select all
void AssemblyFunctions()
{
asm(" .global ReadADCs ");
asm(" .extern g_pRawPixelData ");
asm(" .extern g_uiPixelCount ");
asm(" ReadADCs: ");
asm(" movea.l g_pRawPixelData,%a1 "); // get pointer to current pixel data location
asm(" movea.l #0x02000000,%a0 "); // set a0 to ADC address 1
asm(" move.w %a0@,%a1@+ "); // read ADC 1, store at pixel location and set to next location
asm(" movea.l #0x02010000,%a0 "); // set a0 to ADC address 2
asm(" move.w %a0@,%a1@+ "); // read ADC 2, store at pixel location and set to next location
asm(" movea.l #0x02020000,%a0 "); // set a0 to ADC address 3
asm(" move.w %a0@,%a1@+ "); // read ADC 3, store at pixel location and set to next location
asm(" move.l %a1,g_pRawPixelData "); // set pointer to current pixel data location
asm(" addq.l #1,g_uiPixelCount "); // increment pixel count
asm(" rts ");
}