Mercurial > ecos
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 +
