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

Committer:
ateyercheese
Date:
Mon Jul 04 14:01:13 2016 +0000
Revision:
5:28a540b25e1c
Parent:
3:7584a206afd4
Ifdef to ensure target is present (should use underlying target defs, but I can't find them)

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 **************************************************************************************************/
ateyercheese 3:7584a206afd4 9 #ifdef KL25Z
frankvnk 0:e9beb537cf77 10
frankvnk 0:e9beb537cf77 11 #include "I2C_busreset.h"
frankvnk 0:e9beb537cf77 12
frankvnk 0:e9beb537cf77 13 void I2C_busreset(void)
frankvnk 0:e9beb537cf77 14 {
ateyercheese 1:fe493f707844 15 // Chris Heald [23 Feb 2015]: Adding I2C on PTC9, PTC8, PCR MUX 2..
ateyercheese 1:fe493f707844 16 if((PORTC->PCR[8] & PORT_PCR_MUX(2)) && (PORTC->PCR[9] & PORT_PCR_MUX(2)))
ateyercheese 1:fe493f707844 17 {
ateyercheese 1:fe493f707844 18 I2C0->C1 &= 0x7f; // Disable I2C0 bus
ateyercheese 1:fe493f707844 19 PORTC->PCR[8] = PORT_PCR_MUX(1); // PTC8 Alt1 (pin)
ateyercheese 1:fe493f707844 20 PORTC->PCR[9] = PORT_PCR_MUX(1); // PTC9 Alt1 (pin)
ateyercheese 2:a166055977ec 21 if((PTC->PDIR & 0x3) != 3) // When PTC8 / PTC9 are not 1 : I2C0 bus lock-up
ateyercheese 1:fe493f707844 22 {
ateyercheese 2:a166055977ec 23 PTC->PDDR |= 0x2; // Set PTC8 as a GPIO output so we can bit bang it
ateyercheese 2:a166055977ec 24 PTC->PDOR |= 0x2; // Set PTC8 (SCL) pin high;
ateyercheese 1:fe493f707844 25 wait_ms(1);
ateyercheese 1:fe493f707844 26 while(!(PTC->PDIR & 0x1)) // bit bang SCL until the offending device releases the bus
ateyercheese 1:fe493f707844 27 {
ateyercheese 2:a166055977ec 28 PTC->PDOR &= 0xfffffffd; // Set PTC8 (SCL) pin low;
ateyercheese 1:fe493f707844 29 wait_ms(1);
ateyercheese 2:a166055977ec 30 PTC->PDOR |= 0x2; // Set PTC8 (SCL) pin high;
ateyercheese 1:fe493f707844 31 wait_ms(1);
ateyercheese 1:fe493f707844 32 }
ateyercheese 1:fe493f707844 33 }
ateyercheese 1:fe493f707844 34 // Reinstate I2C1 bus pins
ateyercheese 2:a166055977ec 35 PORTC->PCR[8] = PORT_PCR_MUX(2); // PTC8 Alt2 (SCL)
ateyercheese 2:a166055977ec 36 PORTC->PCR[9] = PORT_PCR_MUX(2); // PTC9 Alt2 (SDA)
ateyercheese 1:fe493f707844 37 I2C0->C1 |= 0x80; // Enable I2C0 bus
ateyercheese 1:fe493f707844 38 }
ateyercheese 1:fe493f707844 39
ateyercheese 1:fe493f707844 40
frankvnk 0:e9beb537cf77 41 if((PORTE->PCR[1] & PORT_PCR_MUX(6)) && (PORTE->PCR[0] & PORT_PCR_MUX(6)))
frankvnk 0:e9beb537cf77 42 {
frankvnk 0:e9beb537cf77 43 I2C1->C1 &= 0x7f; // Disable I2C1 bus
frankvnk 0:e9beb537cf77 44 PORTE->PCR[1] = PORT_PCR_MUX(1); // PTE1 Alt1 (pin)
frankvnk 0:e9beb537cf77 45 PORTE->PCR[0] = PORT_PCR_MUX(1); // PTE0 Alt1 (pin)
frankvnk 0:e9beb537cf77 46 if((PTE->PDIR & 0x3) != 3) // When PTE0 / PTE1 are not 1 : I2C1 bus lock-up
frankvnk 0:e9beb537cf77 47 {
frankvnk 0:e9beb537cf77 48 PTE->PDDR |= 0x2; // Set PTE1 as a GPIO output so we can bit bang it
frankvnk 0:e9beb537cf77 49 PTE->PDOR |= 0x2; // Set PTE1 (SCL) pin high;
frankvnk 0:e9beb537cf77 50 wait_ms(1);
frankvnk 0:e9beb537cf77 51 while(!(PTE->PDIR & 0x1)) // bit bang SCL until the offending device releases the bus
frankvnk 0:e9beb537cf77 52 {
frankvnk 0:e9beb537cf77 53 PTE->PDOR &= 0xfffffffd; // Set PTE1 (SCL) pin low;
frankvnk 0:e9beb537cf77 54 wait_ms(1);
frankvnk 0:e9beb537cf77 55 PTE->PDOR |= 0x2; // Set PTE1 (SCL) pin high;
frankvnk 0:e9beb537cf77 56 wait_ms(1);
frankvnk 0:e9beb537cf77 57 }
frankvnk 0:e9beb537cf77 58 }
frankvnk 0:e9beb537cf77 59 // Reinstate I2C1 bus pins
frankvnk 0:e9beb537cf77 60 PORTE->PCR[1] = PORT_PCR_MUX(6); // PTE1 Alt6 (SCL)
frankvnk 0:e9beb537cf77 61 PORTE->PCR[0] = PORT_PCR_MUX(6); // PTE0 Alt6 (SDA)
frankvnk 0:e9beb537cf77 62 I2C1->C1 |= 0x80; // Enable I2C1 bus
frankvnk 0:e9beb537cf77 63 }
frankvnk 0:e9beb537cf77 64
frankvnk 0:e9beb537cf77 65 if((PORTE->PCR[24] & PORT_PCR_MUX(5)) && (PORTE->PCR[25] & PORT_PCR_MUX(5)))
frankvnk 0:e9beb537cf77 66 {
frankvnk 0:e9beb537cf77 67 I2C0->C1 &= 0x7f; // Disable I2C0 bus
frankvnk 0:e9beb537cf77 68 PORTE->PCR[24] = PORT_PCR_MUX(1); // PTE24 Alt1 (pin)
frankvnk 0:e9beb537cf77 69 PORTE->PCR[25] = PORT_PCR_MUX(1); // PTE25 Alt1 (pin)
frankvnk 0:e9beb537cf77 70 if((PTE->PDIR & 0x03000000) != 0x03000000) // When PTE24 / PTE25 are not 1 : I2C0 bus lock-up
frankvnk 0:e9beb537cf77 71 {
frankvnk 0:e9beb537cf77 72 PTE->PDDR |= 0x01000000; // Set PTE24 as a GPIO output so we can bit bang it
frankvnk 0:e9beb537cf77 73 PTE->PDOR |= 0x01000000; // Set PTE24 (SCL) pin high;
frankvnk 0:e9beb537cf77 74 wait_ms(1);
frankvnk 0:e9beb537cf77 75 while(!(PTE->PDIR & 0x1)) // bit bang SCL until the offending device releases the bus
frankvnk 0:e9beb537cf77 76 {
frankvnk 0:e9beb537cf77 77 PTE->PDOR &= 0xfeffffff; // Set PTE24 (SCL) pin low;
frankvnk 0:e9beb537cf77 78 wait_ms(1);
frankvnk 0:e9beb537cf77 79 PTE->PDOR |= 0x01000000; // Set PTE24 (SCL) pin high;
frankvnk 0:e9beb537cf77 80 wait_ms(1);
frankvnk 0:e9beb537cf77 81 }
frankvnk 0:e9beb537cf77 82 }
frankvnk 0:e9beb537cf77 83 // Reinstate I2C0 bus pins
frankvnk 0:e9beb537cf77 84 PORTE->PCR[24] = PORT_PCR_MUX(5); // PTE24 Alt6 (SCL)
frankvnk 0:e9beb537cf77 85 PORTE->PCR[25] = PORT_PCR_MUX(5); // PTE25 Alt6 (SDA)
frankvnk 0:e9beb537cf77 86 I2C0->C1 |= 0x80; // Enable I2C0 bus
frankvnk 0:e9beb537cf77 87 }
frankvnk 0:e9beb537cf77 88 }
ateyercheese 3:7584a206afd4 89 #endif