uCOS interfering with timing on MOD54115 ?

Discussion to talk about software related topics only.
fd9750
Posts: 40
Joined: Fri Mar 29, 2013 8:08 am
Location: Belgium

uCOS interfering with timing on MOD54115 ?

Post by fd9750 »

Hi,

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									");
}
versamodule
Posts: 14
Joined: Fri Jun 08, 2012 4:59 am

Re: uCOS interfering with timing on MOD54115 ?

Post by versamodule »

I have never tried this myself but it may shed some light on the situation.
How about starting a new project and do not use the calls that start the OS.
Just have your asm routine in main only. then run it.

You will of course loose the ability to update it via Ethernet after this, however you can just short the two pins next to the ethernet socket and hitting reset. This will get you the alternate monitor running then you can upload via Ethernet.
User avatar
pbreed
Posts: 1091
Joined: Thu Apr 24, 2008 3:58 pm

Re: uCOS interfering with timing on MOD54115 ?

Post by pbreed »

How are your chip selects setup? IE what chipselct delay do you have?

Are you doing this in debug or release mode?

If your running with the debugger enabled there is a non-mask able interrupt enabled.

To make this run fast you will probably have to move the code into SRAM as if other things like
ethernet are running the ethernet DMA may steal the DDR bus to process packets....
fd9750
Posts: 40
Joined: Fri Mar 29, 2013 8:08 am
Location: Belgium

Re: uCOS interfering with timing on MOD54115 ?

Post by fd9750 »

I am running it both in debug and release mode and I can't really see any difference.
From reading the documentation I noticed that while in debug mode there is a unmaskable interrupt which could cause a problem.
The fact that I do not see any difference between debug and release indicates that there is an unmaskable interrupt which runs in both cases. It does not gel though with the fact that there is an example from Netburner that clearly states they can achieve 16 ns timing on toggling an I/O pin which they do by doing two consecutive writes to the pin's toggle register.
That suggests move instructions take 8 ns to execute.

As to the Chip select setup: I introduce 1 wait cycle and that checks out perfectly well: the external bus works at fsys/2 (125MHz, 8 ns period). Without wait states the chip select is +/- 8 ns, with one wait state it is +/- 16 ns, exactly what I need. I willl check out the SRAM possibility. that might be the trick.
User avatar
pbreed
Posts: 1091
Joined: Thu Apr 24, 2008 3:58 pm

Re: uCOS interfering with timing on MOD54115 ?

Post by pbreed »

I've spent a lot of time hunting down latency recently on the MOD54415...

This is not an interrupt or NMI problem.
\If you are running the release version and are after a USER_ENTER_CRITICAL there is not interrupt happening and the code runs just as it would
without any RTOS or anythign else.


If you put it into a small loop are subsequent runs through the loop faster?

IE if you execute this code just once then the first time through is a cache miss and
it must open a new DDR session to acquire the code its running to execute...
the second time through in a small loop this should all be in cache and would be quicker...

Here is my code to put a small assembly lang chunk in SRAM...
First the core of the .s assembly lanuage file...
.text
.global my_func
.global my_end_func
my_func:
WORKING CODE GOES HERE
my_end_func:



Here is the code that puts it in sram...

//Declare a block to live in SRAM to put the code in....
DWORD CopyBlock[64] __attribute__(( aligned( 4 ))) FAST_SYS_VAR;


extern "C"
{
void my_func(void);
void my_end_func(void);
}


//Copy the function into SRAM...
PDWORD pdws=(PDWORD)&my_func;
PDWORD pdwe=(PDWORD)&my_end_func;
int n=0;

while(pdws<pdwe) CopyBlock[n++]=*pdws++;


To call the function...
asm(" jsr CopyBlock");

or you could set up a function pointer if your routine needs parameters...
User avatar
dciliske
Posts: 624
Joined: Mon Feb 06, 2012 9:37 am
Location: San Diego, CA
Contact:

Re: uCOS interfering with timing on MOD54115 ?

Post by dciliske »

Given that 400 nanoseconds is too great of a delay for your application, I would recommend you look at implementing this using the DMA timers and a free-running A/D. The DMA Timers can be set to trigger a DMA transfer upon external input.

The basic idea is that you allocate some amount of buffer space in SRAM to act as a ring buffer(s) and whenever your trigger occurs it will transfer the data from the register to your SRAM buffer and advance to the next location in the buffer. You can take a look at the PeriodicAD for a framework on how to do this. The main difference is that this example uses a free-running configuration of the DMA timer to trigger the DMA transfer, not an input capture.

One note: if you do use the DMA method, you will need to use version 3 of reference manual for the MCF54415/8. The version 4 manual is woefully inaccurate, and it is physically impossible to configure the eDMA module using it.

-Dan

[Edit] Forgot to mention this: you can find the version 3 manual in this Freescale forum thread: https://community.freescale.com/thread/301921
Dan Ciliske
Project Engineer
Netburner, Inc
fd9750
Posts: 40
Joined: Fri Mar 29, 2013 8:08 am
Location: Belgium

Re: uCOS interfering with timing on MOD54115 ?

Post by fd9750 »

This is interesting: for testing I compiled the RapidGPIO example that came with the latest version of the netburner Tools ( 2.6.2). Loaded it into the module, checked how it was performing and sure enough it manages to produce a neat square wave with at a 16 ns interval which begs the question: what is the difference ?
fd9750
Posts: 40
Joined: Fri Mar 29, 2013 8:08 am
Location: Belgium

Re: uCOS interfering with timing on MOD54115 ?

Post by fd9750 »

Hi,

This is getting sillier by the minute. I have modified the Pulse50 function in the RapidGPIO example by adding a section to it as follows:

Code: Select all

void Pulse50()
{
   USER_ENTER_CRITICAL();  // Do not allow other task or interrupts
  // added section: begin
  asm("movea.l 	#0x02000000,%a0		");	// set a0 to ADC address 1
  asm(" move.w   	%a0@,%d0				");
  asm("movea.l 	#0x02010000,%a0		");	// set a0 to ADC address 2
  asm(" move.w   	%a0@,%d0				");
  asm("movea.l 	#0x02020000,%a0		");	// set a0 to ADC address 3
  asm(" move.w   	%a0@,%d0				");
  //addded section: end
   asm(" move.l #0x8C00000E,%d0");  // Move toggle register address into d0
   asm(" move.l %d0,%a5");          // Move toggle register address into a5
   asm(" move.l #0x01,%d5");        // Move RGPIO 0 into d5

   // The following asm code sets the toggle register bit RGPIO 0
   asm(" move.w %d5,%a5@");//0
   asm(" move.w %d5,%a5@");//1
   asm(" move.w %d5,%a5@");//2
   asm(" move.w %d5,%a5@");//3
   asm(" move.w %d5,%a5@");//4
   ...
   ..
   .
As far as I can tell the code to read the AD values, and thereby generating the associated chip select signals, is pretty much the same as the code which handles toggling the I/O pin.
The only real difference is the additional reloading of a0 and the direction of data transfer.

The result I get is just weird: between each chip select I see gaps of +/- 80 ns. After the last chip select there is a gap of 32 ns before it starts toggling the GPIO pin. From the moment it starts doing that it happily toggles the pin at the specified rate of 16 ns.

It's almost as if activating the chip select simply throws a spanner in the processor's works and slows it down for a while.

I am beginning to feel tempted to generate the chip selects myself using RapidGPIO toggling on a pin, maybe that would do something useful.
rnixon
Posts: 833
Joined: Thu Apr 24, 2008 3:59 pm

Re: uCOS interfering with timing on MOD54115 ?

Post by rnixon »

Could it be that the rapid gpio module on the processor operates differently from the hardware level to achieve the faster speeds?
fd9750
Posts: 40
Joined: Fri Mar 29, 2013 8:08 am
Location: Belgium

Re: uCOS interfering with timing on MOD54115 ?

Post by fd9750 »

Rapid GPIO definitely works at another level. For starters it uses a different internal bus than it does for "normal" GPIO.

In the mean time I think I have figured it out and Netburner support says it is probably right.

If I do sequential toggling of the rapid GPIO pin I see 16 ns between two toggle events. If I stick the transfer instruction in between I get to see 80 ns. Net result: the total time taken by the transfer takes 64 ns (80-16). 40 ns of that is due to the normal foreseen flow for the read operation (4 standard cycles + 1 wait state). That leaves 24 ns for the processor to read the instruction, decode, switch from one bus to the other etc...

Now that I have an idea as to what is going on I will use the suggestion to put the tiny bit of code in SRAM and try to make it work. If I do get it to work I will provide an outline of how I finally did it. ;)
Post Reply