mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
bsp/atsam/i2c: Simplify driver
Do some clean ups. Remove superfluous variables. Eliminate some overly complex logic (information about transfer and remaining bytes has been tracked redundantly in multiple variables). This patch doesn't change the behavior of the driver. Update #4591
This commit is contained in:
@@ -37,68 +37,67 @@ atsam_i2c_disable_interrupts(Twihs *regs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
atsam_i2c_set_transfer_status(transfer_desc *trans_desc, transfer_state state)
|
atsam_i2c_set_transfer_status(atsam_i2c_bus *bus, transfer_state state)
|
||||||
{
|
{
|
||||||
trans_desc->trans_state = state;
|
bus->trans_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
atsam_i2c_continue_read(Twihs *regs, transfer_desc *trans_desc)
|
atsam_i2c_continue_read(Twihs *regs, atsam_i2c_bus *bus)
|
||||||
{
|
{
|
||||||
trans_desc->data[trans_desc->already_transferred] = TWI_ReadByte(regs);
|
*bus->current_msg_byte = TWI_ReadByte(regs);
|
||||||
trans_desc->already_transferred++;
|
++bus->current_msg_byte;
|
||||||
|
--bus->current_msg_todo;
|
||||||
|
|
||||||
/* check for transfer finish */
|
/* check for transfer finish */
|
||||||
if (trans_desc->already_transferred == trans_desc->data_size) {
|
if (bus->current_msg_todo == 0) {
|
||||||
if (trans_desc->stop_request){
|
if (bus->stop_request){
|
||||||
TWI_DisableIt(regs, TWIHS_IDR_RXRDY);
|
TWI_DisableIt(regs, TWIHS_IDR_RXRDY);
|
||||||
TWI_EnableIt(regs, TWIHS_IER_TXCOMP);
|
TWI_EnableIt(regs, TWIHS_IER_TXCOMP);
|
||||||
atsam_i2c_set_transfer_status(trans_desc, TX_RX_STOP_SENT);
|
atsam_i2c_set_transfer_status(bus, TX_RX_STOP_SENT);
|
||||||
} else {
|
} else {
|
||||||
atsam_i2c_set_transfer_status(trans_desc, RX_CONT_MESSAGE_NEEDED);
|
atsam_i2c_set_transfer_status(bus, RX_CONT_MESSAGE_NEEDED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Last byte? */
|
/* Last byte? */
|
||||||
else if ((trans_desc->already_transferred == (trans_desc->data_size - 1))
|
else if (bus->current_msg_todo == 1 && bus->stop_request) {
|
||||||
&& (trans_desc->stop_request)){
|
|
||||||
TWI_Stop(regs);
|
TWI_Stop(regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
atsam_i2c_is_state(transfer_desc *trans_desc, transfer_state state)
|
atsam_i2c_is_state(atsam_i2c_bus *bus, transfer_state state)
|
||||||
{
|
{
|
||||||
return (trans_desc->trans_state == state);
|
return (bus->trans_state == state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
atsam_i2c_continue_write(Twihs *regs, transfer_desc *trans_desc)
|
atsam_i2c_continue_write(Twihs *regs, atsam_i2c_bus *bus)
|
||||||
{
|
{
|
||||||
/* Transfer finished ? */
|
/* Transfer finished ? */
|
||||||
if (trans_desc->already_transferred == trans_desc->data_size) {
|
if (bus->current_msg_todo == 0) {
|
||||||
TWI_DisableIt(regs, TWIHS_IDR_TXRDY);
|
TWI_DisableIt(regs, TWIHS_IDR_TXRDY);
|
||||||
if (trans_desc->stop_request){
|
if (bus->stop_request){
|
||||||
TWI_EnableIt(regs, TWIHS_IER_TXCOMP);
|
TWI_EnableIt(regs, TWIHS_IER_TXCOMP);
|
||||||
TWI_SendSTOPCondition(regs);
|
TWI_SendSTOPCondition(regs);
|
||||||
atsam_i2c_set_transfer_status(trans_desc, TX_RX_STOP_SENT);
|
atsam_i2c_set_transfer_status(bus, TX_RX_STOP_SENT);
|
||||||
} else {
|
} else {
|
||||||
atsam_i2c_set_transfer_status(trans_desc, TX_CONT_MESSAGE_NEEDED);
|
atsam_i2c_set_transfer_status(bus, TX_CONT_MESSAGE_NEEDED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Bytes remaining */
|
/* Bytes remaining */
|
||||||
else {
|
else {
|
||||||
TWI_WriteByte(regs,
|
TWI_WriteByte(regs, *bus->current_msg_byte);
|
||||||
trans_desc->data[trans_desc->already_transferred]);
|
++bus->current_msg_byte;
|
||||||
trans_desc->already_transferred++;
|
--bus->current_msg_todo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
atsam_i2c_finish_write_transfer(Twihs *regs, transfer_desc *trans_desc)
|
atsam_i2c_finish_write_transfer(Twihs *regs)
|
||||||
{
|
{
|
||||||
TWI_ReadByte(regs);
|
TWI_ReadByte(regs);
|
||||||
TWI_DisableIt(regs, TWIHS_IDR_TXCOMP);
|
TWI_DisableIt(regs, TWIHS_IDR_TXCOMP);
|
||||||
trans_desc->status = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -115,19 +114,6 @@ atsam_i2c_next_packet(atsam_i2c_bus *bus)
|
|||||||
bus->current_msg_byte = msg->buf;
|
bus->current_msg_byte = msg->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
atsam_i2c_set_td(atsam_i2c_bus *bus, uint32_t already_transferred,
|
|
||||||
bool stop_needed)
|
|
||||||
{
|
|
||||||
transfer_desc *trans_desc = &bus->trans_desc;
|
|
||||||
|
|
||||||
trans_desc->status = ASYNC_STATUS_PENDING;
|
|
||||||
trans_desc->data = bus->current_msg_byte;
|
|
||||||
trans_desc->data_size = bus->current_msg_todo;
|
|
||||||
trans_desc->already_transferred = already_transferred;
|
|
||||||
trans_desc->stop_request = stop_needed;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
atsam_i2c_set_address_size(const i2c_msg *msg)
|
atsam_i2c_set_address_size(const i2c_msg *msg)
|
||||||
{
|
{
|
||||||
@@ -186,6 +172,8 @@ atsam_i2c_setup_write_transfer(atsam_i2c_bus *bus, Twihs *regs, bool ctrl,
|
|||||||
{
|
{
|
||||||
atsam_i2c_set_address_regs(regs, slave_addr, ctrl, false);
|
atsam_i2c_set_address_regs(regs, slave_addr, ctrl, false);
|
||||||
TWI_WriteByte(regs, *bus->current_msg_byte);
|
TWI_WriteByte(regs, *bus->current_msg_byte);
|
||||||
|
++bus->current_msg_byte;
|
||||||
|
--bus->current_msg_todo;
|
||||||
TWI_EnableIt(regs, TWIHS_IER_TXRDY);
|
TWI_EnableIt(regs, TWIHS_IER_TXRDY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,8 +185,8 @@ atsam_i2c_setup_transfer(atsam_i2c_bus *bus, Twihs *regs)
|
|||||||
uint32_t msg_todo = bus->msg_todo;
|
uint32_t msg_todo = bus->msg_todo;
|
||||||
uint16_t slave_addr;
|
uint16_t slave_addr;
|
||||||
bool ten_bit_addr = false;
|
bool ten_bit_addr = false;
|
||||||
uint32_t already_transferred;
|
|
||||||
bool stop_needed = true;
|
bool stop_needed = true;
|
||||||
|
bool read;
|
||||||
|
|
||||||
ten_bit_addr = atsam_i2c_set_address_size(msgs);
|
ten_bit_addr = atsam_i2c_set_address_size(msgs);
|
||||||
|
|
||||||
@@ -206,22 +194,19 @@ atsam_i2c_setup_transfer(atsam_i2c_bus *bus, Twihs *regs)
|
|||||||
stop_needed = false;
|
stop_needed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus->read = (msgs->flags & I2C_M_RD) != 0;
|
read = (msgs->flags & I2C_M_RD) != 0;
|
||||||
slave_addr = msgs->addr;
|
slave_addr = msgs->addr;
|
||||||
already_transferred = (bus->read == true) ? 0 : 1;
|
bus->stop_request = stop_needed;
|
||||||
atsam_i2c_set_td(bus, already_transferred, stop_needed);
|
|
||||||
|
|
||||||
transfer_desc *trans_desc = &bus->trans_desc;
|
if (read){
|
||||||
|
|
||||||
if (bus->read){
|
|
||||||
if (bus->current_msg_todo == 1){
|
if (bus->current_msg_todo == 1){
|
||||||
send_stop = true;
|
send_stop = true;
|
||||||
}
|
}
|
||||||
atsam_i2c_set_transfer_status(trans_desc, RX_SEND_DATA);
|
atsam_i2c_set_transfer_status(bus, RX_SEND_DATA);
|
||||||
atsam_i2c_setup_read_transfer(regs, ten_bit_addr,
|
atsam_i2c_setup_read_transfer(regs, ten_bit_addr,
|
||||||
slave_addr, send_stop);
|
slave_addr, send_stop);
|
||||||
} else {
|
} else {
|
||||||
atsam_i2c_set_transfer_status(trans_desc, TX_SEND_DATA);
|
atsam_i2c_set_transfer_status(bus, TX_SEND_DATA);
|
||||||
atsam_i2c_setup_write_transfer(bus, regs, ten_bit_addr,
|
atsam_i2c_setup_write_transfer(bus, regs, ten_bit_addr,
|
||||||
slave_addr);
|
slave_addr);
|
||||||
}
|
}
|
||||||
@@ -233,7 +218,6 @@ atsam_i2c_interrupt(void *arg)
|
|||||||
atsam_i2c_bus *bus = arg;
|
atsam_i2c_bus *bus = arg;
|
||||||
uint32_t irqstatus;
|
uint32_t irqstatus;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
transfer_desc *trans_desc;
|
|
||||||
|
|
||||||
Twihs *regs = bus->regs;
|
Twihs *regs = bus->regs;
|
||||||
|
|
||||||
@@ -244,20 +228,18 @@ atsam_i2c_interrupt(void *arg)
|
|||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
trans_desc = &bus->trans_desc;
|
|
||||||
|
|
||||||
if (((irqstatus & TWIHS_SR_RXRDY) != 0) &&
|
if (((irqstatus & TWIHS_SR_RXRDY) != 0) &&
|
||||||
(atsam_i2c_is_state(trans_desc, RX_SEND_DATA))){
|
(atsam_i2c_is_state(bus, RX_SEND_DATA))){
|
||||||
/* carry on read transfer */
|
/* carry on read transfer */
|
||||||
atsam_i2c_continue_read(regs, trans_desc);
|
atsam_i2c_continue_read(regs, bus);
|
||||||
} else if (((irqstatus & TWIHS_SR_TXCOMP) != 0) &&
|
} else if (((irqstatus & TWIHS_SR_TXCOMP) != 0) &&
|
||||||
(atsam_i2c_is_state(trans_desc, TX_RX_STOP_SENT))){
|
(atsam_i2c_is_state(bus, TX_RX_STOP_SENT))){
|
||||||
atsam_i2c_finish_write_transfer(regs, trans_desc);
|
atsam_i2c_finish_write_transfer(regs);
|
||||||
done = true;
|
done = true;
|
||||||
} else if (((irqstatus & TWIHS_SR_TXRDY) != 0) &&
|
} else if (((irqstatus & TWIHS_SR_TXRDY) != 0) &&
|
||||||
(atsam_i2c_is_state(trans_desc, TX_SEND_DATA))){
|
(atsam_i2c_is_state(bus, TX_SEND_DATA))){
|
||||||
atsam_i2c_continue_write(regs, trans_desc);
|
atsam_i2c_continue_write(regs, bus);
|
||||||
if (trans_desc->trans_state == TX_CONT_MESSAGE_NEEDED){
|
if (atsam_i2c_is_state(bus, TX_CONT_MESSAGE_NEEDED)){
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,33 +30,27 @@ extern "C" {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TX_SEND_DATA,
|
TX_SEND_DATA,
|
||||||
TX_SEND_STOP,
|
|
||||||
TX_CONT_MESSAGE_NEEDED,
|
TX_CONT_MESSAGE_NEEDED,
|
||||||
RX_SEND_DATA,
|
RX_SEND_DATA,
|
||||||
RX_SEND_STOP,
|
|
||||||
RX_CONT_MESSAGE_NEEDED,
|
RX_CONT_MESSAGE_NEEDED,
|
||||||
TX_RX_STOP_SENT
|
TX_RX_STOP_SENT
|
||||||
}transfer_state;
|
}transfer_state;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t status;
|
|
||||||
uint8_t *data;
|
|
||||||
bool stop_request;
|
|
||||||
uint32_t data_size;
|
|
||||||
uint32_t already_transferred;
|
|
||||||
transfer_state trans_state;
|
|
||||||
} transfer_desc;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
i2c_bus base;
|
i2c_bus base;
|
||||||
i2c_msg *msgs;
|
|
||||||
Twihs *regs;
|
Twihs *regs;
|
||||||
transfer_desc trans_desc;
|
|
||||||
|
/* First message and number of messages that have to be processed. */
|
||||||
|
i2c_msg *msgs;
|
||||||
uint32_t msg_todo;
|
uint32_t msg_todo;
|
||||||
|
|
||||||
|
/* Information about the current transfer. */
|
||||||
|
bool stop_request;
|
||||||
|
transfer_state trans_state;
|
||||||
uint32_t current_msg_todo;
|
uint32_t current_msg_todo;
|
||||||
uint8_t *current_msg_byte;
|
uint8_t *current_msg_byte;
|
||||||
|
|
||||||
uint32_t output_clock;
|
uint32_t output_clock;
|
||||||
bool read;
|
|
||||||
rtems_binary_semaphore sem;
|
rtems_binary_semaphore sem;
|
||||||
rtems_vector_number irq;
|
rtems_vector_number irq;
|
||||||
} atsam_i2c_bus;
|
} atsam_i2c_bus;
|
||||||
|
|||||||
Reference in New Issue
Block a user