bsp/atsam: Use binary semaphore for I2C

Remove superfluous sleep before each I2C transfer.  Reset I2C module
after transfer timeouts.

Update #3534.
This commit is contained in:
Sebastian Huber
2018-10-01 09:01:29 +02:00
parent fca9132aa5
commit 5cb23f4b88
2 changed files with 21 additions and 23 deletions
+18 -21
View File
@@ -267,11 +267,8 @@ atsam_i2c_interrupt(void *arg)
atsam_i2c_next_packet(bus);
if (bus->msg_todo == 0 || err != 0) {
rtems_status_code sc;
atsam_i2c_disable_interrupts(regs);
sc = rtems_event_transient_send(bus->task_id);
assert(sc == RTEMS_SUCCESSFUL);
rtems_binary_semaphore_post(&bus->sem);
} else {
atsam_i2c_setup_transfer(bus, regs);
}
@@ -281,15 +278,13 @@ atsam_i2c_interrupt(void *arg)
static int
atsam_i2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)
{
rtems_status_code sc;
atsam_i2c_bus *bus = (atsam_i2c_bus *)base;
Twihs *regs;
uint32_t i;
rtems_task_wake_after(1);
int eno;
if (msg_count < 1){
return 1;
return 0;
}
for (i = 0; i < msg_count; ++i) {
@@ -302,7 +297,6 @@ atsam_i2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)
bus->msg_todo = msg_count;
bus->current_msg_todo = msgs[0].len;
bus->current_msg_byte = msgs[0].buf;
bus->task_id = rtems_task_self();
regs = bus->regs;
@@ -310,9 +304,13 @@ atsam_i2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)
regs->TWIHS_IER = ATSAMV_I2C_IRQ_ERROR;
sc = rtems_event_transient_receive(RTEMS_WAIT, bus->base.timeout);
if (sc != RTEMS_SUCCESSFUL){
rtems_event_transient_clear();
eno = rtems_binary_semaphore_wait_timed_ticks(
&bus->sem,
bus->base.timeout
);
if (eno != 0) {
TWI_ConfigureMaster(bus->regs, bus->output_clock, BOARD_MCK);
rtems_binary_semaphore_try_wait(&bus->sem);
return -ETIMEDOUT;
}
@@ -323,8 +321,8 @@ static int
atsam_i2c_set_clock(i2c_bus *base, unsigned long clock)
{
atsam_i2c_bus *bus = (atsam_i2c_bus *)base;
Twihs *regs = bus->regs;
TWI_ConfigureMaster(regs, clock, BOARD_MCK);
bus->output_clock = clock;
TWI_ConfigureMaster(bus->regs, clock, BOARD_MCK);
return 0;
}
@@ -341,8 +339,7 @@ atsam_i2c_destroy(i2c_bus *base)
}
static void
atsam_i2c_init(atsam_i2c_bus *bus, uint32_t input_clock, Twihs *board_base,
uint32_t board_id, const Pin *pins)
atsam_i2c_init(atsam_i2c_bus *bus, uint32_t board_id, const Pin *pins)
{
/* Initialize the TWI */
@@ -351,7 +348,7 @@ atsam_i2c_init(atsam_i2c_bus *bus, uint32_t input_clock, Twihs *board_base,
/* Enable the TWI clock */
ENABLE_PERIPHERAL(board_id);
TWI_ConfigureMaster(board_base, input_clock, BOARD_MCK);
TWI_ConfigureMaster(bus->regs, bus->output_clock, BOARD_MCK);
}
int
@@ -364,22 +361,22 @@ i2c_bus_register_atsam(
{
atsam_i2c_bus *bus;
rtems_status_code sc;
uint32_t board_id = (uint32_t) irq;
bus = (atsam_i2c_bus *) i2c_bus_alloc_and_init(sizeof(*bus));
if (bus == NULL){
return -1;
}
rtems_binary_semaphore_init(&bus->sem, "ATSAM I2C");
bus->regs = register_base;
bus->irq = irq;
bus->output_clock = I2C_BUS_CLOCK_DEFAULT;
atsam_i2c_init(bus, I2C_BUS_CLOCK_DEFAULT, bus->regs,
board_id, pins);
atsam_i2c_init(bus, irq, pins);
sc = rtems_interrupt_handler_install(
irq,
"Atsamv_I2C",
"ATSAM I2C",
RTEMS_INTERRUPT_UNIQUE,
atsam_i2c_interrupt,
bus
+3 -2
View File
@@ -19,6 +19,7 @@
#include <libchip/include/pio.h>
#include <bsp.h>
#include <rtems/thread.h>
#include <dev/i2c/i2c.h>
#ifdef __cplusplus
@@ -54,9 +55,9 @@ typedef struct {
uint32_t msg_todo;
uint32_t current_msg_todo;
uint8_t *current_msg_byte;
uint32_t input_clock;
uint32_t output_clock;
bool read;
rtems_id task_id;
rtems_binary_semaphore sem;
rtems_vector_number irq;
} atsam_i2c_bus;