|
|
View previous topic :: View next topic |
Author |
Message |
slavka012
Joined: 10 Feb 2012 Posts: 28
|
how to redefine putc? |
Posted: Mon Nov 17, 2014 10:50 am |
|
|
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
|
|
Posted: Mon Nov 17, 2014 11:30 am |
|
|
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
|
|
Posted: Mon Nov 17, 2014 12:34 pm |
|
|
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
|
|
Posted: Mon Nov 17, 2014 1:38 pm |
|
|
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
|
|
Posted: Mon Nov 17, 2014 2:12 pm |
|
|
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
|
|
Posted: Mon Nov 17, 2014 2:57 pm |
|
|
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: 9255 Location: Greensville,Ontario
|
|
Posted: Mon Nov 17, 2014 3:15 pm |
|
|
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
|
|
Posted: Mon Nov 17, 2014 3:44 pm |
|
|
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
|
|
Posted: Mon Nov 17, 2014 3:56 pm |
|
|
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
|
|
Posted: Mon Nov 17, 2014 3:59 pm |
|
|
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: 9255 Location: Greensville,Ontario
|
|
Posted: Mon Nov 17, 2014 4:24 pm |
|
|
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
|
|
Posted: Tue Nov 18, 2014 1:26 am |
|
|
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...
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
|
|
Posted: Tue Nov 18, 2014 12:01 pm |
|
|
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
|
|
Posted: Tue Nov 18, 2014 1:41 pm |
|
|
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 ) |
|
|
|
|
|
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
|