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 support@ccsinfo.com

I2c Force_hw problem
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
Remko



Joined: 24 Sep 2003
Posts: 14

View user's profile Send private message

I2c Force_hw problem
PostPosted: Thu Jun 22, 2006 3:43 am     Reply with quote

Hello,

I am using I2C and RS232 communication. When the RS232 Comunication gets very busy, the I2C communication begins to fail. According to microchip this should not happen because I2C is hardware. The compiler makes software routines unless you specify FORCE_HW. After putting it in, my I2C does not work at all. After cleaning the complete project and only put in the I2C and show it on display, the problem still exist.
When I measure with the scope on the clk pin, it shows me a very nasty signal with FORCE_HW on.
Can anyone tell me how I can get the I2C to work with FORCE_HW.

PIC18F452 @ 20MHz
24LC256
V3.249

Best regards,

Remko
Ttelmah
Guest







PostPosted: Thu Jun 22, 2006 8:35 am     Reply with quote

What pull up resistors are you using?. The hardware will default to operating significantly quicker than the software I2C, requiring lower value pull-ups if there is significant capacitance on the line.

Best Wishes
Remko



Joined: 24 Sep 2003
Posts: 14

View user's profile Send private message

I2c Force_hw problem
PostPosted: Fri Jun 23, 2006 1:25 am     Reply with quote

Tank you for you reply,

The resistors are 1k. When I measure with my scope I can see the speed is much to high, so that one is right (with hardware I2C, not with software I2c). After putting in slow, I can see the CLK go from 0V to 5V so that one must be right. The signal is not a nice clock signal...
But, I have it working now. I deleted the line #use I2C(...) in the 24LC256.C file and put it in my HAL file right behind the #fuses, #use delay and #use RS232. Now the hardware I2C works fine but my problem is not solved.

After debugging I found out that the variable address (a long) is changed after busy communication throuht RS232 on interruptbase. Also other variables are changed after busy RS232 communication. I have made my own ISR. The start of the ISR is:

#INT_GLOBAL
void Int_serv(void)
{
char chartemp;
#asm
MOVLB 0 // to get proc in bank 0
#endasm

if (INT0IF && INT0IE) {
...
...
INT0IF = 0;
}
...
...
...
...


while (RCIF && RCIE)
{
RCIFShadow = 1;
chartemp = getc();
if (chartemp == ':') // 0x3A
rs232_i = 0;// PutRs232_i ; PutRs232_i&=0x07;
if ((chartemp == '#')||(chartemp == 'A')){
string[PutRs232_i][rs232_i] = chartemp;
if (rs232_i < 17) rs232_i ;
chartemp = '\r';}

if (chartemp != 0x0A) // Line Feed
{
string[PutRs232_i][rs232_i] = chartemp;
if (rs232_i < 17) rs232_i ;
if (chartemp == '\r') {
rs232_i = 0;
PutRs232_i ;
PutRs232_i &= 0x07;
} // end if (chartemp == '\r') {
} // end if (chartemp != 0x0A)
} // end if (RCIF && RCIE)

#asm
RETFIE 1 // Return from interrupt fast
#endasm
}

string is:
char string[8][18];

Is there something wrong with the context saving for example, or something else?
Ttelmah
Guest







PostPosted: Fri Jun 23, 2006 2:17 am     Reply with quote

Your interrupt code will bu**er things up.
You are using arrays, which inherently means access to the table registers, and are not saving/restoring these in your handler.
When you write an int_global, it is _your_ responsibility to save _every register_ that is used in the handler. You need to go through the listing file, and work out what your code uses. Also, Assuming the PutRS232i, is the actual hardware register, there is no sign that I can see, of you handling a possible overrun condition, which will lock the UART.

Best Wishes
ckielstra



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

View user's profile Send private message

PostPosted: Fri Jun 23, 2006 2:30 am     Reply with quote

Please use the 'Code' button when posting code, this helps to retain the formatting.

Code:
 if (rs232_i < 17) rs232_i ;
I don't understand this line. Can you give us the definition of rs232_i ?
Remko



Joined: 24 Sep 2003
Posts: 14

View user's profile Send private message

PostPosted: Fri Jun 23, 2006 3:32 am     Reply with quote

Hello,

The code is actually:
Code:
if (rs232_i < 17) rs232_i++;

thank you for the tip on formatting the code.

The PutRs232_i and rs232_i are global variables. I don't think I have to save them, do I?
Ttelmah
Guest







PostPosted: Fri Jun 23, 2006 4:30 am     Reply with quote

No. It is the table handling that is likely to be killing you.
The probables are:
Table pointers.
FSR registers.
Scratch memory.

Best Wishes
Remko



Joined: 24 Sep 2003
Posts: 14

View user's profile Send private message

PostPosted: Fri Jun 23, 2006 4:33 am     Reply with quote

All right, I am beginning to understand. Those things the compiler does which I do not have in hand.
Can you tell me more, or what do I have to do?

I need the speed of the ISR because I am also handling wireless communication in the ISR with the help of INT0 and CCP.
Ttelmah
Guest







PostPosted: Fri Jun 23, 2006 8:40 am     Reply with quote

Realistically, you are tying to go DIY, in a very complex area. There is no shortcut, you need to go through the entire listing file generated by the interrupt handler code, and identify every hardware register that is accessed (remember these are all in the top bank of the RAM, so identification is not that hard). Turn off the 'nolist' option in the header file first, so you also see registers accessed inside system calls. Add any RAM accesses to the first half dozen bytes of memory (this is the default location for the scratch area), Then cross off the W reg, status, and BSR, since you are using RETFIE 1, and you then need to save _every_ register left, and restore these on exit. Do not be suprised if you only end up saving half a dozen instructions over using the standard handler...

Best Wishes
Remko



Joined: 24 Sep 2003
Posts: 14

View user's profile Send private message

PostPosted: Mon Jun 26, 2006 1:58 am     Reply with quote

Thank you for reply,

I have searched the LST of ISR and found several registers (All in the top of the area 0xF80 and higher, i am using 452 now and going to use 4620) There are the registers which I am bittesting for the int flags and bitclearing the int flags. There are timers and ccp pwm registers which I am modifying in the isr myself. The IntEdge is also there which I am modifying myself. There are only a few registers which I am not testing or modifying myself: FSR0H, FSR0L and INDF. I don't think I have to save and restore them do I? And the PRODL and PRODH registers. I have saved them but the problem still exists

My colleage advised me to change the buffer from a 8x18 array to a circular buffer of 144 and use the MOD function.

I already tried a little bit of this idea with string2[144]. Only filling the string does not give me the errors. The difference is the hardware multiplier.
I can go there but I must find out what goes wrong with the string[8][18].

This is the lst of the ISR which goes wrong:

beginning of the isr code:

Code:

0000                11650 .................... #INT_GLOBAL 
0000                11651 .................... void Int_serv(void)
0000                11652 .................... {
0000                11653 ....................   #asm
0000                11654 .................... //  MOVWF W_TEMP registers saven
0000                11655 .................... //  MOVFF STATUS, STATUS_TEMP
0000                11656 .................... //  MOVFF BSR,    BSR_TEMP
0000                11657 .................... MOVFF PRODL, PRODL_Temp
0008 CFF3 F00B      11658 MOVFF  FF3,0B
0000                11659 .................... MOVFF PRODH, PRODH_Temp
000C CFF4 F00A      11660 MOVFF  FF4,0A
0000                11661 ....................     MOVLB 0      
0010 0100           11662 MOVLB  0
0000                11663 ....................   #endasm
0000                11664 .................... 
0000                11665 ....................   if (INT0F && INT0E)      
0012 A2F2           11666 BTFSS  FF2.1
0014 D016           11667 BRA    0042
0016 A8F2           11668 BTFSS  FF2.4
0018 D014           11669 BRA    0042
0000                11670 ....................   {



and the rest of the isr code:

Code:


0000                11954 ....................   if (RCIF && RCIE)
015C AA9E           11955 BTFSS  F9E.5
015E D04F           11956 BRA    01FE
0160 AA9D           11957 BTFSS  F9D.5
0162 D04D           11958 BRA    01FE
0000                11959 ....................   {
0000                11960 ....................     RCIFShadow = 1;      // Deze ISR zet de RCIF weer laag dus wordt RCIFShadow gebruikt voor de Data Request dmv AAA
0164 800D           11961 BSF    0D.0
0000                11962 ....................     chartemp = getc();
0166 AA9E           11963 BTFSS  F9E.5
0168 D7FE           11964 BRA    0166
016A CFAE F010      11965 MOVFF  FAE,10
0000                11966 ....................     if (chartemp == ':') // 0x3A
016E 5010           11967 MOVF   10,W
0170 083A           11968 SUBLW  3A
0172 E101           11969 BNZ   0176
0000                11970 ....................       rs232_i = 0;// PutRs232_i++; PutRs232_i&=0x07;
0174 6A0C           11971 CLRF   0C
0000                11972 ....................     if ((chartemp == '#')||(chartemp == 'A')){
0176 5010           11973 MOVF   10,W
0178 0823           11974 SUBLW  23
017A E003           11975 BZ    0182
017C 5010           11976 MOVF   10,W
017E 0841           11977 SUBLW  41
0180 E11B           11978 BNZ   01B8
0000                11979 ....................       string[PutRs232_i][rs232_i] = chartemp;
0182 500E           11980 MOVF   0E,W
0184 0D12           11981 MULLW  12
0186 50F3           11982 MOVF   FF3,W
0188 0102           11983 MOVLB  2
018A 6BB5           11984 CLRF   xB5
018C 6FB4           11985 MOVWF  xB4
018E 6A03           11986 CLRF   03
0190 500C           11987 MOVF   0C,W
0192 25B4           11988 ADDWF  xB4,W
0194 6E01           11989 MOVWF  01
0196 51B5           11990 MOVF   xB5,W
0198 2203           11991 ADDWFC 03,F
019A 5001           11992 MOVF   01,W
019C 0F11           11993 ADDLW  11
019E 6EE9           11994 MOVWF  FE9
01A0 0E00           11995 MOVLW  00
01A2 2003           11996 ADDWFC 03,W
01A4 6EEA           11997 MOVWF  FEA
01A6 C010 FFEF      11998 MOVFF  10,FEF
0000                11999 ....................       if (rs232_i < 17) rs232_i++;
01AA 500C           12000 MOVF   0C,W
01AC 0810           12001 SUBLW  10
01AE B0D8           12002 BTFSC  FD8.0
01B0 2A0C           12003 INCF   0C,F
0000                12004 ....................       chartemp = 0x0D;}   // 0x0D = '\r'
01B2 0E0D           12005 MOVLW  0D
01B4 6E10           12006 MOVWF  10
01B6 0100           12007 MOVLB  0
0000                12008 .................... 
0000                12009 ....................     if (chartemp != 0x0A) // Line Feed
01B8 5010           12010 MOVF   10,W
01BA 080A           12011 SUBLW  0A
01BC E020           12012 BZ    01FE
0000                12013 ....................     {
0000                12014 ....................       string[PutRs232_i][rs232_i] = chartemp;
01BE 500E           12015 MOVF   0E,W
01C0 0D12           12016 MULLW  12
01C2 50F3           12017 MOVF   FF3,W
01C4 0102           12018 MOVLB  2
01C6 6BB5           12019 CLRF   xB5
01C8 6FB4           12020 MOVWF  xB4
01CA 6A03           12021 CLRF   03
01CC 500C           12022 MOVF   0C,W
01CE 25B4           12023 ADDWF  xB4,W
01D0 6E01           12024 MOVWF  01
01D2 51B5           12025 MOVF   xB5,W
01D4 2203           12026 ADDWFC 03,F
01D6 5001           12027 MOVF   01,W
01D8 0F11           12028 ADDLW  11
01DA 6EE9           12029 MOVWF  FE9
01DC 0E00           12030 MOVLW  00
01DE 2003           12031 ADDWFC 03,W
01E0 6EEA           12032 MOVWF  FEA
01E2 C010 FFEF      12033 MOVFF  10,FEF
0000                12034 ....................       if (rs232_i < 17) rs232_i++;
01E6 500C           12035 MOVF   0C,W
01E8 0810           12036 SUBLW  10
01EA B0D8           12037 BTFSC  FD8.0
01EC 2A0C           12038 INCF   0C,F
0000                12039 ....................       if (chartemp == 0x0D) { // 0x0D = '\r'
01EE 5010           12040 MOVF   10,W
01F0 080D           12041 SUBLW  0D
01F2 E104           12042 BNZ   01FC
0000                12043 ....................         rs232_i = 0; 
01F4 6A0C           12044 CLRF   0C
0000                12045 ....................         PutRs232_i++; 
01F6 2A0E           12046 INCF   0E,F
0000                12047 ....................         PutRs232_i &= 0x07;
01F8 0E07           12048 MOVLW  07
01FA 160E           12049 ANDWF  0E,F
01FC 0100           12050 MOVLB  0
0000                12051 ....................       } // if (chartemp == '\r') {
0000                12052 ....................     } // end if (chartemp != 0x0A) 
0000                12053 ....................   } // if (RCIF && RCIE)
0000                12054 .................... 
0000                12055 ....................   #asm   
0000                12056 .................... //  MOVFF   BSR_TEMP,BSR
0000                12057 .................... //  MOVF   W_TEMP,  W
0000                12058 .................... //  MOVFF   STATUS_TEMP,STATUS
0000                12059 .................... MOVFF PRODL_Temp, PRODL
01FE C00B FFF3      12060 MOVFF  0B,FF3
0000                12061 .................... MOVFF PRODH_Temp, PRODH
0202 C00A FFF4      12062 MOVFF  0A,FF4
0000                12063 ....................   RETFIE 1               // Return from interrupt fast
0206 0011           12064 RETFIE 1
0000                12065 ....................   #endasm
0000                12066 .................... }
      // Return from interrupt fast
Remko



Joined: 24 Sep 2003
Posts: 14

View user's profile Send private message

PostPosted: Mon Jun 26, 2006 6:30 am     Reply with quote

All right, I misunderstood. It is about the scratch RAM which the compiler uses. The scratch RAM is used outside AND inside the ISR. While the program outside is using the scratch, an interrupt is generated and the ISR uses the same scratch area. That's right isn't it?
Because of the complex calculations ot the array of chars scratch has to be used. Simple calculation of a string[144] does not need the scratch.

How can I find out where the scratch is located?
How can I set the scratch addresses used in the ISR fixed to a location I choose instead of being chosen by the compiler?
It seems to be using address 0x00 till 0x04. 0x05 is used by a variable I put in, but it also uses address 0x2B6 and more.
Ttelmah
Guest







PostPosted: Mon Jun 26, 2006 8:19 am     Reply with quote

You _do_ need to save the FSR registers. INDF, is not a 'register' as such, but the contents of the memory addressed _by_ the FSR registers, so will automatically change when the FSR registers are saved/restored. The FSR, is used for all indexed addressing.
The scratch area is at the base of the RAM. Typically expect to have to save perhaps five values here. Look at the symbol map to see how many are used.
Also check you are not using the TBLPTR registers (get used for any ROM tables, and some types of switch statement).

Best Wishes
Remko



Joined: 24 Sep 2003
Posts: 14

View user's profile Send private message

PostPosted: Mon Jun 26, 2006 8:23 am     Reply with quote

The first register begins an 0x05, it is Hekje. So I have to save 0x01, 0x02, 0x03, and 0,04.
What about the _RETURN_ ? Just save address 0x01 also?


Code:

Configuration Fuses:
   Word  1: 2200   HS NOOSCSEN
   Word  2: 0E0D   NOBROWNOUT WDT128 NOWDT BORV20 NOPUT
   Word  3: 0100   CCP2C1
   Word  4: 0001   STVREN DEBUG NOLVP
   Word  5: C00F   NOPROTECT NOCPD NOCPB
   Word  6: E00F   NOWRT NOWRTD NOWRTB NOWRTC
   Word  7: 400F   NOEBTR NOEBTRB

SYMBOL TABLE
  LABEL                             VALUE

_RETURN_                          00000001
Hekje                             00000005
A                                 00000007
rs232_i                           00000009
RCIFshadow                        0000000A
T1kHz                             0000000A
T100Hz                            0000000A
Remko



Joined: 24 Sep 2003
Posts: 14

View user's profile Send private message

PostPosted: Tue Jun 27, 2006 4:08 am     Reply with quote

I have changed my isr to see what the ccs compiler saves. W, Status and BSR are saved. The FSR registers are saved (6 pieces). The PROD registers are saved and the PCLATH is saved. Besides those, the scratch registers 00 till 04 are saved.
Now I understand, thank you for explaining.
You suggested me to look in my ISR and see which registers are used and save them.
In my ISR the registers FSR0L and H and the scratch registers 02 and 03 are used.
FSR0L and H and 03 are used in the RDA area.
02 and 03 are used in the Timer2 area.
To keep the highest speed I assume I have to save and restore them only in those areas.
Because of the fast return from interrupt I don't have to save W, Status and BSR, but what about PCLATH?

Is this what you mean in your former replies?
Is this right what you are saying in your former replies?
Ttelmah
Guest







PostPosted: Tue Jun 27, 2006 6:39 am     Reply with quote

PCLATH, only needs saving, if there is a 'computed GOTO' anywhere in the interrupt handler. This is used by some parts of the CCS code, which is why they save it. If nothing writes to it, you can leave it unsaved.
It sounds as if you have a fairly good list now of what is needed.

Best Wishes
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