Forked from Frank's excellent library and extended to include I2C0 on PTC8 & PTC9. "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."

Fork of KL25Z_I2C_busreset by Frank Vannieuwkerke

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers I2C_busreset.cpp Source File

I2C_busreset.cpp

00001 /**************************************************************************************************
00002  *****                                                                                        *****
00003  *****  Name: KL25Z I2C_busreset.cpp                                                          *****
00004  *****  Date: 24/11/2013                                                                      *****
00005  *****  Auth: Frank Vannieuwkerke                                                             *****
00006  *****  Func: library for unblocking I2C bus on KL25Z board                                   *****
00007  *****  Info: MPL3115A2-AN4481                                                                *****
00008  **************************************************************************************************/
00009 #ifdef KL25Z
00010 
00011 #include "I2C_busreset.h"
00012 
00013 void I2C_busreset(void)
00014 {
00015     // Chris Heald [23 Feb 2015]: Adding I2C on PTC9, PTC8, PCR MUX 2..
00016     if((PORTC->PCR[8] & PORT_PCR_MUX(2)) && (PORTC->PCR[9] & PORT_PCR_MUX(2)))
00017     {
00018         I2C0->C1 &= 0x7f;                 // Disable I2C0 bus
00019         PORTC->PCR[8] = PORT_PCR_MUX(1);  // PTC8 Alt1 (pin)
00020         PORTC->PCR[9] = PORT_PCR_MUX(1);  // PTC9 Alt1 (pin)
00021         if((PTC->PDIR & 0x3) != 3)        // When PTC8 / PTC9 are not 1 : I2C0 bus lock-up
00022         {
00023             PTC->PDDR |= 0x2;             // Set PTC8 as a GPIO output so we can bit bang it
00024             PTC->PDOR |= 0x2;             // Set PTC8 (SCL) pin high;
00025             wait_ms(1);
00026             while(!(PTC->PDIR & 0x1))     // bit bang SCL until the offending device releases the bus
00027             {   
00028                 PTC->PDOR &= 0xfffffffd;  // Set PTC8 (SCL) pin low;
00029                 wait_ms(1);
00030                 PTC->PDOR |= 0x2;         // Set PTC8 (SCL) pin high;
00031                 wait_ms(1);
00032             }
00033         }
00034         // Reinstate I2C1 bus pins
00035         PORTC->PCR[8] = PORT_PCR_MUX(2);  // PTC8 Alt2 (SCL)
00036         PORTC->PCR[9] = PORT_PCR_MUX(2);  // PTC9 Alt2 (SDA)
00037         I2C0->C1 |= 0x80;                 // Enable I2C0 bus
00038     }
00039 
00040 
00041     if((PORTE->PCR[1] & PORT_PCR_MUX(6)) && (PORTE->PCR[0] & PORT_PCR_MUX(6)))
00042     {
00043         I2C1->C1 &= 0x7f;                 // Disable I2C1 bus
00044         PORTE->PCR[1] = PORT_PCR_MUX(1);  // PTE1 Alt1 (pin)
00045         PORTE->PCR[0] = PORT_PCR_MUX(1);  // PTE0 Alt1 (pin)
00046         if((PTE->PDIR & 0x3) != 3)        // When PTE0 / PTE1 are not 1 : I2C1 bus lock-up
00047         {
00048             PTE->PDDR |= 0x2;             // Set PTE1 as a GPIO output so we can bit bang it
00049             PTE->PDOR |= 0x2;             // Set PTE1 (SCL) pin high;
00050             wait_ms(1);
00051             while(!(PTE->PDIR & 0x1))     // bit bang SCL until the offending device releases the bus
00052             {   
00053                 PTE->PDOR &= 0xfffffffd;  // Set PTE1 (SCL) pin low;
00054                 wait_ms(1);
00055                 PTE->PDOR |= 0x2;         // Set PTE1 (SCL) pin high;
00056                 wait_ms(1);
00057             }
00058         }
00059         // Reinstate I2C1 bus pins
00060         PORTE->PCR[1] = PORT_PCR_MUX(6);  // PTE1 Alt6 (SCL)
00061         PORTE->PCR[0] = PORT_PCR_MUX(6);  // PTE0 Alt6 (SDA)
00062         I2C1->C1 |= 0x80;                 // Enable I2C1 bus
00063     }
00064 
00065     if((PORTE->PCR[24] & PORT_PCR_MUX(5)) && (PORTE->PCR[25] & PORT_PCR_MUX(5)))
00066     {
00067         I2C0->C1 &= 0x7f;                 // Disable I2C0 bus
00068         PORTE->PCR[24] = PORT_PCR_MUX(1); // PTE24 Alt1 (pin)
00069         PORTE->PCR[25] = PORT_PCR_MUX(1); // PTE25 Alt1 (pin)
00070         if((PTE->PDIR & 0x03000000) != 0x03000000)  // When PTE24 / PTE25 are not 1 : I2C0 bus lock-up
00071         {
00072             PTE->PDDR |= 0x01000000;      // Set PTE24 as a GPIO output so we can bit bang it
00073             PTE->PDOR |= 0x01000000;      // Set PTE24 (SCL) pin high;
00074             wait_ms(1);
00075             while(!(PTE->PDIR & 0x1))     // bit bang SCL until the offending device releases the bus
00076             {   
00077                 PTE->PDOR &= 0xfeffffff;  // Set PTE24 (SCL) pin low;
00078                 wait_ms(1);
00079                 PTE->PDOR |= 0x01000000;  // Set PTE24 (SCL) pin high;
00080                 wait_ms(1);
00081             }
00082         }
00083         // Reinstate I2C0 bus pins
00084         PORTE->PCR[24] = PORT_PCR_MUX(5); // PTE24 Alt6 (SCL)
00085         PORTE->PCR[25] = PORT_PCR_MUX(5); // PTE25 Alt6 (SDA)
00086         I2C0->C1 |= 0x80;                 // Enable I2C0 bus
00087     }
00088 }
00089 #endif