CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Different speed for different ports
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
RBuilder



Joined: 27 Oct 2011
Posts: 10

View user's profile Send private message

Different speed for different ports
PostPosted: Tue Mar 20, 2012 9:18 am     Reply with quote

Hello,

I noticed something very unusual for me. I wrote a software write serial function. I notice there is a speed difference between pin_Do vs pin_D7.

Although, I checked the asm and the code being generated does seem correct.

Pin_A0, Pin_B0, Pin_C0, Pin_D0 are all faster than Pin_A7, Pin_B7, Pin_C7 and Pin_D7.

Could the method of referencing the BIT within the BYTE be the speed issue? Or does the hardware have different latency on higher port bits than lower port bits?

Also, is it possible to modify a port for input/output on a per BIT basis when using Fast I/O? For example, can I set Pin_D6 to Input without having to re-modify the other bits within the port for that TRIS?

Code:

   #bit bit1 = c.0
   #bit bit2 = c.1
   #bit bit3 = c.2
   #bit bit4 = c.3
   #bit bit5 = c.4
   #bit bit6 = c.5
   #bit bit7 = c.6
   #bit bit8 = c.7

      disable_interrupts(GLOBAL);
     
      output_low(port); // start bit   
      delay_us(delay);
     
      output_bit(port, bit1);
      delay_us(delay);
      output_bit(port, bit2);
      delay_us(delay);
      output_bit(port, bit3);
      delay_us(delay);
      output_bit(port, bit4);
      delay_us(delay);
      output_bit(port, bit5);
      delay_us(delay);
      output_bit(port, bit6);
      delay_us(delay);
      output_bit(port, bit7);
      delay_us(delay);
      output_bit(port, bit8);
      delay_us(delay);
     
      output_high(port); // stop
      delay_us(delay);
     
      enable_interrupts(GLOBAL);           
RBuilder



Joined: 27 Oct 2011
Posts: 10

View user's profile Send private message

PostPosted: Tue Mar 20, 2012 11:43 am     Reply with quote

Hello, also ..

I think i see how to set the tris direction without modifying the entire port... I can use Output_Float (for input) and Output_Drive (for output)?

I notice that Output_Float() works great when i pass in a variable respresenting the port... However, Output_Drive() has a bug that requires a constant.
RBuilder



Joined: 27 Oct 2011
Posts: 10

View user's profile Send private message

PostPosted: Tue Mar 20, 2012 12:42 pm     Reply with quote

I data logged a 12.8us timer turning on and off 20 i/o with fast and general and in the main thread counted from 0 to 800000.

With fast i/o it took 4.5400 seconds
With general purpose it took 4.5425
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 20, 2012 2:18 pm     Reply with quote

If you want help, you need to post a complete test program. For example
in your code, you don't tell show the declaration of 'port'. You also don't
tell us your PIC, or your oscillator frequency.

This thread discusses how to speed up software SPI loop code:
http://www.ccsinfo.com/forum/viewtopic.php?t=46142
Notice that the program I posted is a complete test program.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Mar 20, 2012 2:26 pm     Reply with quote

RBuilder wrote:
With fast i/o it took 4.5400 seconds
With general purpose it took 4.5425
I don't understand your method of measurement, but a difference of 0.055% is insignificant. This difference is well within normal error margins for measurements, for example a temperature difference would explain it.

Off topic: I hate it that often a thread hasn't been responded to for more than an hour, and then just the five minutes it takes me to read the post and type an answer somebody posts the same answer I was going to send. Rolling Eyes
RBuilder



Joined: 27 Oct 2011
Posts: 10

View user's profile Send private message

PostPosted: Tue Mar 20, 2012 4:50 pm     Reply with quote

PCM programmer wrote:
If you want help, you need to post a complete test program. For example
in your code, you don't tell show the declaration of 'port'. You also don't
tell us your PIC, or your oscillator frequency.

This thread discusses how to speed up software SPI loop code:
http://www.ccsinfo.com/forum/viewtopic.php?t=46142
Notice that the program I posted is a complete test program.


Okie dokie. It's a 18f4685 @ 40 mhz (H4)

The rest of the code is too long so i'll just summarize again.

If i output_high(pin_a0), it is faster than if i output_high(pin_a7). Do you know why?

It appears all ports behave the same way. The lower the bit on the port responds faster than the higher bits.

Ckielstra, the 0.055% is actually a HUGE difference because at a 12.8us timer, that's quite a few clock cycles Smile
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 20, 2012 4:53 pm     Reply with quote

What's your CCS compiler version ? It's a 4-digit number given at the
top of the .LST file, which will be in your project directory after a
successful compilation. Examples of version numbers:
http://www.ccsinfo.com/devices.php?page=versioninfo
RBuilder



Joined: 27 Oct 2011
Posts: 10

View user's profile Send private message

PostPosted: Tue Mar 20, 2012 5:03 pm     Reply with quote

PCM programmer wrote:
What's your CCS compiler version ? It's a 4-digit number given at the
top of the .LST file, which will be in your project directory after a
successful compilation. Examples of version numbers:
http://www.ccsinfo.com/devices.php?page=versioninfo


4.105

I took a screenshot of the oscilliscoped output. I have no where to store the image though.

I set the delays for Pin_d0 to bit bash 9600 baud serial from that real basic code i printed earlier. The delay i used comes out to be absolutely PERFECT timing for Pin_d0 @ 9600 .. The width of each pulse is exactly 0.104ms..

But then I do the exact same code but switch to Pin_d7 and the width of each pulse is now 0.106ms

That's a huge difference - and it's consistent. And even stranger, the same code on Pin_d3 (which is half way) is 0.105ms

LOL, it's totally confusing me. I didn't know there was a physical latency on the hardware based on the bit of the port.

Edit: PS I am using Fast I/O also. There are no timers running in the background, as you can see from my above code, i disable them.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 20, 2012 5:22 pm     Reply with quote

Quote:
I have no where to store the image though.

http://www.imageshack.us

Then post a link to it.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Tue Mar 20, 2012 6:50 pm     Reply with quote

Unexplained #bit and other VAR defines aside ---

is this not a a very primitive way to try to output a serial baudot code bit stream ?? ie: generate software rs232 style bit bang output ??

and the complaint, if I decode it right - is that the poster believes
the delay_us function works differently when used on different pins??

There is so much concealed that its hard to have much of an idea of what, if anything - might be wrong - other than surely, at least the basic concept behind this listing. I sure need a define for

c
PORT
DELAY

to even begin to know what could be at issue.

Very Happy Very Happy
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Mar 21, 2012 12:49 am     Reply with quote

RBuilder wrote:
Ckielstra, the 0.055% is actually a HUGE difference because at a 12.8us timer, that's quite a few clock cycles Smile
I disagree. A small percentage error remains small, whatever your clock is. That's why a percentage is such a nice way of indicating value differences.
0.055% speed error equals to 1 instruction difference out of every 1818 instructions.

Unless, of course, I am misunderstanding your test method. Reading your test method again it is not clear to me what you are measuring and how you do it.

One minor suggestion in your code is to not to define bit1 as c.0. In electronics it is common practice to start numbering bits from 0. An other person reading your code could get confused from this (at least I did).
RBuilder



Joined: 27 Oct 2011
Posts: 10

View user's profile Send private message

PostPosted: Wed Mar 21, 2012 12:58 am     Reply with quote

asmboy wrote:
Unexplained #bit and other VAR defines aside ---

is this not a a very primitive way to try to output a serial baudot code bit stream ?? ie: generate software rs232 style bit bang output ??

and the complaint, if I decode it right - is that the poster believes
the delay_us function works differently when used on different pins??

There is so much concealed that its hard to have much of an idea of what, if anything - might be wrong - other than surely, at least the basic concept behind this listing. I sure need a define for

c
PORT
DELAY

to even begin to know what could be at issue.

Very Happy Very Happy


okay here

hook up an oscilliscope to your pic. run this code and look at the length of time of the low pulse.

Code:

void blah() {
 
  int16 port  = pin_d0;
  int    delay = 100;

  while (true) {

    output_bit(port, 1);
    delay_us(delay);
    output_bit(port, 0);
    delay_us(delay);
    output_bit(port, 1);
    delay_us(delay);
  }
}


now run this and look at the length of time of the low pulse.

Code:

void blah() {
 
  int16 port  = pin_d7;
  int    delay = 100;

  while (true) {

    output_bit(port, 1);
    delay_us(delay);
    output_bit(port, 0);
    delay_us(delay);
    output_bit(port, 1);
    delay_us(delay);
  }
}


now see? the same code on the same port and different bits results in two different speeds. i never accused the delay of being different because that would be completely silly Smile

the higher the bit of that port, the more latency there is.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Wed Mar 21, 2012 3:14 am     Reply with quote

You are confusing things by even having the delay there.
All you need to show what you are talking about, is:
Code:

   int16 pin_no;
   int8 count;
   do {
       pin_no=PIN_D0;
       for (count=0;count<100;count++) {
          output_bit(pin_no,1);
          output_bit(pin_no,0);
       }
       pin_no=PIN_D7;       
       for (count=0;count<100;count++) {
          output_bit(pin_no,1);
          output_bit(pin_no,0);
       }
    } while (TRUE);

The answer is 'yes'. Of course it'll take different time.
Even if you wrote it directly in assembler, it would. There is no inbuilt instruction in the PIC, to access a bit by a number stored in a variable. So the compiler has to convert the bit number into a mask, using rotation, and the further up the byte the bit is, the more rotations are needed, so the more time.
You need to rethink what you are actually trying to do.

If (for instance), you are using a variable because you want the same code to talk to two port bits, then just use a single bit variable as a flag, and use two hard coded output instructions.
So:
Code:

#define USE_PIN_D7 (1)
#define USE_PIN_D0 (0)
#define OUTPUTHIGH_TO_PIN(x) if(x) output_high(PIN_D7); else output_high(PIN_D0)
#define OUTPUTLOW_TO_PIN(x) if(x) output_low(PIN_D7); else output_low(PIN_D0)

   int1 pin_flag;
   int8 count;
   do {
       pin_flag=USE_PIN_D7;
       for (count=0;count<100;count++) {
          OUTPUTHIGH_TO_PIN(pin_flag);
          OUTPUTLOW_TO_PIN(pin_flag);
       }
       pin_flag=USE_PIN_D0;       
       for (count=0;count<100;count++) {
          OUTPUTHIGH_TO_PIN(pin_flag);
          OUTPUTLOW_TO_PIN(pin_flag);
       }
    } while (TRUE);   


Realistically, if timing is critical, one also has to ask if software is the right tool for what you are trying to do. This is what things like hardware UART's, and timers are for. If you perform the timings using a hardware timer, then varying latencies in the bit accesses have no effect.
Another alternative, is to perform the masking yourself. If you look at many standard examples for doing bit accesses, people generate the mask _once_ when the code is called, and then just perform a bytewide access using this mask when needed, so the timings remain constant.
This is a case of needing to understand the abilities and limitations of the hardware you are using, and working within these.

Best Wishes
RBuilder



Joined: 27 Oct 2011
Posts: 10

View user's profile Send private message

PostPosted: Wed Mar 21, 2012 5:20 pm     Reply with quote

Great that is a nice response. Thanks for taking the time.

The thing is, this actually comes from a timer experience also. output_high(pin_d7) is slower than output_high(pin_d0) even when in a timer, and even when it's the only thing in the timer.

When i scope the pulse widths, they're identical in pin_d0 and pin_a0 and pin_b0. Then when I do the same with pin_d7, pin_a7, pin_b7, the time are equally the same but higher than lower bits of the same ports.

I've even tried using assembler instead of CCS. And they're the same also (i.e. BCF 0xF8C.7, BSF 0xF8C.7) is slower vs (i.e. BCF 0xF8C.0, BSF 0xF8C.0)

It seems that higher bits of a port respond slower by a few microseconds. I'm surprised no one else has experienced it.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 21, 2012 5:24 pm     Reply with quote

Quote:
output_high(pin_d7) is slower than output_high(pin_d0) even when in a timer

You should be able to post a super-short compilable test program so
we can test this.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group