changeset 2561:55c015cde894

* cdl/hal_arm_lpc2xxx_ea2468.cdl: Added compile platform_i2c.c and CYGPKG_HAL_ARM_LPC24XX_EA2468_TESTS for building I2C test * include/plf_io.h: Exported I2C devices and bus via macro HAL_I2C_EXPORTED_DEVICES, Added I2C related defines, Added functions declarations hal_lpc_eeprom_write() and hal_lpc_eeprom_read() for I2C EEPROM access * src/ea2468_misc.c: Replaced CYGARC_HAL_LPC24XX_SET_PIN_FUN() macro calls with hal_set_pin_function() calls * src/platform_i2c.c: New file adds I2C bus support for I2C bus 0 and adds support for I2C EEPROM * tests/i2c_eeprom: Simple I2C EEPROM read/write test case
author asl
date Mon, 22 Sep 2008 19:20:26 +0000
parents cec45c19fdcc
children 14c67833f954
files packages/hal/arm/lpc24xx/ea2468/current/ChangeLog packages/hal/arm/lpc24xx/ea2468/current/cdl/hal_arm_lpc24xx_ea2468.cdl packages/hal/arm/lpc24xx/ea2468/current/include/plf_io.h packages/hal/arm/lpc24xx/ea2468/current/src/ea2468_misc.c packages/hal/arm/lpc24xx/ea2468/current/src/platform_i2c.c packages/hal/arm/lpc24xx/ea2468/current/tests/i2c_eeprom.c
diffstat 6 files changed, 501 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/packages/hal/arm/lpc24xx/ea2468/current/ChangeLog
+++ b/packages/hal/arm/lpc24xx/ea2468/current/ChangeLog
@@ -1,3 +1,17 @@
+2008-09-18  Uwe Kindler  <uwe_kindler@web.de>
+
+	* cdl/hal_arm_lpc2xxx_ea2468.cdl: Added compile platform_i2c.c and
+	  CYGPKG_HAL_ARM_LPC24XX_EA2468_TESTS for building I2C test
+	* include/plf_io.h: Exported I2C devices and bus via macro
+	  HAL_I2C_EXPORTED_DEVICES, Added I2C related defines, Added
+	  functions declarations  hal_lpc_eeprom_write() and 
+	  hal_lpc_eeprom_read() for I2C EEPROM access
+	* src/ea2468_misc.c: Replaced CYGARC_HAL_LPC24XX_SET_PIN_FUN() macro
+	  calls with hal_set_pin_function() calls
+	* src/platform_i2c.c: New file adds I2C bus support for I2C bus 0 and 
+	  adds support for I2C EEPROM
+	* tests/i2c_eeprom: Simple I2C EEPROM read/write test case
+
 2008-09-11  Uwe Kindler  <uwe_kindler@web.de>
 
 	* cdl/hal_arm_lpc2xxx_ea2468.cdl: Added constraint for
--- a/packages/hal/arm/lpc24xx/ea2468/current/cdl/hal_arm_lpc24xx_ea2468.cdl
+++ b/packages/hal/arm/lpc24xx/ea2468/current/cdl/hal_arm_lpc24xx_ea2468.cdl
@@ -58,7 +58,7 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX_EA246
         The LPC2468 OEM HAL package provides the support needed to run
         eCos on Embedded Artists LPC2468 OEM 16/32 boards."
 
-    compile       ea2468_misc.c
+    compile       ea2468_misc.c platform_i2c.c
 
     requires      { CYGHWR_HAL_ARM_LPC24XX == "LPC2468" }
     requires      { is_active(CYGPKG_DEVS_ETH_PHY) implies
@@ -288,6 +288,7 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX_EA246
 
         }
     }
+    
 
     cdl_component CYGHWR_MEMORY_LAYOUT {
         display "Memory layout"
@@ -316,4 +317,15 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX_EA246
                              "<pkgconf/mlt_arm_lpc24xx_ea2468_rom.h>" }
         }
     }
+    
+   cdl_option CYGPKG_HAL_ARM_LPC24XX_EA2468_TESTS {
+        display "Tests for LPC2468 OEM board HAL"
+        flavor  data
+        no_define
+        calculated { "tests/i2c_eeprom" }
+        description   "
+            This option specifies the set of tests for the LPC2xxx 
+            CAN device driver."
+    }
+
 }
--- a/packages/hal/arm/lpc24xx/ea2468/current/include/plf_io.h
+++ b/packages/hal/arm/lpc24xx/ea2468/current/include/plf_io.h
@@ -53,6 +53,14 @@
 // On-chip device base addresses
 
 
+// ----------------------------------------------------------------------------
+// exported I2C devices on OEM board
+//
+#define HAL_I2C_EXPORTED_DEVICES                      \
+    extern cyg_i2c_device i2c_cat24c256_eeprom;       \
+    extern cyg_i2c_bus    hal_ea2468_i2c0_bus;
+    
+
 //----------------------------------------------------------------------
 // The platform needs this initialization during the
 // hal_hardware_init() function in the varient HAL.
@@ -68,8 +76,47 @@ extern void hal_plf_hardware_init(void);
 #ifdef CYGPKG_DEVS_CAN_LPC2XXX
 externC void hal_lpc_can_init(cyg_uint8 can_chan_no);            
 #define HAL_LPC2XXX_INIT_CAN(_can_chan_no_) hal_lpc_can_init(_can_chan_no_)
-#endif // CYGPKG_DEVS_CAN_LPC2XXX   
+#endif // CYGPKG_DEVS_CAN_LPC2XXX 
+
+
+// ----------------------------------------------------------------------------
+// I2C support. The LPC2468 OEM board supports up to 3 I2C busses. Only the
+// I2C bus 0 is used on the board. The other I2C busses are available via
+// the expansion connector. If only the first bus is used, the I2C driver
+// will be optimized for a single I2C bus
+#ifdef CYGPKG_DEVS_I2C_ARM_LPC2XXX
+# define HAL_LPC2XXX_I2C_SINGLETON_BASE     CYGARC_HAL_LPC24XX_REG_I2C0_BASE
+# define HAL_LPC2XXX_I2C_SINGLETON_ISRVEC   CYGNUM_HAL_INTERRUPT_I2C
+# define HAL_LPC2XXX_I2C_SINGLETON_CLK      CYGNUM_HAL_ARM_LPC24XX_I2C0_CLK
+# define HAL_LPC2XXX_I2C_SINGLETON_ISRPRI   CYGNUM_HAL_ARM_LPC24XX_I2C0_INT_PRIO
+# define HAL_LPC2XXX_I2C_SINGLETON_BUS_FREQ CYGNUM_HAL_ARM_LPC24XX_I2C0_BUS_FREQ
+
 
+//-----------------------------------------------------------------------------
+// Write data to eeprom (page write)
+// If the call is blocking (blocking == true) then the function will poll
+// the device if it is busy writing. If it is non blocking then the function
+// immediately return 0 if the device is busy
+// Function returns number of bytes written to device
+//-----------------------------------------------------------------------------
+externC cyg_uint32 hal_lpc_eeprom_write(cyg_uint16 addr,
+                                        cyg_uint8 *pdata,
+                                        cyg_uint16 size,
+                                        cyg_bool   blocking);
+
+
+//-----------------------------------------------------------------------------
+// Read data from eeprom (selcetive, sequencial read)
+// If the call is blocking (blocking == true) then the function will poll
+// the device if it is busy writing. If it is non blocking then the function
+// immediately return 0 if the device is busy
+// Function returns number of bytes read from device
+//-----------------------------------------------------------------------------
+externC cyg_uint32 hal_lpc_eeprom_read(cyg_uint16 addr,
+                                       cyg_uint8 *pdata,
+                                       cyg_uint16 size,
+                                       cyg_bool   blocking);
+#endif // CYGPKG_DEVS_I2C_ARM_LPC2XXX  
 #endif  //__ASSEMBLER__ 
 
 //-----------------------------------------------------------------------------
--- a/packages/hal/arm/lpc24xx/ea2468/current/src/ea2468_misc.c
+++ b/packages/hal/arm/lpc24xx/ea2468/current/src/ea2468_misc.c
@@ -269,9 +269,7 @@ void hal_mem_init(void)
     //
     HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMC_CTRL, 
                      CYGARC_HAL_LPC24XX_REG_EMC_CTRL_EN);
-    HAL_READ_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCONP, regval);
-    HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCONP,
-                     regval | CYGARC_HAL_LPC24XX_REG_PCONP_EMC);  
+    hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_EMC, 1);
                     
     //
     // Setup pin functions
@@ -438,26 +436,20 @@ void hal_lpc_can_init(cyg_uint8 can_chan
 {
     CYG_ASSERT(can_chan_no < 2, "CAN channel number out of bounds");
     
-    cyg_uint32 pinsel0_val;
-    cyg_uint32 pconp_val;
-    HAL_READ_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL0, pinsel0_val);
-    HAL_READ_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCONP, pconp_val);
     switch (can_chan_no)
     {
         case 0:
-             CYGARC_HAL_LPC24XX_SET_PIN_FUN(pinsel0_val, 0, 1);
-             CYGARC_HAL_LPC24XX_SET_PIN_FUN(pinsel0_val, 1, 1);
-             pconp_val |= CYGARC_HAL_LPC24XX_REG_PCONP_CAN1;
+             hal_set_pin_function(0, 0, 1); // RD1
+             hal_set_pin_function(0, 1, 1); // TD1
+             hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_CAN1, 1);
              break;
         
         case 1:
-             CYGARC_HAL_LPC24XX_SET_PIN_FUN(pinsel0_val, 4, 2);
-             CYGARC_HAL_LPC24XX_SET_PIN_FUN(pinsel0_val, 5, 2); 
-             pconp_val |= CYGARC_HAL_LPC24XX_REG_PCONP_CAN2;
+             hal_set_pin_function(0, 4, 2); // RD2
+             hal_set_pin_function(0, 5, 2); // TD2
+             hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_CAN2, 1);
              break;
     }
-    HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL0, pinsel0_val);
-    HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCONP, pconp_val);
 }
 #endif // #ifdef CYGPKG_DEVS_CAN_LPC2XXX
 
new file mode 100644
--- /dev/null
+++ b/packages/hal/arm/lpc24xx/ea2468/current/src/platform_i2c.c
@@ -0,0 +1,241 @@
+//==========================================================================
+//
+//      platform_i2c.c
+//
+//      Optional I2C support for LPC2468
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Uwe Kindler <uwe_kindler@web.de>
+// Contributors: 
+// Date:         2008-09-11
+// Purpose:      
+// Description:  
+//              
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+//=============================================================================
+//                               INCLUDES
+//=============================================================================
+#include <pkgconf/system.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/io/i2c.h>
+#include <cyg/io/i2c_lpc2xxx.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/hal/hal_endian.h>
+
+
+#ifdef CYGHWR_HAL_ARM_LPC24XX_I2C0_SUPP
+//=============================================================================
+// Setup I2C bus 0
+//=============================================================================
+static void ea2468_i2c0_init(struct cyg_i2c_bus* bus)
+{  
+    //
+    // The LPC24xx variant sets up the I2C0 clock and powers up the I2C0
+    // on-chip peripheral. We only need to setup the pins here and 
+    // leave the I2C driver to take care of the rest.
+    //
+    hal_set_pin_function(0, 27, 1); // SDA0
+    hal_set_pin_function(0, 28, 1); // SCL0
+    cyg_lpc2xxx_i2c_init(bus);
+}
+
+
+//-----------------------------------------------------------------------------
+// I2C bus 0
+// 
+CYG_LPC2XXX_I2C_BUS(hal_ea2468_i2c0_bus,
+                    &ea2468_i2c0_init,
+                    CYGARC_HAL_LPC24XX_REG_I2C0_BASE,
+                    CYGNUM_HAL_INTERRUPT_I2C,
+                    CYGNUM_HAL_ARM_LPC24XX_I2C0_INT_PRIO,
+                    CYGNUM_HAL_ARM_LPC24XX_I2C0_CLK,
+                    CYGNUM_HAL_ARM_LPC24XX_I2C0_BUS_FREQ);
+                   
+
+//-----------------------------------------------------------------------------
+// 256-Kb I2C CMOS Serial EEPROM
+//      
+CYG_I2C_DEVICE(i2c_cat24c256_eeprom, 
+               &hal_ea2468_i2c0_bus, 
+               0x50, 
+               0, 
+               CYG_I2C_DEFAULT_DELAY);
+                 
+               
+//===========================================================================
+// Check if device is busy - Acknowledge polling can be used to determine
+// if the CAT24C256 is busy writing or is ready to accept commands.
+// Polling is implemented by interrogating the device with a Selective Read
+// command (see READ OPERATIONS). The CAT24C256 will not acknowledge the
+// Slave address, as long as internal Write is in progress.
+//===========================================================================
+static bool cat24c256_is_busy(void)
+{
+    cyg_uint16 addr = 0;
+    cyg_uint32 result;
+
+    cyg_i2c_transaction_begin(&i2c_cat24c256_eeprom);
+    result = cyg_i2c_transaction_tx(&i2c_cat24c256_eeprom,
+                                    true, (cyg_uint8*)&addr, 2, true);
+    cyg_i2c_transaction_end(&i2c_cat24c256_eeprom);
+
+    return (result != 2);
+}
+ 
+               
+//===========================================================================
+// Write up to 64 bytes of data - one single write cycle
+//===========================================================================
+static cyg_uint32 cat24c256_do_write_cyle(cyg_uint16 addr,
+                                          cyg_uint8 *pdata,
+                                          cyg_uint8  size)
+{
+    cyg_uint32 result;
+
+    cyg_i2c_transaction_begin(&i2c_cat24c256_eeprom);
+    addr = CYG_CPU_TO_BE16(addr);
+    result = cyg_i2c_transaction_tx(&i2c_cat24c256_eeprom,
+                                    true, (cyg_uint8*)&addr, 2, false);
+    if (result)
+    {
+        result = cyg_i2c_transaction_tx(&i2c_cat24c256_eeprom,
+                                        false, pdata, size, true);
+    }
+    cyg_i2c_transaction_end(&i2c_cat24c256_eeprom);
+
+    return result;
+}
+
+
+//===========================================================================
+// Write data to eeprom (page write)
+// If the call is blocking (blocking == true) then the function will poll
+// the device if it is busy writing. If it is non blocking then the function
+// immediately return 0 if the device is busy
+//===========================================================================
+cyg_uint32 hal_lpc_eeprom_write(cyg_uint16 addr,
+                                cyg_uint8 *pdata,
+                                cyg_uint16 size,
+                                cyg_bool   blocking)
+{
+    cyg_uint32 result;
+    cyg_uint16 wsize;
+    cyg_uint16 datasize = size;
+    
+    CYG_ASSERT(addr < 0x8000, "Address out of range");
+    CYG_ASSERT(pdata, "Invalid data pointer");
+    CYG_ASSERT((size <= 0x8000) && (size > 0), "Invalid data size");
+    CYG_ASSERT((addr + size) < 0x8000,
+               "Attempt to write data beyond end of memory.");
+
+   
+    do
+    { 
+        if (cat24c256_is_busy())
+        {
+            if (blocking)
+            {
+                while (cat24c256_is_busy()) {};
+            }
+            else
+            {
+                return 0;
+            }
+        } // if (cat24c256_is_busy())
+        wsize = (datasize > 64) ? 64 : datasize;
+        result = cat24c256_do_write_cyle(addr, pdata, wsize);
+        datasize  -= result;
+        addr      += wsize;
+        pdata     += wsize;
+    } while (datasize && (result == wsize));
+
+    return size - datasize;
+}
+
+
+//===========================================================================
+// Read data from eeprom (selective, sequential read)
+// If the call is blocking (blocking == true) then the function will poll
+// the device if it is busy writing. If it is non blocking then the function
+// immediately return 0 if the device is busy
+//===========================================================================
+cyg_uint32 hal_lpc_eeprom_read(cyg_uint16 addr,
+                               cyg_uint8 *pdata,
+                               cyg_uint16 size,
+                               cyg_bool   blocking)
+{
+    cyg_uint32 result;
+
+    CYG_ASSERT(addr < 0x8000, "Address out of range");
+    CYG_ASSERT(pdata, "Invalid data pointer");
+    CYG_ASSERT((size <= 64) && (size > 0), "Invalid data size");
+    CYG_ASSERT((addr + size) < 0x8000,
+               "Attempt to read data beyond end of memory.");
+
+    if (cat24c256_is_busy())
+    {
+        if (blocking)
+        {
+            while (cat24c256_is_busy());
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    cyg_i2c_transaction_begin(&i2c_cat24c256_eeprom);
+    addr = CYG_CPU_TO_BE16(addr);
+    result = cyg_i2c_transaction_tx(&i2c_cat24c256_eeprom,
+                                    true, (cyg_uint8*)&addr, 2, false);
+    if (result)
+    {
+        result = cyg_i2c_transaction_rx(&i2c_cat24c256_eeprom,
+                                        true, pdata, size, true, true);
+    }
+    cyg_i2c_transaction_end(&i2c_cat24c256_eeprom);
+
+    return result;
+}
+#endif // #ifdef CYGHWR_HAL_ARM_LPC24XX_I2C0_SUPP               
+
+//-----------------------------------------------------------------------------
+// EOF platform_i2c.c
+
new file mode 100644
--- /dev/null
+++ b/packages/hal/arm/lpc24xx/ea2468/current/tests/i2c_eeprom.c
@@ -0,0 +1,178 @@
+//==========================================================================
+//
+//        ea2468_i2c_test.c
+//
+//        Simple I2C test of I2C eeprom on LPC2468 OEM board
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:
+// Date:          2008-09-16
+// Description:   Simple I2C read/write test of I2C eeprom
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                                INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h>         // test macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_diag.h>
+
+// Package requirements
+#if defined(CYGHWR_HAL_ARM_LPC24XX_I2C0_SUPP) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/i2c.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+
+//===========================================================================
+//                               DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+    cyg_thread   obj;
+    long         stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+    cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+//                              LOCAL DATA
+//===========================================================================
+#define EEPROM_SIZE 0x8000
+cyg_thread_entry_t i2c0_thread;
+thread_data_t      i2c0_thread_data;
+static cyg_uint8   write_buf[EEPROM_SIZE];
+static cyg_uint8   read_buf[EEPROM_SIZE];
+
+//===========================================================================
+//                             I2C THREAD
+//===========================================================================
+void i2c0_thread(cyg_addrword_t data)
+{
+    cyg_uint16 i;
+    cyg_uint32 result;
+
+    diag_printf("I2C EEPROM read/write test at %d bit/s\n",
+    		    CYGNUM_HAL_ARM_LPC24XX_I2C0_BUS_FREQ);
+    diag_printf("Initialising write buffer\n");
+    for (i = 0; i < EEPROM_SIZE; ++i)
+    {
+        write_buf[i] = (i & 0xFF);
+    }
+
+    diag_printf("Writing 32768 bytes to I2C EEPROM...\n");
+    result = hal_lpc_eeprom_write(0, write_buf, EEPROM_SIZE, true);
+    if (result != (EEPROM_SIZE))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing to EEPROM");
+    }
+
+    diag_printf("Reading 32768 bytes from I2C EEPROM...\n");
+    result = hal_lpc_eeprom_read(0, read_buf, EEPROM_SIZE, true);
+    if (result != EEPROM_SIZE)
+    {
+        CYG_TEST_FAIL_FINISH("Error reading from EEPROM");
+    }
+
+    for (i = 0; i < EEPROM_SIZE; ++i)
+    {
+        if (write_buf[i] != read_buf[i])
+        {
+            diag_printf("Buffers don't match - write_buf[%d]=0x%02X, "
+                        "read_buf[%d]=0x%02X\n",
+                         i, write_buf[i], i, read_buf[i]);
+            CYG_TEST_FAIL_FINISH("Buffers don't match");
+        }
+    }
+
+    CYG_TEST_PASS_FINISH("I2C EEPROM read/write test OK");
+}
+
+
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+
+    //
+    // create the threads that access the CAN device driver
+    //
+    cyg_thread_create(4, i2c0_thread,
+                      (cyg_addrword_t) 0,
+                      "i2c0_thread",
+                      (void *) i2c0_thread_data.stack,
+                      1024 * sizeof(long),
+                      &i2c0_thread_data.hdl,
+                      &i2c0_thread_data.obj);
+
+    cyg_thread_resume(i2c0_thread_data.hdl);
+
+    cyg_scheduler_start();
+}
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs LPC2xxx I2C support and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF can_tx.c
+
+//---------------------------------------------------------------------------
+// eof i2c_test.c
+