View previous topic :: View next topic |
Author |
Message |
Tiny
Joined: 10 Nov 2010 Posts: 101 Location: The Netherlands
|
Posted: Sat Sep 30, 2017 7:25 pm Post subject: i2c problem between 2.0.7.9 and 2.0.8.0 |
|
|
Hello,
I have a probleem between bascom compiler version 2.0.7.9.00 and 2.0.8.0.001
the i2c device is a RTC type ISL1220
when i compile the code in 2.0.7.9.001 the communication is oke with the device ( see picture version 2079.png )
compile the code with 2.0.8.0.001 the program stops, but timer interrupts are still working ( see picture version 2080.png )
whats is wrong?
Code: | I2cstart #4 'send start
I2cwbyte Rtclk_addressw , #4 'send address
If Err = 1 Then
#if Debugoutput
Print #1 , "rtc not ready !!!!! "
#endif
I2cstop #4
Reset I2c_busy_flag
'free bus
Exit Sub
Else
I2cstop #4 'free bus
#if Debugoutput
' Print #1 , "rtc oke"
#endif
End If
Waitms 500
I2cstart #4 'generate start
I2cwbyte Rtclk_addressw , #4 'slave adsress
I2cwbyte &H00 , #4 'address of status register
I2crepstart #4 'repeated start
I2cwbyte Rtclk_addressr , #4 'slave address (read)
I2crbyte Rtc_value , Ack , #4
Rtc_seconde = Makedec(rtc_value) 'read byte
I2crbyte Rtc_value , Ack , #4 'read byte
Rtc_minuut = Makedec(rtc_value)
I2crbyte Rtc_value , Ack , #4
Reset Rtc_value.7 'wis 24 uur flag
Rtc_uur = Makedec(rtc_value)
I2crbyte Rtc_value , Ack , #4 'read byte
Rtc_dag = Makedec(rtc_value)
I2crbyte Rtc_value , Ack , #4 'read byte
Rtc_maand = Makedec(rtc_value)
I2crbyte Rtc_value , Nack , #4 'read byte
Rtc_jaar = Makedec(rtc_value)
I2cstop #4 'generate stop
Reset I2c_busy_flag
|
(BASCOM-AVR version : 2080 , Latest : 2.0.7.8 ) |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Sat Sep 30, 2017 8:27 pm Post subject: |
|
|
you do not show any code that can reproduce the problem.
for problems it is important to know which processor is used.
it seems you use an xmega.
in 2080 we corrected some code in i2cstop. but the odd thing is that not all xmega respond the same.
in order to get around this you can use this code in xmega.lib
;generate I2C stop
_i2c_stop:
Ldi r24, &B111 ; perform stop
std z+3,R24 ; generate stop
_i2c_stop3:
LDI r24,1
STD Z+4,r24
ldd r24, z+4 ; get status
andi r24,&B11 ; isolate bus state
cpi r24,1 ; should be 1 (idle)
#IF Varexist("_TWI_STOP_NEW")
brne _i2c_stop3 ; if not, wait till state is right
#ELSE
brne _i2c_stop ; if not, send a new command, for some reason one is not enough?
#ENDIF
Ret
just replace the existing code for this one.
if you create a constant named _TWI_STOP_NEW , value is not important, then you can influence the behavior.
the old code sends stop commands while only one should be needed. some chips do not like to get multiple stop commands.
so in your case, you should not need create the constant ! only customers with hardware that do not like repeated stops should include it. _________________ Mark |
|
Back to top |
|
|
Tiny
Joined: 10 Nov 2010 Posts: 101 Location: The Netherlands
|
Posted: Sat Sep 30, 2017 9:34 pm Post subject: |
|
|
Thanks for the quick response.
Yes I use a atxmega256a3u
the hole code is about 12000 rows
I will test your solution a.s.a.p and I wil post the result.
Regard Tiny |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Sat Sep 30, 2017 9:53 pm Post subject: |
|
|
ok, the atxmega256a3u . that is good to know.
I do not mean that you must post a complete code, just the part that we can compile and test.
of course you can also use the 2079 version :
;generate I2C stop
_i2c_stop:
Ldi r24, &B111 ; perform stop
st z+3,R24 ; generate stop
ld r24, z+4 ; get status
andi r24,&B11 ; isolate bus state
cpi r24,2 ; should be 2 (idle)
breq _i2c_stop ; if not, send a new command, for some reason one is not enough?
Ret
as you see, that version keeps sending stops till the bus is free. but that would not work in all cases.
technically sending 1 stop should be sufficient. in normal avr that works correct. _________________ Mark |
|
Back to top |
|
|
Tiny
Joined: 10 Nov 2010 Posts: 101 Location: The Netherlands
|
Posted: Sun Oct 01, 2017 11:06 am Post subject: |
|
|
Dear Mark,
Adjusting the xmega lib works for me. thankx for your quick solution
1 thing that I notice is that the status of the clock line not ends the same as in the 2079 code
as i adjust the xmage.lib with the old 2079 "i2c_stop code" the clock line Always is high after complete a communication, when adjust de xmage.lib with the suggested code in your first reply it is different.
see the attached pictures
the second picture is with the 2079 code in the xmega.lib
both picture are i2c logging with compiler 2.0.8.0.001
maybe it's an idea to be able to select which stop option you want to use in the next release of bascom.
Regard Tiny |
|
Back to top |
|
|
Tiny
Joined: 10 Nov 2010 Posts: 101 Location: The Netherlands
|
Posted: Sun Oct 01, 2017 8:01 pm Post subject: |
|
|
This is the code where the i2c goes wrong with the standard 2080 xmega.lib
Code: | $regfile = "xm256a3def.dat"
$crystal = 8000000 '8MHz
$hwstack = 500
$swstack = 250
$framesize = 250
Config Submode = New
'*******************************************************************************
' constanten
'*******************************************************************************
Config_constanten:
Const Rtc_address = &HDE 'slave address Tealtime clock
Const E2prom_address = &HA0 'slave address e2prom
'*******************************************************************************
' Config i/o
'*******************************************************************************
Config Porta.2 = Input '
Config Porta.6 = Output '
Config Porta.7 = Output '
Config Portb.0 = Input '
Config Portb.1 = Output '
Config Portb.4 = Output '
Config Portb.5 = Output 'LED Rood (change)
Config Portb.6 = Output 'BUZZER (change)
Config Portb.7 = Input '
Config Portc.2 = Input '
Config Portc.3 = Input '
Config Portc.4 = Output 'led green
Config Portc.5 = Input '
Config Portc.6 = Input '
Config Portc.7 = Output '
Config Portd.0 = Input ' '
Config Portd.1 = Input '
Config Portd.2 = Input '
Config Portd.3 = Input '
Config Portd.4 = Output '
Config Portd.5 = Input '
Config Portd.6 = Input '
Config Portd.7 = Output '
Config Porte.0 = Output 'TX Led
Config Porte.1 = Input '
Config Porte.2 = Input '
Config Porte.3 = Output '
Config Porte.4 = Output '
Config Porte.5 = Output '
Config Porte.6 = Input '
Config Porte.7 = Output '
Config Portf.0 = Input '
Config Portf.1 = Input '
Config Portf.2 = Input '
Config Portf.3 = Output '
Config Portf.4 = Output '
Config Portf.5 = Output '
'*******************************************************************************
' Config Clock
' Enable the external oscillator with Range 2MHz....9MHz
'*******************************************************************************
Config Osc = Disabled , Extosc = Enabled , Range = 2mhz_9mhz , Startup = Xtal_256clk
Config Sysclock = External , Prescalea = 1 , Prescalebc = 1_1
Portcfg_clkevout = 10 'output sysclk clock on PortD.7
'*******************************************************************************
' Config compoort
'*******************************************************************************
Config Com2 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
'Config Com2 = 19200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
Open "COM2:" For Binary As #1
'*******************************************************************************
' Config watchdog
'*******************************************************************************
Config_watchdog:
Config Watchdog = 8
'*******************************************************************************
Enable Interrupts
'*******************************************************************************
' Config I2C
'*******************************************************************************
Config_i2c:
Dim Twi_start As Byte
' Dim I2cstatus As Byte
Config Sda = Portc.0
Config Scl = Portc.1
Open "twic" For Binary As #4 ' or use TWID,TWIE oR TWIF
Config Twic = 100000 'CONFIG TWI will ENABLE the TWI master interface
I2cinit #4
'*******************************************************************************
' Declare Alias
'*******************************************************************************
Config_alias:
Power_on Alias Porte.3 'enable
E2wp Alias Portb.4 'E2_Write protect (change)
'*******************************************************************************
' Declare sub's
'*******************************************************************************
Declare_subs:
Declare Sub Read_time_date()
'*******************************************************************************
' Config Priority
'*******************************************************************************
Config Priority = Static , Vector = Application , Lo = Enabled , Med = Enabled 'Enable Lo Level Interrupts
'*******************************************************************************
' Config watchdog
'*******************************************************************************
Config Watchdog = 1000
'*******************************************************************************
' enable pullup resistors
'*******************************************************************************
Config_pullups:
Porta_pin2ctrl = Bits(3 , 4) ' Pullup
Portb_pin0ctrl = Bits(3 , 4) ' Pullup
Portb_pin4ctrl = Bits(3 , 4) ' Pullup
Portb_pin7ctrl = Bits(3 , 4) ' Pullup
Portc_pin2ctrl = Bits(3 , 4) ' Pullup
Portc_pin3ctrl = Bits(3 , 4) ' Pullup
Portc_pin5ctrl = Bits(3 , 4) ' Pullup
Portc_pin6ctrl = Bits(3 , 4) ' Pullup
Portd_pin0ctrl = Bits(3 , 4) ' Pullup
Portd_pin1ctrl = Bits(3 , 4) ' Pullup
Portd_pin2ctrl = Bits(3 , 4) ' Pullup
Portd_pin3ctrl = Bits(3 , 4) ' Pullup
Portd_pin5ctrl = Bits(3 , 4) ' Pullup
Portd_pin6ctrl = Bits(3 , 4) ' Pullup
Portf_pin1ctrl = Bits(3 , 4) ' Pullup
Portf_pin2ctrl = Bits(3 , 4) ' Pullup
Portf_pin4ctrl = Bits(3 , 4) ' Pullup
'*******************************************************************************
' RTC variable en constanten
'*******************************************************************************
Const Rtclk_addressw = &HDE
Const Rtclk_addressr = &HDF
Const Rtclk_status = &H07
Const Rtclk_seconde = &H00
Const Rtclk_minuut = &H01
Const Rtclk_uur = &H02
Const Rtclk_dag = &H03
Const Rtclk_maand = &H04
Const Rtclk_jaar = &H05
Dim Rtc_value As Byte
'*******************************************************************************
' main program
'*******************************************************************************
Set Power_on
Toggle Portc.4
Reset E2wp 'disable 24c1024
Print #1 , "starting..."
Dim Temp As Byte
For Temp = 0 To 254 Step 2 'for all addresses
I2cstart #4 'send start
I2cwbyte Temp , #4 'send address
If Err = 0 Then
Print #1 , "found " ; Temp
End If
I2cstop #4 'free bus
Next
Set E2wp
Print #1 , "starting mainloop"
Main_loop:
Do
Toggle Porte.0
Call Read_time_date() ' Call Read_time_date()
Waitms 500
Loop
End
'*******************************************************************************
' Sub read_time_date
' read value's from rtc chip
'*******************************************************************************
Sub Read_time_date()
I2cstart #4 'send start
I2cwbyte Rtclk_addressw , #4 'send address
If Err = 1 Then
Print #1 , "rtc not ready !!!!! "
I2cstop #4 'free bus
Exit Sub
Else
I2cstop #4 'free bus
Print #1 , "rtc oke"
End If
I2cstart #4 'generate start
I2cwbyte Rtclk_addressw , #4 'slave adsress
I2cwbyte &H00 , #4 'address of status register
I2crepstart #4 'repeated start
I2cwbyte Rtclk_addressr , #4 'slave address (read)
I2crbyte Rtc_value , Ack , #4
I2crbyte Rtc_value , Ack , #4 'read byte
I2crbyte Rtc_value , Ack , #4
I2crbyte Rtc_value , Ack , #4 'read byte
I2crbyte Rtc_value , Ack , #4 'read byte
I2crbyte Rtc_value , Nack , #4 'read byte
I2cstop #4 'generate stop
Print #1 , "time readed"
End Sub |
|
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Mon Oct 02, 2017 9:57 am Post subject: |
|
|
do you use pull up resistors?
it is really weird. non of the normal avr chips has issues with i2cstop.
when implementing for xmega i found that doing an i2cstop would not free the bus.
normally you send just 1 command, the processor performs this command and using the status register you can see if it has been executed.
most experiments where done with xmega128A1 but for some reason some other xmega that were made later worked slightly different.
anyway, i would expect that the bus become idle after the stop so the original code was sending i2cstop command, and then is polling the status to see if the bus is idle.
Now odd thing 1 : the datasheet says that idle is 1. And owner is 2. but 1 would never happen. while with multiple stop commands, 2 would work.
So the working code till 2079 :
_i2c_stop:
Ldi r24, &B111 ; perform stop
st z+3,R24 ; generate stop
ld r24, z+4 ; get status
andi r24,&B11 ; isolate bus state
cpi r24,2 ; should be 2 (idle)
breq _i2c_stop ; if not, send a new command, for some reason one is not enough?
Ret
then came a customer with hardware that had problems because of the multiple commands so the code was changed with an optional condition.
ok, so far so good. but then i made an fram driver for xmega. and i found out that the bus would not become free. i guess it depends on the slave chip. for example a clock stretch or so.
anyway, then i was confronted with the odd idle/owner thing. so then i made code that would reset the bus to idle and wait for it. that is what you have now.
of course i can make it all optional. errata show that there were several twi problems in the silicon.
but anyway, i do not understand that with idle mode, the lines show different. maybe i overlook something. _________________ Mark |
|
Back to top |
|
|
Tiny
Joined: 10 Nov 2010 Posts: 101 Location: The Netherlands
|
Posted: Tue Oct 03, 2017 5:56 am Post subject: |
|
|
Yes I use pull-up resistors with the value 4k7
please make it as een option so that my code stays working in future releases off bascom.
Regard Tiny |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Tue Oct 03, 2017 9:05 pm Post subject: |
|
|
i added 2 new options to the next release. the default will be as in 2079. _________________ Mark |
|
Back to top |
|
|
Tiny
Joined: 10 Nov 2010 Posts: 101 Location: The Netherlands
|
Posted: Wed Oct 04, 2017 5:45 am Post subject: |
|
|
Thanks Mark |
|
Back to top |
|
|
holli
Joined: 29 Jul 2010 Posts: 28
|
Posted: Sat Nov 04, 2017 1:04 am Post subject: |
|
|
Hi,
looks like the XMega D3 has the same problems, my temporary solution is to add a "waitus 10". Here's a example:
Code: |
$regfile = "xm128D3def.dat"
$crystal = 32000000
$hwstack = 70
$swstack = 50
$framesize = 50
Config Submode = New
Config Eeprom = Mapped
Config Osc = Enabled , 32mhzosc = Enabled
'configure the systemclock
Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
'#####################################################
Dim Twi_start As Byte
Open "TWIC" For Binary As #4
Config Twic = 100000
I2cinit #4
'#####################################################
'LCD
Const Rtc_w = &HD0
Const Rtc_r = &HD1
Dim Rtc_config(3) As Byte
Do
I2cstart #4 ' generate start code
I2cwbyte Rtc_w , #4 ' send address
I2cwbyte 0 , #4 ' start address
I2cstop #4
I2cstart #4 ' Generate start code
I2cwbyte Rtc_r , #4 ' send address
I2crbyte Rtc_config(1) , Ack , #4 ' read config
I2crbyte Rtc_config(2) , Ack , #4 ' read config
I2crbyte Rtc_config(3) , Nack , #4 ' read config
'Waitus 10
I2cstop #4
Loop
|
|
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Sat Nov 04, 2017 9:40 am Post subject: |
|
|
I think it also has to do with the device on the bus.
anyway, here is the code from the next version you can use in xmega.lib
;generate I2C stop
_i2c_stop:
#IF Varexist("_TWI_STOP_1")
Ldi r24, &B111 ; perform stop
std z+3,R24 ; generate stop
#ELSEIF Varexist("_TWI_STOP_2")
Ldi r24, &B111 ; perform stop
std z+3,R24 ; generate stop
_i2c_stop3:
ldd r25, z+4 ; get status
andi r25,&B11 ; isolate bus state
cpi r25,2 ; should be 1 (idle) or 0, but not 2 (owner)
breq _i2c_stop3 ; wait without sending new stop
#ELSE
Ldi r24, &B111 ; perform stop
st z+3,R24 ; generate stop
ld r24, z+4 ; get status
andi r24,&B11 ; isolate bus state
cpi r24,2 ; should be 1 (idle) or 0 but not owner (2)
breq _i2c_stop ; if not, send a new command, for some reason one is not enough?
#ENDIF
Ret _________________ Mark |
|
Back to top |
|
|
holli
Joined: 29 Jul 2010 Posts: 28
|
Posted: Sat Nov 04, 2017 4:43 pm Post subject: |
|
|
Thanks, Problem solved.
Btw, the chips involved here are DS1307 and PCF8523. Both had problems. |
|
Back to top |
|
|
|
|
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 You cannot attach files in this forum You cannot download files in this forum
|
|