mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Files at this revision

API Documentation at this revision

Comitter:
mbed_official
Date:
Wed Feb 11 08:30:07 2015 +0000
Parent:
469:fc4922e0c183
Child:
471:36e91e24cc94
Commit message:
Synchronized with git revision cef6954740757764062afa31fc6341450433a71c

Full URL: https://github.com/mbedmicro/mbed/commit/cef6954740757764062afa31fc6341450433a71c/

I2CSlave support for lpc812

Changed in this revision

hal/i2c_api.h Show annotated file Show diff for this revision Revisions of this file
targets/cmsis/TARGET_NXP/TARGET_LPC81X/TARGET_LPC810/system_LPC8xx.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_NXP/TARGET_LPC81X/i2c_api.c Show annotated file Show diff for this revision Revisions of this file
--- a/hal/i2c_api.h	Mon Feb 09 09:30:07 2015 +0000
+++ b/hal/i2c_api.h	Wed Feb 11 08:30:07 2015 +0000
@@ -46,6 +46,8 @@
 int  i2c_slave_receive(i2c_t *obj);
 int  i2c_slave_read   (i2c_t *obj, char *data, int length);
 int  i2c_slave_write  (i2c_t *obj, const char *data, int length);
+int  i2c_slave_byte_read(i2c_t *obj, int last);
+int  i2c_slave_byte_write(i2c_t *obj, int data);
 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask);
 #endif
 
--- a/targets/cmsis/TARGET_NXP/TARGET_LPC81X/TARGET_LPC810/system_LPC8xx.c	Mon Feb 09 09:30:07 2015 +0000
+++ b/targets/cmsis/TARGET_NXP/TARGET_LPC81X/TARGET_LPC810/system_LPC8xx.c	Wed Feb 11 08:30:07 2015 +0000
@@ -100,14 +100,18 @@
 //   </h>
 // </e>
 */
+
+// 1 == IRC 12Mhz 2 == System Oscillator 12Mhz Xtal:
 #define CLOCK_SETUP           1
+//use PLL for IRC
 #define SYSOSCCTRL_Val        0x00000000              // Reset: 0x000
 #define WDTOSCCTRL_Val        0x00000000              // Reset: 0x000
-#define SYSPLLCTRL_Val        0x00000041              // Reset: 0x000
-#define SYSPLLCLKSEL_Val      0x00000000              // Reset: 0x000
-#define MAINCLKSEL_Val        0x00000003              // Reset: 0x000
-#define SYSAHBCLKDIV_Val      0x00000001              // Reset: 0x001
-
+#define SYSPLLCTRL_Val        0x00000041              // Reset: 0x000  MSEL=1 => M=2; PSEL=2 => 2P=8; PLLCLKOUT = (12x2) = 24MHz
+//#define SYSPLLCTRL_Val        0x00000004              // Reset: 0x000  MSEL=4 => M=5; PSEL=0 => 2P=2; PLLCLKOUT = (12x5) = 60MHz
+#define SYSPLLCLKSEL_Val      0x00000000              // Reset: 0x000  Select IRC
+#define MAINCLKSEL_Val        0x00000003              // Reset: 0x000  MainClock = PLLCLKOUT
+#define SYSAHBCLKDIV_Val      0x00000001              // Reset: 0x001  DIV=1 => SYSTEMCORECLK = 24 / 1 = 24MHz
+//#define SYSAHBCLKDIV_Val      0x00000002              // Reset: 0x001  DIV=2 => SYSTEMCORECLK = 60 / 2 = 30MHz
 /*
 //-------- <<< end of configuration section >>> ------------------------------
 */
@@ -235,9 +239,10 @@
 /*----------------------------------------------------------------------------
   Clock Variable definitions
  *----------------------------------------------------------------------------*/
-uint32_t SystemCoreClock = __SYSTEM_CLOCK;/*!< System Clock Frequency (Core Clock)*/
+uint32_t MainClock = __MAIN_CLOCK;         /*!< Main Clock Frequency */
+uint32_t SystemCoreClock = __SYSTEM_CLOCK; /*!< System Clock Frequency (Core Clock)*/
 
-
+//Replaced SystemCoreClock with MainClock
 /*----------------------------------------------------------------------------
   Clock functions
  *----------------------------------------------------------------------------*/
@@ -268,46 +273,46 @@
 
   switch (LPC_SYSCON->MAINCLKSEL & 0x03) {
     case 0:                             /* Internal RC oscillator             */
-      SystemCoreClock = __IRC_OSC_CLK;
+      MainClock = __IRC_OSC_CLK;
       break;
     case 1:                             /* Input Clock to System PLL          */
       switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
           case 0:                       /* Internal RC oscillator             */
-            SystemCoreClock = __IRC_OSC_CLK;
+            MainClock = __IRC_OSC_CLK;
             break;
           case 1:                       /* System oscillator                  */
-            SystemCoreClock = __SYS_OSC_CLK;
+            MainClock = __SYS_OSC_CLK;
             break;
           case 2:                       /* Reserved                           */
-            SystemCoreClock = 0;
+            MainClock = 0;
             break;
           case 3:                       /* CLKIN pin                          */
-            SystemCoreClock = __CLKIN_CLK;
+            MainClock = __CLKIN_CLK;
             break;
       }
       break;
     case 2:                             /* WDT Oscillator                     */
-      SystemCoreClock = wdt_osc;
+      MainClock = wdt_osc;
       break;
     case 3:                             /* System PLL Clock Out               */
       switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
           case 0:                       /* Internal RC oscillator             */
-            SystemCoreClock = __IRC_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
+            MainClock = __IRC_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
             break;
           case 1:                       /* System oscillator                  */
-            SystemCoreClock = __SYS_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
+            MainClock = __SYS_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
             break;
           case 2:                       /* Reserved                           */
-            SystemCoreClock = 0;
+            MainClock = 0;
             break;
           case 3:                       /* CLKIN pin                          */
-            SystemCoreClock = __CLKIN_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
+            MainClock = __CLKIN_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
             break;
       }
       break;
   }
 
-  SystemCoreClock /= LPC_SYSCON->SYSAHBCLKDIV;
+  SystemCoreClock = MainClock / LPC_SYSCON->SYSAHBCLKDIV;
 
 }
 
--- a/targets/hal/TARGET_NXP/TARGET_LPC81X/i2c_api.c	Mon Feb 09 09:30:07 2015 +0000
+++ b/targets/hal/TARGET_NXP/TARGET_LPC81X/i2c_api.c	Wed Feb 11 08:30:07 2015 +0000
@@ -17,6 +17,8 @@
 #include "cmsis.h"
 #include "pinmap.h"
 
+#if DEVICE_I2C
+
 static const SWM_Map SWM_I2C_SDA[] = {
     {7, 24},
 };
@@ -75,6 +77,10 @@
     i2c_interface_enable(obj);
 }
 
+//Actually Wrong. Spec says: First store Address in DAT before setting STA ! 
+//Undefined state when using single byte I2C operations and too much delay
+//between i2c_start and do_i2c_write(Address).
+//Also note that lpc812 will immediately continue reading a byte when Address b0 == 1
 inline int i2c_start(i2c_t *obj) {
     int status = 0;
     if (repeated_start) {
@@ -86,8 +92,6 @@
     return status;
 }
 
-
-
 //Generate Stop condition and wait until bus is Idle
 //Will also send NAK for previous RD
 inline int i2c_stop(i2c_t *obj) {
@@ -95,7 +99,8 @@
 
     obj->i2c->MSTCTL = (1 << 2) | (1 << 0); // STP bit and Continue bit. Sends NAK to complete previous RD
     
-    while ((obj->i2c->STAT & ((7 << 1) | (1 << 0))) != ((0 << 1) | (1 << 0))) { //Spin until Ready (b0 == 1)and Status is Idle (b3..b1 == 000)
+    //Spin until Ready (b0 == 1)and Status is Idle (b3..b1 == 000)
+    while ((obj->i2c->STAT & ((7 << 1) | (1 << 0))) != ((0 << 1) | (1 << 0))) { 
         timeout ++;
         if (timeout > 100000) return 1;
     }
@@ -265,3 +270,244 @@
 
     return ack;
 }
+
+#if DEVICE_I2CSLAVE
+
+#define I2C_SLVDAT(x)        (x->i2c->SLVDAT)
+#define I2C_SLVSTAT(x)      ((x->i2c->STAT >> 9) & (0x03))
+#define I2C_SLVSI(x)        ((x->i2c->STAT >> 8) & (0x01))
+//#define I2C_SLVCNT(x)        (x->i2c->SLVCTL = (1 << 0))
+//#define I2C_SLVNAK(x)        (x->i2c->SLVCTL = (1 << 1))
+
+#if(0)
+// Wait until the Slave Serial Interrupt (SI) is set
+// Timeout when it takes too long.
+static int i2c_wait_slave_SI(i2c_t *obj) {
+    int timeout = 0;
+    while (!(obj->i2c->STAT & (1 << 8))) {
+        timeout++;
+        if (timeout > 100000) return -1;
+    }
+    return 0;
+}
+#endif
+
+void i2c_slave_mode(i2c_t *obj, int enable_slave) {
+
+  if (enable_slave) {
+//    obj->i2c->CFG &= ~(1 << 0); //Disable Master mode    
+    obj->i2c->CFG |=  (1 << 1); //Enable Slave mode
+  }
+  else {
+//    obj->i2c->CFG |=  (1 << 0); //Enable Master mode    
+    obj->i2c->CFG &= ~(1 << 1); //Disable Slave mode
+  } 
+}
+
+// Wait for next I2C event and find out what is going on
+//
+int i2c_slave_receive(i2c_t *obj) {
+  int addr;
+  
+  // Check if there is any data pending
+  if (! I2C_SLVSI(obj)) {
+    return 0; //NoData    
+  };
+  
+  // Check State
+  switch(I2C_SLVSTAT(obj)) {
+    case 0x0: // Slave address plus R/W received 
+              // At least one of the four slave addresses has been matched by hardware.
+              // You can figure out which address by checking Slave address match Index in STAT register.
+               
+              // Get the received address
+              addr = I2C_SLVDAT(obj) & 0xFF;
+              // Send ACK on address and Continue
+              obj->i2c->SLVCTL = (1 << 0); 
+              
+              if (addr == 0x00) {
+                return 2; //WriteGeneral
+              }  
+              //check the RW bit
+              if ((addr & 0x01) == 0x01) {
+                return 1; //ReadAddressed
+              }
+              else {
+                return 3; //WriteAddressed
+              }
+              //break;
+    
+    case 0x1: // Slave receive. Received data is available (Slave Receiver mode).
+              // Oops, should never get here...     
+              obj->i2c->SLVCTL = (1 << 1);  // Send NACK on received data, try to recover...
+              return 0; //NoData        
+              
+    case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode).
+              // Oops, should never get here...         
+              I2C_SLVDAT(obj) = 0xFF;       // Send dummy data for transmission
+              obj->i2c->SLVCTL = (1 << 0);  // Continue and try to recover...
+              return 0; //NoData        
+    
+    case 0x3: // Reserved.
+    default:  // Oops, should never get here... 
+              obj->i2c->SLVCTL = (1 << 0);  // Continue and try to recover...              
+              return 0; //NoData        
+              //break; 
+  } //switch status  
+}
+
+// The dedicated I2C Slave byte read and byte write functions need to be called
+// from 'common' mbed I2CSlave API for devices that have separate Master and 
+// Slave engines such as the lpc812 and lpc1549.
+
+//Called when Slave is addressed for Write, Slave will receive Data in polling mode
+//Parameter last=1 means received byte will be NACKed.
+int i2c_slave_byte_read(i2c_t *obj, int last) {
+  int data;
+  
+  // Wait for data
+  while (!I2C_SLVSI(obj)); // Wait forever
+//if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout
+
+  // Dont bother to check State, were not returning it anyhow..
+//if (I2C_SLVSTAT(obj)) == 0x01) {
+  // Slave receive. Received data is available (Slave Receiver mode).    
+//};
+
+  data = I2C_SLVDAT(obj) & 0xFF; // Get and store the received data
+  if (last) {
+    obj->i2c->SLVCTL = (1 << 1);  // Send NACK on received data and Continue 
+  }    
+  else {  
+    obj->i2c->SLVCTL = (1 << 0);  // Send ACK on data and Continue to read                
+  }
+ 
+  return data; 
+}
+
+
+//Called when Slave is addressed for Read, Slave will send Data in polling mode
+//
+int i2c_slave_byte_write(i2c_t *obj, int data) {
+
+  // Wait until Ready 
+  while (!I2C_SLVSI(obj)); // Wait forever
+//  if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout
+
+  // Check State
+  switch(I2C_SLVSTAT(obj)) {
+    case 0x0: // Slave address plus R/W received 
+              // At least one of the four slave addresses has been matched by hardware.
+              // You can figure out which address by checking Slave address match Index in STAT register.                
+              // I2C Restart occurred
+              return -1; 
+              //break;    
+    case 0x1: // Slave receive. Received data is available (Slave Receiver mode).
+              // Should not get here... 
+              return -2;
+              //break;                
+    case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode).
+              I2C_SLVDAT(obj) = data & 0xFF; // Store the data for transmission
+              obj->i2c->SLVCTL = (1 << 0);   // Continue to send
+              
+              return 1;    
+              //break;      
+    case 0x3: // Reserved.
+    default:
+              // Should not get here... 
+              return -3;
+              //break; 
+  } // switch status
+}
+
+
+//Called when Slave is addressed for Write, Slave will receive Data in polling mode
+//Parameter length (>=1) is the maximum allowable number of bytes. All bytes will be ACKed.
+int i2c_slave_read(i2c_t *obj, char *data, int length) {
+  int count=0;
+  
+  // Read and ACK all expected bytes
+  while (count < length) {
+    // Wait for data
+    while (!I2C_SLVSI(obj)); // Wait forever
+//    if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout
+
+    // Check State
+    switch(I2C_SLVSTAT(obj)) {
+      case 0x0: // Slave address plus R/W received 
+                // At least one of the four slave addresses has been matched by hardware.
+                // You can figure out which address by checking Slave address match Index in STAT register.                
+                // I2C Restart occurred
+                return -1; 
+                //break;
+    
+      case 0x1: // Slave receive. Received data is available (Slave Receiver mode).
+                data[count] = I2C_SLVDAT(obj) & 0xFF; // Get and store the received data
+                obj->i2c->SLVCTL = (1 << 0);          // Send ACK on data and Continue to read                
+                break;
+
+      case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode).
+      case 0x3: // Reserved.
+      default:  // Should never get here... 
+                return -2;
+                //break; 
+    } // switch status
+    
+    count++;
+  } // for all bytes
+    
+  return count; // Received the expected number of bytes
+}
+
+
+//Called when Slave is addressed for Read, Slave will send Data in polling mode
+//Parameter length (>=1) is the maximum number of bytes. Exit when Slave byte is NACKed.
+int i2c_slave_write(i2c_t *obj, const char *data, int length) {
+  int count;
+  
+  // Send and all bytes or Exit on NAK
+  for (count=0; count < length; count++) {
+    // Wait until Ready for data 
+    while (!I2C_SLVSI(obj)); // Wait forever
+//    if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout
+
+    // Check State
+    switch(I2C_SLVSTAT(obj)) {
+      case 0x0: // Slave address plus R/W received 
+                // At least one of the four slave addresses has been matched by hardware.
+                // You can figure out which address by checking Slave address match Index in STAT register.                
+                // I2C Restart occurred
+                return -1; 
+                //break;    
+      case 0x1: // Slave receive. Received data is available (Slave Receiver mode).
+                // Should not get here... 
+                return -2;
+                //break;                
+      case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode).
+                I2C_SLVDAT(obj) = data[count] & 0xFF; // Store the data for transmission
+                obj->i2c->SLVCTL = (1 << 0);          // Continue to send
+                break;      
+      case 0x3: // Reserved.
+      default:
+              // Should not get here... 
+              return -3;
+              //break; 
+    } // switch status
+  } // for all bytes
+     
+  return length; // Transmitted the max number of bytes
+}
+
+
+// Set the four slave addresses. 
+void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
+  obj->i2c->SLVADR0   = (address & 0xFE); // Store address in address 0 register
+  obj->i2c->SLVADR1   = (0x00    & 0xFE); // Store general call write address in address 1 register
+  obj->i2c->SLVADR2   = (0x01);           // Disable address 2 register
+  obj->i2c->SLVADR3   = (0x01);           // Disable address 3 register
+  obj->i2c->SLVQUAL0  = (mask & 0xFE);    // Qualifier mask for address 0 register. Any maskbit that is 1 will always be a match 
+}
+
+#endif
+
+#endif