mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-26 06:53:52 +01:00
Merge pull request #13037 from benpicco/lpc23xx_i2c
cpu/lpc2387: implement periph/i2c
This commit is contained in:
commit
50a5845b15
@ -3,6 +3,7 @@ CPU_MODEL = lpc2388
|
||||
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
FEATURES_PROVIDED += periph_adc
|
||||
FEATURES_PROVIDED += periph_i2c
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_spi
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
|
||||
@ -101,6 +101,33 @@ static const adc_conf_t adc_config[] = {
|
||||
};
|
||||
|
||||
#define ADC_NUMOF (1)
|
||||
|
||||
/**
|
||||
* @name I2C configuration
|
||||
* @{
|
||||
*/
|
||||
static const i2c_conf_t i2c_config[] = {
|
||||
{
|
||||
.dev = I2C0,
|
||||
.speed = I2C_SPEED_NORMAL,
|
||||
.irq_prio = 5,
|
||||
.pinsel_sda = 1,
|
||||
.pinsel_scl = 1,
|
||||
.pinsel_msk_sda = BIT22, /* P0.27 */
|
||||
.pinsel_msk_scl = BIT24, /* P0.28 */
|
||||
},
|
||||
{
|
||||
.dev = I2C1,
|
||||
.speed = I2C_SPEED_NORMAL,
|
||||
.irq_prio = 5,
|
||||
.pinsel_sda = 1,
|
||||
.pinsel_scl = 1,
|
||||
.pinsel_msk_sda = BIT6 | BIT7, /* P0.19 */
|
||||
.pinsel_msk_scl = BIT8 | BIT9, /* P0.20 */
|
||||
},
|
||||
};
|
||||
|
||||
#define I2C_NUMOF (2)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -2,6 +2,7 @@ CPU = lpc2387
|
||||
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
FEATURES_PROVIDED += periph_adc
|
||||
FEATURES_PROVIDED += periph_i2c
|
||||
FEATURES_PROVIDED += periph_pwm
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_spi
|
||||
|
||||
@ -155,6 +155,25 @@ static const adc_conf_t adc_config[] = {
|
||||
#define ADC_NUMOF ARRAY_SIZE(adc_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name I2C configuration
|
||||
* @{
|
||||
*/
|
||||
static const i2c_conf_t i2c_config[] = {
|
||||
{ /* JP3 */
|
||||
.dev = I2C2,
|
||||
.speed = I2C_SPEED_NORMAL,
|
||||
.irq_prio = 5,
|
||||
.pinsel_sda = 0,
|
||||
.pinsel_scl = 0,
|
||||
.pinsel_msk_sda = BIT21, /* P0.10 */
|
||||
.pinsel_msk_scl = BIT23, /* P0.11 */
|
||||
},
|
||||
};
|
||||
|
||||
/* used in arithmetic preprocessor expression, so no ARRAY_SIZE() */
|
||||
#define I2C_NUMOF (1)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -195,7 +195,40 @@ typedef struct {
|
||||
uint32_t pinsel_msk; /**< PINSEL Mask for ADC pin */
|
||||
} adc_conf_t;
|
||||
|
||||
/**
|
||||
* @brief Override I2C clock speed values
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_I2C_SPEED_T
|
||||
typedef enum {
|
||||
I2C_SPEED_LOW = 10000, /**< low speed mode: ~10 kbit/s */
|
||||
I2C_SPEED_NORMAL = 100000, /**< normal mode: ~100 kbit/s */
|
||||
I2C_SPEED_FAST = 400000, /**< fast mode: ~400 kbit/s */
|
||||
} i2c_speed_t;
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @brief I2C device configuration
|
||||
*/
|
||||
typedef struct {
|
||||
lpc23xx_i2c_t *dev; /**< pointer to the I2C device */
|
||||
i2c_speed_t speed; /**< I2C bus speed */
|
||||
uint8_t irq_prio; /**< priority of the I2C IRQ */
|
||||
uint8_t pinsel_sda; /**< PINSEL# of the SDA pin */
|
||||
uint8_t pinsel_scl; /**< PINSEL# of the SCL pin */
|
||||
uint32_t pinsel_msk_sda;/**< SDA PINSEL Mask */
|
||||
uint32_t pinsel_msk_scl;/**< SCL PINSEL Mask */
|
||||
} i2c_conf_t;
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @name Use shared I2C functions
|
||||
* @{
|
||||
*/
|
||||
#define PERIPH_I2C_NEED_READ_REG
|
||||
#define PERIPH_I2C_NEED_WRITE_REG
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
29
cpu/lpc2387/include/vendor/lpc23xx.h
vendored
29
cpu/lpc2387/include/vendor/lpc23xx.h
vendored
@ -771,8 +771,35 @@ typedef struct {
|
||||
#define U3FDR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x28))
|
||||
#define U3TER (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x30))
|
||||
|
||||
/**
|
||||
* @brief Generic I2C register map
|
||||
*/
|
||||
typedef struct {
|
||||
REG32 CONSET; /**< Control Set Register */
|
||||
REG32 STAT; /**< Status Register */
|
||||
REG32 DAT; /**< Data Register */
|
||||
REG32 ADR; /**< Slave Address Register */
|
||||
REG32 SCLH; /**< Duty Cycle High Half Word */
|
||||
REG32 SCLL; /**< Duty Cycle Low Half Word */
|
||||
REG32 CONCLR; /**< Control Clear Register */
|
||||
} lpc23xx_i2c_t;
|
||||
|
||||
/* I2C Control Set Register */
|
||||
#define I2CONSET_AA 0x00000004 /**< Assert acknowledge */
|
||||
#define I2CONSET_SI 0x00000008 /**< Interrupt flag */
|
||||
#define I2CONSET_STO 0x00000010 /**< STOP flag */
|
||||
#define I2CONSET_STA 0x00000020 /**< START flag */
|
||||
#define I2CONSET_I2EN 0x00000040 /**< Interface enable */
|
||||
|
||||
/* I2C Control clear Register */
|
||||
#define I2CONCLR_AAC 0x00000004 /**< clear Assert ACK */
|
||||
#define I2CONCLR_SIC 0x00000008 /**< clear Interrupt */
|
||||
#define I2CONCLR_STAC 0x00000020 /**< clear START flag */
|
||||
#define I2CONCLR_I2ENC 0x00000040 /**< Interface disable */
|
||||
|
||||
/* I2C Interface 0 */
|
||||
#define I2C0_BASE_ADDR 0xE001C000
|
||||
#define I2C0 ((lpc23xx_i2c_t *)I2C0_BASE_ADDR)
|
||||
#define I20CONSET (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x00))
|
||||
#define I20STAT (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x04))
|
||||
#define I20DAT (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x08))
|
||||
@ -783,6 +810,7 @@ typedef struct {
|
||||
|
||||
/* I2C Interface 1 */
|
||||
#define I2C1_BASE_ADDR 0xE005C000
|
||||
#define I2C1 ((lpc23xx_i2c_t *)I2C1_BASE_ADDR)
|
||||
#define I21CONSET (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x00))
|
||||
#define I21STAT (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x04))
|
||||
#define I21DAT (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x08))
|
||||
@ -793,6 +821,7 @@ typedef struct {
|
||||
|
||||
/* I2C Interface 2 */
|
||||
#define I2C2_BASE_ADDR 0xE0080000
|
||||
#define I2C2 ((lpc23xx_i2c_t *)I2C2_BASE_ADDR)
|
||||
#define I22CONSET (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x00))
|
||||
#define I22STAT (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x04))
|
||||
#define I22DAT (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x08))
|
||||
|
||||
484
cpu/lpc2387/periph/i2c.c
Normal file
484
cpu/lpc2387/periph/i2c.c
Normal file
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Beuth Hochschule für Technik Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_lpc2387
|
||||
* @ingroup drivers_periph_i2c
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level I2C driver implementation for lpc23xx
|
||||
*
|
||||
* @author Benjamin Valentin <benpicco@beuth-hochschule.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "board.h"
|
||||
#include "byteorder.h"
|
||||
#include "periph_conf.h"
|
||||
#include "periph/i2c.h"
|
||||
|
||||
#include "sched.h"
|
||||
#include "thread.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#if I2C_NUMOF > 0
|
||||
static void I2C0_IRQHandler(void) __attribute__((interrupt("IRQ")));
|
||||
#endif
|
||||
#if I2C_NUMOF > 1
|
||||
static void I2C1_IRQHandler(void) __attribute__((interrupt("IRQ")));
|
||||
#endif
|
||||
#if I2C_NUMOF > 2
|
||||
static void I2C2_IRQHandler(void) __attribute__((interrupt("IRQ")));
|
||||
#endif
|
||||
|
||||
/**
|
||||
* We only ever need two buffers for read/write reg
|
||||
*/
|
||||
#define TRX_BUFS_MAX (2)
|
||||
static struct i2c_ctx {
|
||||
mutex_t lock;
|
||||
mutex_t tx_done;
|
||||
uint8_t *buf[TRX_BUFS_MAX];
|
||||
uint8_t *buf_end[TRX_BUFS_MAX];
|
||||
uint8_t *cur;
|
||||
uint8_t *end;
|
||||
int res;
|
||||
uint8_t addr[TRX_BUFS_MAX];
|
||||
uint8_t buf_num;
|
||||
uint8_t buf_cur;
|
||||
} ctx[I2C_NUMOF] = {
|
||||
#if I2C_NUMOF > 0
|
||||
{ .lock = MUTEX_INIT, .tx_done = MUTEX_INIT_LOCKED },
|
||||
#endif
|
||||
#if I2C_NUMOF > 1
|
||||
{ .lock = MUTEX_INIT, .tx_done = MUTEX_INIT_LOCKED },
|
||||
#endif
|
||||
#if I2C_NUMOF > 2
|
||||
{ .lock = MUTEX_INIT, .tx_done = MUTEX_INIT_LOCKED },
|
||||
#endif
|
||||
};
|
||||
|
||||
static void poweron(lpc23xx_i2c_t *i2c)
|
||||
{
|
||||
switch ((uint32_t)i2c) {
|
||||
case I2C0_BASE_ADDR:
|
||||
PCONP |= PCI2C0;
|
||||
break;
|
||||
case I2C1_BASE_ADDR:
|
||||
PCONP |= PCI2C1;
|
||||
break;
|
||||
case I2C2_BASE_ADDR:
|
||||
PCONP |= PCI2C2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void poweroff(lpc23xx_i2c_t *i2c)
|
||||
{
|
||||
switch ((uint32_t)i2c) {
|
||||
case I2C0_BASE_ADDR:
|
||||
PCONP &= ~PCI2C0;
|
||||
break;
|
||||
case I2C1_BASE_ADDR:
|
||||
PCONP &= ~PCI2C1;
|
||||
break;
|
||||
case I2C2_BASE_ADDR:
|
||||
PCONP &= ~PCI2C2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int i2c_acquire(i2c_t dev)
|
||||
{
|
||||
assert(dev < I2C_NUMOF);
|
||||
|
||||
mutex_lock(&ctx[dev].lock);
|
||||
poweron(i2c_config[dev].dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2c_release(i2c_t dev)
|
||||
{
|
||||
assert(dev < I2C_NUMOF);
|
||||
|
||||
poweroff(i2c_config[dev].dev);
|
||||
mutex_unlock(&ctx[dev].lock);
|
||||
}
|
||||
|
||||
static void _set_baud(lpc23xx_i2c_t *i2c, uint32_t baud)
|
||||
{
|
||||
uint32_t pclksel, prescale;
|
||||
lpc2387_pclk_scale(CLOCK_CORECLOCK, baud, &pclksel, &prescale);
|
||||
|
||||
switch ((uint32_t)i2c) {
|
||||
case I2C0_BASE_ADDR:
|
||||
PCLKSEL0 &= ~(BIT14 | BIT15);
|
||||
PCLKSEL0 |= pclksel << 14;
|
||||
I20SCLL = prescale / 2;
|
||||
I20SCLH = prescale / 2;
|
||||
break;
|
||||
case I2C1_BASE_ADDR:
|
||||
PCLKSEL1 &= ~(BIT6 | BIT7);
|
||||
PCLKSEL1 |= pclksel << 6;
|
||||
I21SCLL = prescale / 2;
|
||||
I21SCLH = prescale / 2;
|
||||
break;
|
||||
case I2C2_BASE_ADDR:
|
||||
PCLKSEL1 &= ~(BIT20 | BIT21);
|
||||
PCLKSEL1 |= pclksel << 20;
|
||||
I22SCLL = prescale / 2;
|
||||
I22SCLH = prescale / 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned _get_irq(i2c_t dev)
|
||||
{
|
||||
switch ((uint32_t)i2c_config[dev].dev) {
|
||||
case I2C0_BASE_ADDR:
|
||||
return I2C0_INT;
|
||||
case I2C1_BASE_ADDR:
|
||||
return I2C1_INT;
|
||||
case I2C2_BASE_ADDR:
|
||||
return I2C2_INT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _install_irq(i2c_t dev)
|
||||
{
|
||||
switch (dev) {
|
||||
#if I2C_NUMOF > 0
|
||||
case 0:
|
||||
install_irq(_get_irq(dev), I2C0_IRQHandler, i2c_config[dev].irq_prio);
|
||||
break;
|
||||
#endif
|
||||
#if I2C_NUMOF > 1
|
||||
case 1:
|
||||
install_irq(_get_irq(dev), I2C1_IRQHandler, i2c_config[dev].irq_prio);
|
||||
break;
|
||||
#endif
|
||||
#if I2C_NUMOF > 2
|
||||
case 2:
|
||||
install_irq(_get_irq(dev), I2C2_IRQHandler, i2c_config[dev].irq_prio);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_init(i2c_t dev)
|
||||
{
|
||||
assert(dev < I2C_NUMOF);
|
||||
|
||||
const i2c_conf_t *cfg = &i2c_config[dev];
|
||||
lpc23xx_i2c_t *i2c = cfg->dev;
|
||||
|
||||
poweron(i2c);
|
||||
|
||||
/* configure SDA & SCL pins */
|
||||
*(&PINSEL0 + cfg->pinsel_sda) |= cfg->pinsel_msk_sda;
|
||||
*(&PINSEL0 + cfg->pinsel_scl) |= cfg->pinsel_msk_scl;
|
||||
|
||||
/* clear control register */
|
||||
i2c->CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC
|
||||
| I2CONCLR_I2ENC;
|
||||
|
||||
_set_baud(i2c, cfg->speed);
|
||||
|
||||
_install_irq(dev);
|
||||
|
||||
/* enable the interface */
|
||||
i2c->CONSET = I2CONSET_I2EN;
|
||||
|
||||
poweroff(i2c);
|
||||
}
|
||||
|
||||
static void _end_tx(i2c_t dev, unsigned res)
|
||||
{
|
||||
ctx[dev].res = res;
|
||||
mutex_unlock(&ctx[dev].tx_done);
|
||||
}
|
||||
|
||||
static void _next_buffer(i2c_t dev)
|
||||
{
|
||||
/* We only need two buffers max.
|
||||
This can only be called for the first buffer
|
||||
as there is no next buffer for the second buffer */
|
||||
assert(ctx[dev].buf_cur == 0);
|
||||
|
||||
lpc23xx_i2c_t *i2c = i2c_config[dev].dev;
|
||||
|
||||
/* if mode (read/write) changed, send START again */
|
||||
if (ctx[dev].addr[0] != ctx[dev].addr[1]) {
|
||||
i2c->CONSET = I2CONSET_STA;
|
||||
}
|
||||
|
||||
ctx[dev].cur = ctx[dev].buf[1];
|
||||
ctx[dev].end = ctx[dev].buf_end[1];
|
||||
ctx[dev].buf_cur = 1;
|
||||
}
|
||||
|
||||
static void irq_handler(i2c_t dev)
|
||||
{
|
||||
lpc23xx_i2c_t *i2c = i2c_config[dev].dev;
|
||||
|
||||
unsigned stat = i2c->STAT;
|
||||
|
||||
DEBUG("[i2c] STAT: %x\n", stat);
|
||||
|
||||
switch (stat) {
|
||||
case 0x00: /* Bus Error */
|
||||
DEBUG("[i2c] Bus Error\n");
|
||||
_end_tx(dev, -EIO);
|
||||
break;
|
||||
|
||||
case 0x08: /* A Start Condition is issued. */
|
||||
case 0x10: /* A repeated Start Condition is issued */
|
||||
ctx[dev].cur = ctx[dev].buf[ctx[dev].buf_cur];
|
||||
i2c->DAT = ctx[dev].addr[ctx[dev].buf_cur];
|
||||
i2c->CONSET = I2CONSET_AA;
|
||||
i2c->CONCLR = I2CONCLR_STAC;
|
||||
break;
|
||||
|
||||
case 0x20: /* Address NACK (write) */
|
||||
case 0x48: /* Address NACK (read) */
|
||||
/* slave did not ACK address - send STOP */
|
||||
i2c->CONSET = I2CONSET_STO | I2CONSET_AA;
|
||||
_end_tx(dev, -ENXIO);
|
||||
break;
|
||||
|
||||
case 0x18: /* Master Transmit, SLA_R has been sent */
|
||||
i2c->DAT = *ctx[dev].cur++;
|
||||
i2c->CONSET = I2CONSET_AA;
|
||||
break;
|
||||
|
||||
case 0x28: /* Data byte has been transmitted */
|
||||
|
||||
if (ctx[dev].cur == ctx[dev].end) {
|
||||
/* we transmitted all buffers */
|
||||
if (ctx[dev].buf_cur == ctx[dev].buf_num) {
|
||||
i2c->CONSET = I2CONSET_STO | I2CONSET_AA;
|
||||
_end_tx(dev, 0);
|
||||
break;
|
||||
} else {
|
||||
_next_buffer(dev);
|
||||
}
|
||||
}
|
||||
|
||||
i2c->DAT = *ctx[dev].cur++;
|
||||
i2c->CONSET = I2CONSET_AA;
|
||||
break;
|
||||
|
||||
case 0x30: /* Data NACK */
|
||||
i2c->CONSET = I2CONSET_STO | I2CONSET_AA;
|
||||
_end_tx(dev, 0);
|
||||
break;
|
||||
|
||||
case 0x38: /* Arbitration has been lost */
|
||||
i2c->CONSET = I2CONSET_STA | I2CONSET_AA;
|
||||
break;
|
||||
|
||||
case 0x40: /* Master Receive, SLA_R has been sent */
|
||||
|
||||
/* if we only want to read one byte, send NACK already */
|
||||
if (ctx[dev].cur + 1 == ctx[dev].end) {
|
||||
i2c->CONCLR = I2CONCLR_AAC;
|
||||
} else {
|
||||
i2c->CONSET = I2CONSET_AA;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x50: /* Data byte has been received */
|
||||
|
||||
*ctx[dev].cur++ = i2c->DAT;
|
||||
|
||||
if (ctx[dev].cur == ctx[dev].end) {
|
||||
i2c->CONCLR = I2CONCLR_AAC;
|
||||
} else {
|
||||
i2c->CONSET = I2CONSET_AA;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x58: /* Data received, NACK */
|
||||
*ctx[dev].cur = i2c->DAT;
|
||||
|
||||
if (ctx[dev].buf_cur != ctx[dev].buf_num) {
|
||||
i2c->CONSET = I2CONSET_AA;
|
||||
_next_buffer(dev);
|
||||
} else {
|
||||
i2c->CONSET = I2CONSET_AA | I2CONSET_STO;
|
||||
_end_tx(dev, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* clear interrupt flag */
|
||||
i2c->CONCLR = I2CONCLR_SIC;
|
||||
}
|
||||
|
||||
static void _init_buffer(i2c_t dev, uint8_t idx, uint8_t addr,
|
||||
uint8_t *data, size_t len)
|
||||
{
|
||||
ctx[dev].addr[idx] = addr;
|
||||
ctx[dev].buf[idx] = data;
|
||||
ctx[dev].buf_end[idx] = data + len;
|
||||
|
||||
ctx[dev].buf_num = idx;
|
||||
|
||||
ctx[dev].buf_cur = 0;
|
||||
ctx[dev].cur = ctx[dev].buf[0];
|
||||
ctx[dev].end = ctx[dev].buf_end[0];
|
||||
}
|
||||
|
||||
int i2c_read_bytes(i2c_t dev, uint16_t addr,
|
||||
void *data, size_t len, uint8_t flags)
|
||||
{
|
||||
assert(dev < I2C_NUMOF);
|
||||
lpc23xx_i2c_t *i2c = i2c_config[dev].dev;
|
||||
|
||||
/* Check for wrong arguments given */
|
||||
if (data == NULL || len == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TODO: 10 bit addresses */
|
||||
if (flags) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
_init_buffer(dev, 0, 1 | (addr << 1), (void*)data, len);
|
||||
|
||||
/* set Start flag */
|
||||
i2c->CONSET = I2CONSET_STA;
|
||||
|
||||
mutex_lock(&ctx[dev].tx_done);
|
||||
return ctx[dev].res;
|
||||
}
|
||||
|
||||
int i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_t len,
|
||||
uint8_t flags)
|
||||
{
|
||||
assert(dev < I2C_NUMOF);
|
||||
lpc23xx_i2c_t *i2c = i2c_config[dev].dev;
|
||||
|
||||
/* Check for wrong arguments given */
|
||||
if (data == NULL || len == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TODO: 10 bit addresses */
|
||||
if (flags) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
_init_buffer(dev, 0, addr << 1, (void*)data, len);
|
||||
|
||||
/* set Start flag */
|
||||
i2c->CONSET = I2CONSET_STA;
|
||||
|
||||
mutex_lock(&ctx[dev].tx_done);
|
||||
return ctx[dev].res;
|
||||
}
|
||||
|
||||
int i2c_read_regs(i2c_t dev, uint16_t addr, uint16_t reg,
|
||||
void *data, size_t len, uint8_t flags)
|
||||
{
|
||||
assert(dev < I2C_NUMOF);
|
||||
lpc23xx_i2c_t *i2c = i2c_config[dev].dev;
|
||||
|
||||
/* Check for wrong arguments given */
|
||||
if (data == NULL || len == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TODO: 10 bit addresses */
|
||||
if (flags & ~I2C_REG16) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Handle endianness of register if 16 bit */
|
||||
if (flags & I2C_REG16) {
|
||||
reg = htons(reg); /* Make sure register is in big-endian on I2C bus */
|
||||
}
|
||||
|
||||
_init_buffer(dev, 0, addr << 1, (void*)®, (flags & I2C_REG16) ? 2 : 1);
|
||||
_init_buffer(dev, 1, 1 | (addr << 1), (void*)data, len);
|
||||
|
||||
/* set Start flag */
|
||||
i2c->CONSET = I2CONSET_STA;
|
||||
|
||||
mutex_lock(&ctx[dev].tx_done);
|
||||
return ctx[dev].res;
|
||||
}
|
||||
|
||||
int i2c_write_regs(i2c_t dev, uint16_t addr, uint16_t reg,
|
||||
const void *data, size_t len, uint8_t flags)
|
||||
{
|
||||
assert(dev < I2C_NUMOF);
|
||||
lpc23xx_i2c_t *i2c = i2c_config[dev].dev;
|
||||
|
||||
/* Check for wrong arguments given */
|
||||
if (data == NULL || len == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TODO: 10 bit addresses */
|
||||
if (flags & ~I2C_REG16) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Handle endianness of register if 16 bit */
|
||||
if (flags & I2C_REG16) {
|
||||
reg = htons(reg); /* Make sure register is in big-endian on I2C bus */
|
||||
}
|
||||
|
||||
_init_buffer(dev, 0, addr << 1, (void*)®, (flags & I2C_REG16) ? 2 : 1);
|
||||
_init_buffer(dev, 1, addr << 1, (void*)data, len);
|
||||
|
||||
/* set Start flag */
|
||||
i2c->CONSET = I2CONSET_STA;
|
||||
|
||||
mutex_lock(&ctx[dev].tx_done);
|
||||
return ctx[dev].res;
|
||||
}
|
||||
|
||||
#if I2C_NUMOF > 0
|
||||
static void I2C0_IRQHandler(void)
|
||||
{
|
||||
irq_handler(0);
|
||||
VICVectAddr = 0; /* Acknowledge Interrupt */
|
||||
}
|
||||
#endif
|
||||
#if I2C_NUMOF > 1
|
||||
static void I2C1_IRQHandler(void)
|
||||
{
|
||||
irq_handler(1);
|
||||
VICVectAddr = 0; /* Acknowledge Interrupt */
|
||||
}
|
||||
#endif
|
||||
#if I2C_NUMOF > 2
|
||||
static void I2C2_IRQHandler(void)
|
||||
{
|
||||
irq_handler(2);
|
||||
VICVectAddr = 0; /* Acknowledge Interrupt */
|
||||
}
|
||||
#endif
|
||||
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "kernel_defines.h"
|
||||
|
||||
#include "at24mac.h"
|
||||
#include "at24mac_params.h"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user