starting to fix I2C for lpc

This commit is contained in:
Antoine Drouin
2010-09-03 15:07:42 +00:00
parent f10ce38ced
commit 8bbe76f6d4
12 changed files with 59 additions and 380 deletions
+2 -1
View File
@@ -203,7 +203,8 @@
</target>
<subsystem name="radio_control" type="ppm"/>
<subsystem name="actuators" type="mkk"/>
<subsystem name="imu" type="b2_v1.0"/>
<subsystem name="imu" type="b2_v1.1"/>
<!-- <subsystem name="imu" type="b2_v1.0"/> -->
<subsystem name="gps" type="ublox"/>
<subsystem name="ahrs" type="cmpl"/>
<subsystem name="ins" type="hff"/>
+2 -1
View File
@@ -182,7 +182,8 @@
<subsystem name="actuators" type="mkk"/>
</target>
<subsystem name="imu" type="b2_v1.1"/>
<!-- <subsystem name="imu" type="b2_v1.1"/> -->
<subsystem name="imu" type="aspirin"/>
<subsystem name="gps" type="ublox"/>
<subsystem name="ahrs" type="cmpl"/>
</firmware>
@@ -31,9 +31,8 @@ ap.srcs += $(SRC_BOOZ)/actuators/booz_actuators_mkk.c
ap.srcs += i2c.c $(SRC_ARCH)/i2c_hw.c
ifeq ($(ARCHI), arm7)
ap.CFLAGS += -DACTUATORS_MKK_DEVICE=i2c0
ap.CFLAGS += -DUSE_I2C0 -DI2C0_SCLL=150 -DI2C0_SCLH=150 -DI2C0_VIC_SLOT=10
ap.CFLAGS += -DI2C0_STOP_HANDLER=ActuatorsMkkI2cHandler
ap.CFLAGS += -DI2C0_STOP_HANDLER_HEADER=\"actuators/booz_actuators_mkk.h\"
else ifeq ($(ARCHI), stm32)
ap.CFLAGS += -DACTUATORS_MKK_DEVICE=i2c1
ap.CFLAGS += -DUSE_I2C1
+28 -116
View File
@@ -24,12 +24,9 @@
#include "i2c.h"
#include "led.h"
#include "std.h"
#include "interrupt_hw.h"
#include BOARD_CONFIG
///////////////////
@@ -206,13 +203,27 @@ static inline void I2cAutomaton(int32_t state, struct i2c_periph* p) {
#define I2C0_VIC_SLOT 9
#endif
void i2c0_ISR(void) __attribute__((naked));
void i2c0_ISR(void) {
ISR_ENTRY();
uint32_t state = I2C0STAT;
I2cAutomaton(state,&i2c0);
I2cClearIT(i2c0.reg_addr);
VICVectAddr = 0x00000000; // clear this interrupt from the VIC
ISR_EXIT(); // recover registers and return
}
/* SDA0 on P0.3 */
/* SCL0 on P0.2 */
void i2c0_hw_init ( void ) {
i2c0.reg_addr = I2C0;
/* set P0.2 and P0.3 to I2C0 */
PINSEL0 |= 1 << 4 | 1 << 6;
/* clear all flags */
@@ -230,21 +241,6 @@ void i2c0_hw_init ( void ) {
_VIC_ADDR(I2C0_VIC_SLOT) = (uint32_t)i2c0_ISR; // address of the ISR
}
#define I2C_DATA_REG I2C0DAT
#define I2C_STATUS_REG I2C0STAT
void i2c0_ISR(void)
{
ISR_ENTRY();
uint32_t state = I2C_STATUS_REG;
I2c0Automaton(state);
I2c0ClearIT();
VICVectAddr = 0x00000000; // clear this interrupt from the VIC
ISR_EXIT(); // recover registers and return
}
#endif /* USE_I2C0 */
@@ -283,16 +279,25 @@ void i2c0_ISR(void)
#endif
#endif
#define I2C1_DATA_REG I2C1DAT
#define I2C1_STATUS_REG I2C1STAT
void i2c1_ISR(void) __attribute__((naked));
void i2c1_ISR(void) {
ISR_ENTRY();
uint32_t state = I2C1STAT;
I2cAutomaton(state,&i2c1);
I2cClearIT(i2c1.reg_addr);
VICVectAddr = 0x00000000; // clear this interrupt from the VIC
ISR_EXIT(); // recover registers and return
}
/* SDA1 on P0.14 */
/* SCL1 on P0.11 */
void i2c1_hw_init ( void ) {
i2c1.reg_addr = I2C1;
/* set P0.11 and P0.14 to I2C1 */
PINSEL0 |= 3 << 22 | 3 << 28;
/* clear all flags */
@@ -310,100 +315,8 @@ void i2c1_hw_init ( void ) {
_VIC_ADDR(I2C1_VIC_SLOT) = (uint32_t)i2c1_ISR; // address of the ISR
}
void i2c1_ISR(void)
{
ISR_ENTRY();
uint32_t state = I2C1_STATUS_REG;
I2c1Automaton(state);
I2c1ClearIT();
VICVectAddr = 0x00000000; // clear this interrupt from the VIC
ISR_EXIT(); // recover registers and return
}
#endif /* USE_I2C1 */
#ifdef USE_I2C2
/* default clock speed 37.5KHz with our 15MHz PCLK
I2C0_CLOCK = PCLK / (I2C0_SCLL + I2C0_SCLH) */
#ifndef I2C0_SCLL
#define I2C0_SCLL 200
#endif
#ifndef I2C0_SCLH
#define I2C0_SCLH 200
#endif
/* adjust for other PCLKs */
#if (PCLK == 15000000)
#define I2C0_SCLL_D I2C0_SCLL
#define I2C0_SCLH_D I2C0_SCLH
#else
#if (PCLK == 30000000)
#define I2C0_SCLL_D (2*I2C0_SCLL)
#define I2C0_SCLH_D (2*I2C0_SCLH)
#else
#if (PCLK == 60000000)
#define I2C0_SCLL_D (4*I2C0_SCLL)
#define I2C0_SCLH_D (4*I2C0_SCLH)
#else
#error unknown PCLK frequency
#endif
#endif
#endif
#ifndef I2C0_VIC_SLOT
#define I2C0_VIC_SLOT 9
#endif
void i2c0_ISR(void) __attribute__((naked));
/* SDA0 on P0.3 */
/* SCL0 on P0.2 */
void i2c2_hw_init ( void ) {
i2c2.reg_addr = I2C0;
/* set P0.2 and P0.3 to I2C0 */
PINSEL0 |= 1 << 4 | 1 << 6;
/* clear all flags */
I2C0CONCLR = _BV(AAC) | _BV(SIC) | _BV(STAC) | _BV(I2ENC);
/* enable I2C */
I2C0CONSET = _BV(I2EN);
/* set bitrate */
I2C0SCLL = I2C0_SCLL_D;
I2C0SCLH = I2C0_SCLH_D;
// initialize the interrupt vector
VICIntSelect &= ~VIC_BIT(VIC_I2C0); // I2C0 selected as IRQ
VICIntEnable = VIC_BIT(VIC_I2C0); // I2C0 interrupt enabled
_VIC_CNTL(I2C0_VIC_SLOT) = VIC_ENABLE | VIC_I2C0;
_VIC_ADDR(I2C0_VIC_SLOT) = (uint32_t)i2c0_ISR; // address of the ISR
}
#define I2C_STATUS_REG I2C0STAT
void i2c0_ISR(void)
{
ISR_ENTRY();
uint32_t state = I2C_STATUS_REG;
I2cAutomaton(state,&i2c2);
I2cClearIT(i2c2.reg_addr);
VICVectAddr = 0x00000000; // clear this interrupt from the VIC
ISR_EXIT(); // recover registers and return
}
bool_t i2c_submit(struct i2c_periph* p, struct i2c_transaction* t) {
@@ -428,6 +341,5 @@ bool_t i2c_submit(struct i2c_periph* p, struct i2c_transaction* t) {
return TRUE;
}
#endif /* USE_I2C2 */
+1 -173
View File
@@ -16,191 +16,19 @@
#define I2C_MR_DATA_NACK 0x58
#define I2C_IDLE 0
#define I2C_BUSY 1
#ifdef USE_I2C0
#ifdef I2C0_STOP_HANDLER
#include I2C0_STOP_HANDLER_HEADER
#define I2c0StopHandler() I2C0_STOP_HANDLER()
#else
#define I2c0StopHandler() {}
#endif /* I2C0_STOP_HANDLER */
extern void i2c0_hw_init(void);
#define I2c0SendAck() { I2C0CONSET = _BV(AA); }
#define I2c0Finished() { \
if (i2c0_finished) *i2c0_finished = TRUE; \
i2c0_status = I2C_IDLE; \
I2c0StopHandler(); \
}
#define I2c0SendStop() { \
I2C0CONSET = _BV(STO); \
I2c0Finished(); \
}
#define I2c0SendStart() { I2C0CONSET = _BV(STA); }
#define I2c0SendByte(b) { I2C_DATA_REG = b; }
#define I2c0Receive(_ack) { \
if (_ack) I2C0CONSET = _BV(AA); \
else I2C0CONCLR = _BV(AAC); \
}
#define I2c0ClearStart() { I2C0CONCLR = _BV(STAC); }
#define I2c0ClearIT() { I2C0CONCLR = _BV(SIC); }
#define I2c0Automaton(state) { \
switch (state) { \
case I2C_START: \
case I2C_RESTART: \
I2c0SendByte(i2c0_slave_addr); \
I2c0ClearStart(); \
i2c0_index = 0; \
break; \
case I2C_MR_DATA_ACK: \
if (i2c0_index < i2c0_len_r) { \
i2c0_buf[i2c0_index] = I2C_DATA_REG; \
i2c0_index++; \
I2c0Receive(i2c0_index < i2c0_len_r - 1); \
} \
else { \
/* error , we should have got NACK */ \
I2c0SendStop(); \
} \
break; \
case I2C_MR_SLA_ACK: /* At least one char */ \
/* Wait and reply with ACK or NACK */ \
I2c0Receive(i2c0_index < i2c0_len_r - 1); \
break; \
case I2C_MR_SLA_NACK: \
case I2C_MT_SLA_NACK: \
I2c0SendStart(); \
break; \
case I2C_MT_SLA_ACK: \
case I2C_MT_DATA_ACK: \
if (i2c0_index < i2c0_len_w) { \
I2c0SendByte(i2c0_buf[i2c0_index]); \
i2c0_index++; \
} else { \
if (i2c0_trx) { \
i2c0_trx = 0; \
i2c0_index = 0; \
i2c0_slave_addr |= 1; \
I2c0SendStart(); \
} else { \
if (i2c0_stop_after_transmit) { \
I2c0SendStop(); \
} else { \
I2c0Finished(); \
} \
} \
} \
break; \
case I2C_MR_DATA_NACK: \
if (i2c0_index < i2c0_len_r) { \
i2c0_buf[i2c0_index] = I2C_DATA_REG; \
} \
I2c0SendStop(); \
break; \
default: \
I2c0SendStop(); \
/* FIXME log error */ \
} \
} \
#endif /* USE_I2C0 */
#ifdef USE_I2C1
extern void i2c1_hw_init(void);
#define I2c1StopHandler() {}
#define I2c1SendAck() { I2C1CONSET = _BV(AA); }
#define I2c1SendStop() { \
I2C1CONSET = _BV(STO); \
if (i2c1_finished) *i2c1_finished = TRUE; \
i2c1_status = I2C_IDLE; \
I2c1StopHandler(); \
}
#define I2c1SendStart() { I2C1CONSET = _BV(STA); }
#define I2c1SendByte(b) { I2C1_DATA_REG = b; }
#define I2c1Receive(_ack) { \
if (_ack) I2C1CONSET = _BV(AA); \
else I2C1CONCLR = _BV(AAC); \
}
#define I2c1ClearStart() { I2C1CONCLR = _BV(STAC); }
#define I2c1ClearIT() { I2C1CONCLR = _BV(SIC); }
#define I2c1Automaton(state) { \
switch (state) { \
case I2C_START: \
case I2C_RESTART: \
I2c1SendByte(i2c1_slave_addr); \
I2c1ClearStart(); \
i2c1_index = 0; \
break; \
case I2C_MR_DATA_ACK: \
if (i2c1_index < i2c1_len_r) { \
i2c1_buf[i2c1_index] = I2C1_DATA_REG; \
i2c1_index++; \
I2c1Receive(i2c1_index < i2c1_len_r - 1); \
} \
else { \
/* error , we should have got NACK */ \
I2c1SendStop(); \
} \
break; \
case I2C_MR_SLA_ACK: /* At least one char */ \
/* Wait and reply with ACK or NACK */ \
I2c1Receive(i2c1_index < i2c1_len_r - 1); \
break; \
case I2C_MR_SLA_NACK: \
case I2C_MT_SLA_NACK: \
I2c1SendStart(); \
break; \
case I2C_MT_SLA_ACK: \
case I2C_MT_DATA_ACK: \
if (i2c1_index < i2c1_len_w) { \
I2c1SendByte(i2c1_buf[i2c1_index]); \
i2c1_index++; \
} else { \
if (i2c1_trx) { \
i2c1_trx = 0; \
i2c1_index = 0; \
i2c1_slave_addr |= 1; \
I2c1SendStart(); \
} else { \
I2c1SendStop(); \
} \
} \
break; \
case I2C_MR_DATA_NACK: \
if (i2c1_index < i2c1_len_r) { \
i2c1_buf[i2c1_index] = I2C1_DATA_REG; \
} \
I2c1SendStop(); \
break; \
default: \
I2c1SendStop(); \
/* LED_ON(2); FIXME log error */ \
} \
} \
#endif /* USE_I2C1 */
#ifdef USE_I2C2
extern void i2c2_hw_init(void);
#endif
#endif /* I2C_HW_H */
@@ -239,7 +239,8 @@ void exti15_10_irq_handler(void) {
imu_aspirin.i2c_trans_gyro.slave_addr = ITG3200_ADDR;
imu_aspirin.i2c_trans_gyro.len_w = 1;
imu_aspirin.i2c_trans_gyro.len_r = 6;
if (!i2c_submit(&i2c2,&imu_aspirin.i2c_trans_gyro)) while(1);
// if (!i2c_submit(&i2c2,&imu_aspirin.i2c_trans_gyro)) while(1);
i2c_submit(&i2c2,&imu_aspirin.i2c_trans_gyro);
imu_aspirin.status = AspirinStatusReadingGyro;
}
+14
View File
@@ -90,6 +90,20 @@ static void configure_mag(void) {
}
static void send_i2c_msg_with_retry(struct i2c_transaction* t) {
uint8_t max_retry = 8;
uint8_t nb_retry = 0;
do {
i2c_submit(&i2c2,&t);
while (t.status == I2CTransPending || t.status == I2CTransRunning);
if (t.status == I2CTransFailed)
nb_retry++;
}
while (t.status != I2CTransSuccess || nb_retry < max_retry);
}
static void configure_accel(void) {
/* set data rate to 800Hz */
+1 -1
View File
@@ -6,7 +6,7 @@ uint8_t ami601_foo3;
uint16_t ami601_values[AMI601_NB_CHAN];
volatile uint8_t ami601_status;
volatile bool_t ami601_i2c_done;
struct i2c_transaction ami601_i2c_trans;
volatile uint32_t ami601_nb_err;
void ami601_init( void ) {
+1 -1
View File
@@ -22,7 +22,7 @@ extern uint8_t ami601_foo3;
#define AMI601_READING_MEASURE 3
#define AMI601_DATA_AVAILABLE 4
extern volatile uint8_t ami601_status;
extern volatile bool_t ami601_i2c_done;
extern struct i2c_transaction ami601_i2c_trans;
extern volatile uint32_t ami601_nb_err;
#define AMI601_SLAVE_ADDR 0x60
+1 -1
View File
@@ -86,7 +86,7 @@ static inline void main_periodic_task( void ) {
&i2c2_errors.last_unexpected_event);
});
#endif
booz_imu_periodic();
if (cpu_time_sec > 1) booz_imu_periodic();
RunOnceEvery(10, { LED_PERIODIC();});
}
+3 -62
View File
@@ -1,74 +1,17 @@
#include <stdio.h> /* For NULL */
#include "i2c.h"
#define I2C_RECEIVE 1
#ifdef USE_I2C0
volatile uint8_t i2c0_status;
volatile uint8_t i2c0_buf[I2C0_BUF_LEN];
volatile uint16_t i2c0_len_r;
volatile uint8_t i2c0_len_w;
volatile uint8_t i2c0_index;
volatile uint8_t i2c0_slave_addr;
volatile bool_t i2c0_stop_after_transmit;
volatile uint8_t i2c0_trx;
volatile bool_t* i2c0_finished;
struct i2c_periph i2c0;
void i2c0_init(void) {
i2c0_status = I2C_IDLE;
i2c_init(&i2c0);
i2c0_hw_init();
i2c0_finished = NULL;
}
void i2c0_receive(uint8_t slave_addr, uint16_t len, volatile bool_t* finished) {
i2c0_trx = 0;
i2c0_len_r = len;
i2c0_slave_addr = slave_addr | I2C_RECEIVE;
i2c0_finished = finished;
i2c0_status = I2C_BUSY;
i2c0_stop_after_transmit = TRUE; /** Default "historic" behaviour */
I2c0SendStart();
}
static inline void i2c0_init_transmit(uint8_t slave_addr, uint8_t len, volatile bool_t* finished) {
i2c0_trx = 0;
i2c0_len_w = len;
i2c0_slave_addr = slave_addr & ~I2C_RECEIVE;
i2c0_finished = finished;
i2c0_status = I2C_BUSY;
}
void i2c0_transmit(uint8_t slave_addr, uint8_t len, volatile bool_t* finished) {
i2c0_trx = 0;
i2c0_init_transmit(slave_addr, len, finished);
i2c0_stop_after_transmit = TRUE; /** Default "historic" behaviour */
I2c0SendStart();
}
void i2c0_transmit_no_stop(uint8_t slave_addr, uint8_t len, volatile bool_t* finished) {
i2c0_trx = 0;
i2c0_init_transmit(slave_addr, len, finished);
i2c0_stop_after_transmit = FALSE; /** Default "historic" behaviour */
I2c0SendStart();
}
void i2c0_transceive(uint8_t slave_addr, uint8_t len_w, uint16_t len_r, volatile bool_t* finished) {
i2c0_trx = 1;
i2c0_len_w = len_w;
i2c0_len_r = len_r;
i2c0_slave_addr = slave_addr & ~I2C_RECEIVE;
i2c0_finished = finished;
i2c0_status = I2C_BUSY;
I2c0SendStart();
}
#endif /* USE_I2C0 */
#ifdef USE_I2C1
struct i2c_periph i2c1;
@@ -83,8 +26,6 @@ void i2c1_init(void) {
#ifdef USE_I2C2
#include "booz/booz2_debug.h"
struct i2c_periph i2c2;
void i2c2_init(void) {
+3 -21
View File
@@ -102,31 +102,13 @@ struct i2c_errors {
#ifdef USE_I2C0
extern struct i2c_periph i2c0;
extern void i2c0_init(void);
extern void i2c0_receive(uint8_t slave_addr, uint16_t len, volatile bool_t* finished);
extern void i2c0_transmit(uint8_t slave_addr, uint8_t len, volatile bool_t* finished);
extern void i2c0_transmit_no_stop(uint8_t slave_addr, uint8_t len, volatile bool_t* finished);
extern void i2c0_transceive(uint8_t slave_addr, uint8_t len_w, uint16_t len_r, volatile bool_t* finished);
extern volatile uint8_t i2c0_status;
extern volatile bool_t i2c0_stop_after_transmit;
#ifndef I2C0_BUF_LEN
#define I2C0_BUF_LEN 32
#endif
extern volatile uint8_t i2c0_buf[I2C0_BUF_LEN];
extern volatile uint16_t i2c0_len_r;
extern volatile uint8_t i2c0_len_w;
extern volatile uint8_t i2c0_index;
extern volatile uint8_t i2c0_slave_addr;
extern volatile uint8_t i2c0_trx;
extern volatile bool_t* i2c0_finished;
#endif /* USE_I2C0 */
#ifdef USE_I2C1
extern struct i2c_periph i2c1;