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

how to redefine putc?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
slavka012



Joined: 10 Feb 2012
Posts: 28

View user's profile Send private message

how to redefine putc?
PostPosted: Mon Nov 17, 2014 10:50 am     Reply with quote

I'm using serial IO in some of projects, and I'm having problems with s/w RS232.

My chip is running @ 4MHz, and communication speed is set 38400. The ideal bit length is therefore 26uS, and 26 instruction cycles. Normally it works, but seemingly randomly CCS compiler would generate code with bit length equal to 24 instruction cycles.

The way it works is like this: I have a perfectly working serial comm. As I continue to work on my project, at some point my communication would stop working, at which time I have to switch requested baudrate from 38400 to say 36400. Then starts working again, and work for some time, until my further changes to the project would trigger CCS back into generating proper bit length.

This has become extremely annoying, and happens through multiple updates of the compiler. I mean I could live with that if it was consistent systemic error. But it switches back and forth.

Currently the affected project is running on PIC16LF1907. In case you are wondering, it is not due to the CPU speed being off from nominal.

If this can't be fixed, can I just provide my own implementation of PUTC that does not suffer from such nonsense? If I just define new one compiler complains it's being redefined.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 11:30 am     Reply with quote

Quote:
The ideal bit length is therefore 26uS, and 26 instruction cycles. Normally
it works, but seemingly randomly CCS compiler would generate code with
bit length equal to 24 instruction cycles.

This seems unlikely, because the CCS library code for a software UART
is visible in the .LST file. It's right after the #use rs232() statement.
It shows careful coding so that a 0 or 1 bit has equal bit timing in the
0/1 bit decision code, as shown below:
Code:
                         // 0-bit  1-bit 
0013:  BTFSC  STATUS.C   //   2      1     
0014:  BSF    LATB.LATB1 //   0      1
0015:  BTFSS  STATUS.C   //   1      2
0016:  BCF    LATB.LATB1 //   1      0
0017:  BSF    @78.6
0018:  GOTO   026


How could it randomly use a different number of cycles ?

Do you have interrupts running ?
slavka012



Joined: 10 Feb 2012
Posts: 28

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 12:34 pm     Reply with quote

I don't have interrupts, and I have DISABLE_INTS just in case in my RS232 parameters.

I think you misunderstood. It is not randomly happening during execution. If it compiled correctly, it executes 100% fine. But sometimes compiler generates me wrong baud rate putc.

Here. This is compiled with baudrate 41667. The bit time should be 24 instruction cycles. But in the generated code one bit takes 26 instructions.

This weird number I had to put here because if I put 38400 it would (or, rather, could) generate putc with 28 cycles per bit. And it changes from time to time when I modify unrelated portions of code. Sometimes it gets it right, sometimes not.

Code:

5:                 #pragma use rs232(baud=41667,bits=8,parity=N,stop=1,DISABLE_INTS,RESTART_WDT,RS232_PARAM)
  01C9    080B     MOVF INTCON, W
  01CA    00FA     MOVWF 0x7a
  01CB    138B     BCF INTCON, 0x7
  01CC    0021     MOVLB 0x1
  01CD    130D     BCF PORTB, 0x6
  01CE    0022     MOVLB 0x2
  01CF    130D     BCF PORTB, 0x6
  01D0    3008     MOVLW 0x8
  01D1    00F8     MOVWF 0x78
  01D2    29D3     GOTO 0x1d3
  01D3    0000     NOP
  01D4    17F8     BSF 0x78, 0x7
  01D5    29EF     GOTO 0x1ef
  01D6    13F8     BCF 0x78, 0x7
  01D7    0023     MOVLB 0x3
  01D8    0820     MOVF 0x20, W
  01D9    00F9     MOVWF 0x79
  01DA    0CF9     RRF 0x79, F
  01DB    0022     MOVLB 0x2
  01DC    1803     BTFSC STATUS, 0
  01DD    170D     BSF PORTB, 0x6
  01DE    1C03     BTFSS STATUS, 0
  01DF    130D     BCF PORTB, 0x6
  01E0    1778     BSF 0x78, 0x6
  01E1    29EF     GOTO 0x1ef
  01E2    1378     BCF 0x78, 0x6
  01E3    0BF8     DECFSZ 0x78, F
  01E4    29E6     GOTO 0x1e6
  01E5    29E8     GOTO 0x1e8
  01E6    0023     MOVLB 0x3
  01E7    29DA     GOTO 0x1da
  01E8    0879     MOVF 0x79, W
  01E9    0023     MOVLB 0x3
  01EA    00A0     MOVWF 0x20
  01EB    29EC     GOTO 0x1ec
  01EC    0000     NOP
  01ED    0022     MOVLB 0x2
  01EE    170D     BSF PORTB, 0x6
  01EF    29F0     GOTO 0x1f0
  01F0    29F1     GOTO 0x1f1
  01F1    0064     CLRWDT
  01F2    1BF8     BTFSC 0x78, 0x7
  01F3    29D6     GOTO 0x1d6
  01F4    1B78     BTFSC 0x78, 0x6
  01F5    29E2     GOTO 0x1e2
  01F6    1BFA     BTFSC 0x7a, 0x7
  01F7    178B     BSF INTCON, 0x7
  01F8    0020     MOVLB 0
  01F9    0008     RETURN
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 1:38 pm     Reply with quote

Somewhere, I have the feeling that CCS published a method to redefine
stdout. You could define your own versions of the output functions
using a mechanism provided by CCS. I just can't find it in the manual
right now (if it even still exists). I am too busy right now. Maybe later.
Ttelmah



Joined: 11 Mar 2010
Posts: 19566

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 2:12 pm     Reply with quote

I think you will find the problem appears if you have a RX/getc used.
I seem to remember testing a while ago, and somewhere around 26 instructions was the shortest that the supplied code would reliably generate for getc. It can go slightly faster if the code only handles putc. If it can't 'cope', it switches the timings on both directions.
I have to ask 'why' you want to redefine putc though. Just replace all calls of putc, with your own routine name (my_putc...). If you want to use printf, then just redirect this.
slavka012



Joined: 10 Feb 2012
Posts: 28

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 2:57 pm     Reply with quote

I'm using a lot of printf's for debugging purpose. So just creating my own my_putc is not sufficient.

26 instructions is not the shortest they can make. You can see at line 1EF two consecutive "goto $+1" instructions. So at least 4 cycles could be shed. In my experience with requested baudrate 38400 it can generate putc with either 24,26, or 28 instructions. And it changes for no apparent reason.
temtronic



Joined: 01 Jul 2010
Posts: 9254
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 3:15 pm     Reply with quote

need some more info...
1) that PIC has a 16Mhz internal osc any reason why you're running at 4 mHz ?

2) it also has a real UART...is it commited to another serial device.

I seem to recall that running PICs over 9600 baud with a 4MHz xtal was 'marginal'.... though that won't explain the code created.

3) if you need 2 UARTS can you use a PIC with 2 hardware UARTS that's still pin compatible with your project? while it might cost a few pennies more it will be cost effective i the long run.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19566

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 3:44 pm     Reply with quote

I don't see why having your own my_putc is any more difficult for having a lot of debug outputs. Just do a search and replace on all your putc's, and it is done. If you use printf, then just replace 'printf("', with 'printf(my_putc,"'. Less than ten seconds work.
In fact if this is for debug, then normally you'd have a single debug_printf define used for the debug, so you can disable this by just defining this as nothing, which makes the change even easier. One line of code.
slavka012



Joined: 10 Feb 2012
Posts: 28

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 3:56 pm     Reply with quote

Quote:
need some more info...
1) that PIC has a 16Mhz internal osc any reason why you're running at 4 mHz ?

2) it also has a real UART...is it commited to another serial device.

I seem to recall that running PICs over 9600 baud with a 4MHz xtal was 'marginal'.... though that won't explain the code created.

3) if you need 2 UARTS can you use a PIC with 2 hardware UARTS that's still pin compatible with your project? while it might cost a few pennies more it will be cost effective i the long run.


There are reasons for all of this. It is an LCD, low power device. Let's just say I can't run at 16MHz, I can't use HW UART, and I can't use another PIC.

I presenting a clear case of a compiler bug, and I'd like either a way for me to work around it, or a true bug fix. I don't need suggestions on redesigning of the device: it is not happening. At the moment my workaround is change requested baud rate whenever compiler changes its mind about the number of cycles per bit, but I'm getting tired of that.

Btw, there is nothing marginal about running serial comm at any speed with 1-2% accurate clock, without crystal. Serial communication tolerates clock deviation up to 4% just fine.
slavka012



Joined: 10 Feb 2012
Posts: 28

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 3:59 pm     Reply with quote

Ttelmah wrote:
I don't see why having your own my_putc is any more difficult for having a lot of debug outputs. Just do a search and replace on all your putc's, and it is done. If you use printf, then just replace 'printf("', with 'printf(my_putc,"'. Less than ten seconds work.
In fact if this is for debug, then normally you'd have a single debug_printf define used for the debug, so you can disable this by just defining this as nothing, which makes the change even easier. One line of code.


oh, that's great. That's what I was looking for. I did not realize I can supply printf with my own putc as an extra parameter.

Thanks a lot!
temtronic



Joined: 01 Jul 2010
Posts: 9254
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 4:24 pm     Reply with quote

I only wanted to know more in case you _could_ use an alternative PIC for the project. I was 'stung' years ago with a PIC that failed to communicate when it got bitterly cold had to redo the PCBs with xtals and caps. One of those 'it worked fine in the shop...failed in the real world'.

Regulars here _know_ the pitfalls of a sw uart but if you know them, then a sw uart will function ok, that's why I asked about 'upgrading' to a pIC with two UARTs.

As for the 'bug', it might be related to the compiler version. Fixing one thing might have caused another thing to go wacky. As Mr. T pointed out there is a 'workaround'. Hopefully it'll do the job for you!!

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19566

View user's profile Send private message

PostPosted: Tue Nov 18, 2014 1:26 am     Reply with quote

slavka012 wrote:
Ttelmah wrote:
I don't see why having your own my_putc is any more difficult for having a lot of debug outputs. Just do a search and replace on all your putc's, and it is done. If you use printf, then just replace 'printf("', with 'printf(my_putc,"'. Less than ten seconds work.
In fact if this is for debug, then normally you'd have a single debug_printf define used for the debug, so you can disable this by just defining this as nothing, which makes the change even easier. One line of code.


oh, that's great. That's what I was looking for. I did not realize I can supply printf with my own putc as an extra parameter.

Thanks a lot!


Aha!, the critical missing bit of knowledge... Smile

Yes, this is a feature of CCS, that you can redirect printf, to use any output routine you want. It's a very basic part of the language (how else could you use printf, with several serials etc..), but if you haven't read the manual or looked at the examples, and 'twigged' this power, then your problem makes sense.

At least you have a solution now.
slavka012



Joined: 10 Feb 2012
Posts: 28

View user's profile Send private message

PostPosted: Tue Nov 18, 2014 12:01 pm     Reply with quote

So this is what I'm talking about.

I'm still compiling the same code, but bit lengths is now 22 instructions:
Code:

5:                 #pragma use rs232(baud=5:                 #pragma use rs232(baud=41667,bits=8,parity=N,stop=1,DISABLE_INTS,RESTART_WDT,RS232_PARAM)
  0135    080B     MOVF INTCON, W
  0136    00FA     MOVWF 0x7a
  0137    138B     BCF INTCON, 0x7
  0138    0021     MOVLB 0x1
  0139    130D     BCF PORTB, 0x6
  013A    0022     MOVLB 0x2
  013B    130D     BCF PORTB, 0x6
  013C    3008     MOVLW 0x8
  013D    00F8     MOVWF 0x78
  013E    293F     GOTO 0x13f
  013F    0000     NOP
  0140    17F8     BSF 0x78, 0x7
  0141    2954     GOTO 0x154
  0142    13F8     BCF 0x78, 0x7
  0143    0860     MOVF 0x60, W
  0144    00F9     MOVWF 0x79
  0145    0CF9     RRF 0x79, F
  0146    1803     BTFSC STATUS, 0
  0147    170D     BSF PORTB, 0x6
  0148    1C03     BTFSS STATUS, 0
  0149    130D     BCF PORTB, 0x6
  014A    1778     BSF 0x78, 0x6
  014B    2954     GOTO 0x154
  014C    1378     BCF 0x78, 0x6
  014D    0BF8     DECFSZ 0x78, F
  014E    2945     GOTO 0x145
  014F    0879     MOVF 0x79, W
  0150    00E0     MOVWF 0x60
  0151    2952     GOTO 0x152
  0152    0000     NOP
  0153    170D     BSF PORTB, 0x6
  0154    2955     GOTO 0x155
  0155    2956     GOTO 0x156
  0156    0064     CLRWDT
  0157    1BF8     BTFSC 0x78, 0x7
  0158    2942     GOTO 0x142
  0159    1B78     BTFSC 0x78, 0x6
  015A    294C     GOTO 0x14c
  015B    1BFA     BTFSC 0x7a, 0x7
  015C    178B     BSF INTCON, 0x7
  015D    0020     MOVLB 0
  015E    0008     RETURN
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 18, 2014 1:41 pm     Reply with quote

I asked CCS support if there was a method to globally replace putc and
getc, and here is their reply:

You can do this:
Code:
#use rs232( CALL_PUTC=myputc,  CALL_GETC=mygetc,  CALL_KBHIT=mykbhit )
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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