inglewoodpete
Senior Member
I have been using a 20X2 (Firmware C.2) as an i2c slave and have been plagued by random lockups in the slave.
I have used PICAXEs as i2c slaves (28X1, 28X2, 40X1, & 40X2) for several years, so consider myself fairly familiar with them.
I understand that care must be taken with 'blocking' commands when it comes to time-critical background tasks like hSerial and hi2c. I accept that data corruptions can occur with incoming data if the kernel is not given enough time to clear the serial buffers in time for subsequent incoming data.
However, I believe the slave chip should be 100% stable and be able to recover from i2c overruns/overwrites. Which leads to the problem that I am encountering: occasional and random lockups of the i2c port of the slave. The timing of the lockup is random: it can take anything from 10 seconds to 10 minutes for the lockup to occur.
I have developed the following software to highlight the problem. I admit that it 'pushes the limits', with its extensive use of SerTxd commands. The 'bit-banged' serial output to the PE terminal disables internal interrupts, meaning that there is a risk that the i2c receive buffer may not be cleared, resulting is data corruption. However, this should not cause unrecoverable lockups of the i2c serial port. The code in the slave also regularly writes data to the scratchpad (in case this is the cause of the lockups - I suspect not).
When the lockup occurs, the master chip only reads '255' values from the slave. The only way to recover i2c communications is to power cycle the slave chip. The master chip does not need resetting, indicating that the problem is in the 20X2 i2c slave.
The circuit is a basic one: download circuits, indicator LEDs and 2 x 4.7kohm pullup resistors on the two i2c lines. The power pins of both chips have 100nF decoupling capacitors. The power supply is a 5-volt regulated bench supply. PE version 5.5.5
Slave code:
Software for the i2c master chip follows in the next post....
I have used PICAXEs as i2c slaves (28X1, 28X2, 40X1, & 40X2) for several years, so consider myself fairly familiar with them.
I understand that care must be taken with 'blocking' commands when it comes to time-critical background tasks like hSerial and hi2c. I accept that data corruptions can occur with incoming data if the kernel is not given enough time to clear the serial buffers in time for subsequent incoming data.
However, I believe the slave chip should be 100% stable and be able to recover from i2c overruns/overwrites. Which leads to the problem that I am encountering: occasional and random lockups of the i2c port of the slave. The timing of the lockup is random: it can take anything from 10 seconds to 10 minutes for the lockup to occur.
I have developed the following software to highlight the problem. I admit that it 'pushes the limits', with its extensive use of SerTxd commands. The 'bit-banged' serial output to the PE terminal disables internal interrupts, meaning that there is a risk that the i2c receive buffer may not be cleared, resulting is data corruption. However, this should not cause unrecoverable lockups of the i2c serial port. The code in the slave also regularly writes data to the scratchpad (in case this is the cause of the lockups - I suspect not).
When the lockup occurs, the master chip only reads '255' values from the slave. The only way to recover i2c communications is to power cycle the slave chip. The master chip does not need resetting, indicating that the problem is in the 20X2 i2c slave.
The circuit is a basic one: download circuits, indicator LEDs and 2 x 4.7kohm pullup resistors on the two i2c lines. The power pins of both chips have 100nF decoupling capacitors. The power supply is a 5-volt regulated bench supply. PE version 5.5.5
Slave code:
Code:
'20X2 i2c Slave code Firmware is C.2
Symbol Version = 3 'v0.3 24/06/2013 284 bytes Lockup Demo-3 Cut Down version Locks up.
'
'#COM 1 'AXE026 Cable
#PICAXE 20X2
#Terminal 38400 'SerTxd default at 32MHz
#No_Table
'
' **** Hardware Connections - i2c Slave 20X2
'
Symbol oLED = C.4 ' Indicator LED
'
Symbol bCommsStatus = b0 '<<<b0 is reserved for bit flags
Symbol ti2cInMode = Bit7 'Flag: Data received via i2c
'
Symbol bDebugi2c = b10 'w5
Symbol wIdleCounter = w6 'b12/13
Symbol bi2cAddress = b14 'w7
Symbol bInChar = b21 'w10
Symbol bCounter = b54 'w27
'
' **** Constants
'
Symbol False = 0
Symbol True = 1
'
Symbol cEmpty = 250 'Indicates empty location.
'
Symbol ci2cSlaveAddress = 5
'
' **** Scratchpad (20X2 - Bytes 0 to 127d)
'
Symbol sSerInBuffStart = 0
'Symbol sSerInBuffEnd = 63
'
'
' ****************************************************
' **** I n i t i a l i s a t i o n ****
' ****************************************************
'
Init: Output oLED
'
For bCounter = 1 to 8 'Bootup indicator
Toggle oLED
Pause 60
Next bCounter
'
SetFreq M32
Pause 100 'Allow speed to settle before outputting next line
SerTxd(CR, LF, CR, LF, "i2c Lockup test 20X2 32MHz v.", #Version, CR, LF)
'
'Initialise scratchpad
ptr = 0
Do
@ptrInc = cEmpty 'Fill scratchpad with "Empty" marker bytes (cEmpty=250)
Loop Until ptr = sSerInBuffStart
'
Flags = 0
SetIntFlags %01000000, %01000000 'Set hi2c to interrupt
'
'Initialise i2c as slave
bi2cAddress = ci2cSlaveAddress * 2
hi2cSetup i2cSlave, bi2cAddress
'
SerTxd("Entering main loop", CR, LF)
'
' ****************************************************
' **** Main program loop, runs at 32MHz ****
' ****************************************************
'
'Enters with ptr pointing to sSerInBuffStart
Do
If ti2cInMode = True Then 'i2c data has been received
'Ptr points to the location of the next byte to be read
GoSub FetchData 'Returns bInChar from scratchpad sequential data buffer
'
If bInChar = cEmpty Then 'Once past the available characters
bCommsStatus = 0 'Clear the i2c Status bits
'
SerTxd(CR, LF) 'Last debugging until next i2c packet received
Do 'Backfill scratchpad buffer with "empty" markers
@PtrDec = cEmpty
Loop Until Ptr = sSerInBuffStart
@Ptr = cEmpty 'Mark the first scratchpad location with "empty" marker
'First scratchpad location is poller by i2c Master
Else
Inc Ptr
EndIf
Else 'No i2c data received: indicate every 500 loops
Inc wIdleCounter
If wIdleCounter = 500 Then
wIdleCounter = 0
Inc bDebugi2c 'Should regularly get reset in the Interrupt routine
SerTxd("~", #bDebugi2c)
Do While bDebugi2c = 20: Loop 'Code loops here when i2c comms stops
EndIf
EndIf
Loop
'
' ****************************************************
' **** S u b r o u t i n e s ****
' ****************************************************
'
' **** FetchData: Get a byte of data from Lower Scratchpad area
'
' Exit: bInChar b21 Received Character
'
FetchData: SerTxd("@", #Ptr, ":") 'The location
bInChar = @Ptr 'The location's contents
If bInChar < 128 And bInChar > 31 Then
SerTxd(bInChar, " ") 'Standard ASCII characters
ElseIf bInChar = cEmpty Then 'Byte value 250
SerTxd("[EoD]")
Else 'Any "non-print" character 0-31, 128-249, 251-255
SerTxd("[", #bInChar, "] ")
EndIf
Return
'
' ************************************************************
' Interrupt handler
' ************************************************************
'
Interrupt: bDebugi2c = 0 'Reset watchdog counter
ti2cInMode = True 'Remains set
hi2cFlag = False
SetIntFlags %01000000, %01000000 'Set hi2c to interrupt again
Return
' ************************************************************