Tool to recover from an I2C bus lockup on the KL25Z

Dependents:   Ejerc_slave_I2c

This tool allows you to recover from an I2C bus lockup on I2C0 (PTE24, PTE25) and I2C1 (PTE0, PTE1).
The reset is only carried out when the corresponding I2C bus is enabled.

Add following code to your program :

#include "I2C_busreset.h"
...
...
int main (void)
{
    I2C_busreset();
    ....
Committer:
frankvnk
Date:
Wed Feb 19 19:18:49 2014 +0000
Revision:
0:e9beb537cf77
Initial release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 0:e9beb537cf77 1 /**************************************************************************************************
frankvnk 0:e9beb537cf77 2 ***** *****
frankvnk 0:e9beb537cf77 3 ***** Name: KL25Z I2C_busreset.cpp *****
frankvnk 0:e9beb537cf77 4 ***** Date: 24/11/2013 *****
frankvnk 0:e9beb537cf77 5 ***** Auth: Frank Vannieuwkerke *****
frankvnk 0:e9beb537cf77 6 ***** Func: library for unblocking I2C bus on KL25Z board *****
frankvnk 0:e9beb537cf77 7 ***** Info: MPL3115A2-AN4481 *****
frankvnk 0:e9beb537cf77 8 **************************************************************************************************/
frankvnk 0:e9beb537cf77 9
frankvnk 0:e9beb537cf77 10 #include "I2C_busreset.h"
frankvnk 0:e9beb537cf77 11
frankvnk 0:e9beb537cf77 12 void I2C_busreset(void)
frankvnk 0:e9beb537cf77 13 {
frankvnk 0:e9beb537cf77 14 if((PORTE->PCR[1] & PORT_PCR_MUX(6)) && (PORTE->PCR[0] & PORT_PCR_MUX(6)))
frankvnk 0:e9beb537cf77 15 {
frankvnk 0:e9beb537cf77 16 I2C1->C1 &= 0x7f; // Disable I2C1 bus
frankvnk 0:e9beb537cf77 17 PORTE->PCR[1] = PORT_PCR_MUX(1); // PTE1 Alt1 (pin)
frankvnk 0:e9beb537cf77 18 PORTE->PCR[0] = PORT_PCR_MUX(1); // PTE0 Alt1 (pin)
frankvnk 0:e9beb537cf77 19 if((PTE->PDIR & 0x3) != 3) // When PTE0 / PTE1 are not 1 : I2C1 bus lock-up
frankvnk 0:e9beb537cf77 20 {
frankvnk 0:e9beb537cf77 21 PTE->PDDR |= 0x2; // Set PTE1 as a GPIO output so we can bit bang it
frankvnk 0:e9beb537cf77 22 PTE->PDOR |= 0x2; // Set PTE1 (SCL) pin high;
frankvnk 0:e9beb537cf77 23 wait_ms(1);
frankvnk 0:e9beb537cf77 24 while(!(PTE->PDIR & 0x1)) // bit bang SCL until the offending device releases the bus
frankvnk 0:e9beb537cf77 25 {
frankvnk 0:e9beb537cf77 26 PTE->PDOR &= 0xfffffffd; // Set PTE1 (SCL) pin low;
frankvnk 0:e9beb537cf77 27 wait_ms(1);
frankvnk 0:e9beb537cf77 28 PTE->PDOR |= 0x2; // Set PTE1 (SCL) pin high;
frankvnk 0:e9beb537cf77 29 wait_ms(1);
frankvnk 0:e9beb537cf77 30 }
frankvnk 0:e9beb537cf77 31 }
frankvnk 0:e9beb537cf77 32 // Reinstate I2C1 bus pins
frankvnk 0:e9beb537cf77 33 PORTE->PCR[1] = PORT_PCR_MUX(6); // PTE1 Alt6 (SCL)
frankvnk 0:e9beb537cf77 34 PORTE->PCR[0] = PORT_PCR_MUX(6); // PTE0 Alt6 (SDA)
frankvnk 0:e9beb537cf77 35 I2C1->C1 |= 0x80; // Enable I2C1 bus
frankvnk 0:e9beb537cf77 36 }
frankvnk 0:e9beb537cf77 37
frankvnk 0:e9beb537cf77 38 if((PORTE->PCR[24] & PORT_PCR_MUX(5)) && (PORTE->PCR[25] & PORT_PCR_MUX(5)))
frankvnk 0:e9beb537cf77 39 {
frankvnk 0:e9beb537cf77 40 I2C0->C1 &= 0x7f; // Disable I2C0 bus
frankvnk 0:e9beb537cf77 41 PORTE->PCR[24] = PORT_PCR_MUX(1); // PTE24 Alt1 (pin)
frankvnk 0:e9beb537cf77 42 PORTE->PCR[25] = PORT_PCR_MUX(1); // PTE25 Alt1 (pin)
frankvnk 0:e9beb537cf77 43 if((PTE->PDIR & 0x03000000) != 0x03000000) // When PTE24 / PTE25 are not 1 : I2C0 bus lock-up
frankvnk 0:e9beb537cf77 44 {
frankvnk 0:e9beb537cf77 45 PTE->PDDR |= 0x01000000; // Set PTE24 as a GPIO output so we can bit bang it
frankvnk 0:e9beb537cf77 46 PTE->PDOR |= 0x01000000; // Set PTE24 (SCL) pin high;
frankvnk 0:e9beb537cf77 47 wait_ms(1);
frankvnk 0:e9beb537cf77 48 while(!(PTE->PDIR & 0x1)) // bit bang SCL until the offending device releases the bus
frankvnk 0:e9beb537cf77 49 {
frankvnk 0:e9beb537cf77 50 PTE->PDOR &= 0xfeffffff; // Set PTE24 (SCL) pin low;
frankvnk 0:e9beb537cf77 51 wait_ms(1);
frankvnk 0:e9beb537cf77 52 PTE->PDOR |= 0x01000000; // Set PTE24 (SCL) pin high;
frankvnk 0:e9beb537cf77 53 wait_ms(1);
frankvnk 0:e9beb537cf77 54 }
frankvnk 0:e9beb537cf77 55 }
frankvnk 0:e9beb537cf77 56 // Reinstate I2C0 bus pins
frankvnk 0:e9beb537cf77 57 PORTE->PCR[24] = PORT_PCR_MUX(5); // PTE24 Alt6 (SCL)
frankvnk 0:e9beb537cf77 58 PORTE->PCR[25] = PORT_PCR_MUX(5); // PTE25 Alt6 (SDA)
frankvnk 0:e9beb537cf77 59 I2C0->C1 |= 0x80; // Enable I2C0 bus
frankvnk 0:e9beb537cf77 60 }
frankvnk 0:e9beb537cf77 61 }