|
|
View previous topic :: View next topic |
Author |
Message |
Remko
Joined: 24 Sep 2003 Posts: 14
|
I2c Force_hw problem |
Posted: Thu Jun 22, 2006 3:43 am |
|
|
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
|
|
Posted: Thu Jun 22, 2006 8:35 am |
|
|
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
|
I2c Force_hw problem |
Posted: Fri Jun 23, 2006 1:25 am |
|
|
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
|
|
Posted: Fri Jun 23, 2006 2:17 am |
|
|
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
|
|
Posted: Fri Jun 23, 2006 2:30 am |
|
|
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
|
|
Posted: Fri Jun 23, 2006 3:32 am |
|
|
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
|
|
Posted: Fri Jun 23, 2006 4:30 am |
|
|
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
|
|
Posted: Fri Jun 23, 2006 4:33 am |
|
|
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
|
|
Posted: Fri Jun 23, 2006 8:40 am |
|
|
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
|
|
Posted: Mon Jun 26, 2006 1:58 am |
|
|
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
|
|
Posted: Mon Jun 26, 2006 6:30 am |
|
|
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
|
|
Posted: Mon Jun 26, 2006 8:19 am |
|
|
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
|
|
Posted: Mon Jun 26, 2006 8:23 am |
|
|
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
|
|
Posted: Tue Jun 27, 2006 4:08 am |
|
|
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
|
|
Posted: Tue Jun 27, 2006 6:39 am |
|
|
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 |
|
|
|
|
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
|