Skip to content

Commit

Permalink
Wire: allow switch from master to slave and vice versa (#191)
Browse files Browse the repository at this point in the history
  • Loading branch information
maidnl authored Nov 16, 2023
1 parent 87dcacb commit d0354d4
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 68 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
.idea
compile_commands.json
.clangd
.cache/
cores/arduino/mydebug.cpp
libraries/Storage/.development
cores/arduino/mydebug.cpp.donotuse
Expand Down
93 changes: 53 additions & 40 deletions cores/arduino/IRQManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,79 +556,85 @@ bool IRQManager::addPeripheral(Peripheral_t p, void *cfg) {
#endif

#if WIRE_HOWMANY > 0
/* I2C true NOT SCI */
else if(p == IRQ_I2C_MASTER && cfg != NULL) {
I2CIrqMasterReq_t *p_cfg = (I2CIrqMasterReq_t *)cfg;
//iic_master_instance_ctrl_t *ctrl = (iic_master_instance_ctrl_t *)p_cfg->ctrl;
i2c_master_cfg_t *mcfg = (i2c_master_cfg_t *)p_cfg->cfg;
uint8_t hw_channel = p_cfg->hw_channel;
I2CIrqReq_t *p_cfg = (I2CIrqReq_t *)cfg;
i2c_master_cfg_t *mcfg = (i2c_master_cfg_t *)p_cfg->mcfg;
i2c_slave_cfg_t *scfg = (i2c_slave_cfg_t *)p_cfg->scfg;
mcfg->ipl = I2C_MASTER_PRIORITY;

if (mcfg->txi_irq == FSP_INVALID_VECTOR) {
/* TX interrupt */
mcfg->txi_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)iic_master_txi_isr;
set_iic_tx_link_event(last_interrupt_index, hw_channel);
scfg->txi_irq = (IRQn_Type)last_interrupt_index;
set_iic_tx_link_event(last_interrupt_index, p_cfg->mcfg->channel);
R_BSP_IrqCfg((IRQn_Type)last_interrupt_index, I2C_MASTER_PRIORITY, mcfg);
last_interrupt_index++;

/* RX interrupt */
mcfg->rxi_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)iic_master_rxi_isr;
set_iic_rx_link_event(last_interrupt_index, hw_channel);
scfg->rxi_irq = (IRQn_Type)last_interrupt_index;
set_iic_rx_link_event(last_interrupt_index, p_cfg->mcfg->channel);
R_BSP_IrqCfg((IRQn_Type)last_interrupt_index, I2C_MASTER_PRIORITY, mcfg);
last_interrupt_index++;

/* TX ERROR interrupt */
mcfg->tei_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)iic_master_tei_isr;
set_iic_tei_link_event(last_interrupt_index, hw_channel);
scfg->tei_irq = (IRQn_Type)last_interrupt_index;
set_iic_tei_link_event(last_interrupt_index, p_cfg->mcfg->channel);
R_BSP_IrqCfg((IRQn_Type)last_interrupt_index, I2C_MASTER_PRIORITY, mcfg);
last_interrupt_index++;

/* RX ERROR interrupt */
mcfg->eri_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)iic_master_eri_isr;
set_iic_eri_link_event(last_interrupt_index, hw_channel);
scfg->eri_irq = (IRQn_Type)last_interrupt_index;
set_iic_eri_link_event(last_interrupt_index, p_cfg->mcfg->channel);
R_BSP_IrqCfg((IRQn_Type)last_interrupt_index, I2C_MASTER_PRIORITY, mcfg);
last_interrupt_index++;
}

*(irq_ptr + mcfg->txi_irq) = (uint32_t)iic_master_txi_isr;
*(irq_ptr + mcfg->rxi_irq) = (uint32_t)iic_master_rxi_isr;
*(irq_ptr + mcfg->tei_irq) = (uint32_t)iic_master_tei_isr;
*(irq_ptr + mcfg->eri_irq) = (uint32_t)iic_master_eri_isr;

R_BSP_IrqEnable (mcfg->txi_irq);
R_BSP_IrqEnable (mcfg->rxi_irq);
R_BSP_IrqEnable (mcfg->tei_irq);
R_BSP_IrqEnable (mcfg->eri_irq);
}
/* I2C SCI MASTER (only) */
else if(p == IRQ_SCI_I2C_MASTER && cfg != NULL) {
I2CIrqMasterReq_t *p_cfg = (I2CIrqMasterReq_t *)cfg;
//iic_master_instance_ctrl_t *ctrl = (iic_master_instance_ctrl_t *)p_cfg->ctrl;
i2c_master_cfg_t *mcfg = (i2c_master_cfg_t *)p_cfg->cfg;
uint8_t hw_channel = p_cfg->hw_channel;
I2CIrqReq_t *p_cfg = (I2CIrqReq_t *)cfg;
i2c_master_cfg_t *mcfg = (i2c_master_cfg_t *)p_cfg->mcfg;
mcfg->ipl = I2C_MASTER_PRIORITY;
if (mcfg->txi_irq == FSP_INVALID_VECTOR) {
/* TX interrupt */
mcfg->txi_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)sci_i2c_txi_isr;
set_sci_tx_link_event(last_interrupt_index, hw_channel);
set_sci_tx_link_event(last_interrupt_index, p_cfg->mcfg->channel);
R_BSP_IrqCfg((IRQn_Type)last_interrupt_index, I2C_MASTER_PRIORITY, mcfg);
last_interrupt_index++;

/* RX interrupt */
mcfg->rxi_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)sci_i2c_rxi_isr;
set_sci_rx_link_event(last_interrupt_index, hw_channel);
set_sci_rx_link_event(last_interrupt_index, p_cfg->mcfg->channel);
R_BSP_IrqCfg((IRQn_Type)last_interrupt_index, I2C_MASTER_PRIORITY, mcfg);
last_interrupt_index++;

/* TX ERROR interrupt */
mcfg->tei_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)sci_i2c_tei_isr;
set_sci_tei_link_event(last_interrupt_index, hw_channel);
set_sci_tei_link_event(last_interrupt_index, p_cfg->mcfg->channel);
R_BSP_IrqCfg((IRQn_Type)last_interrupt_index, I2C_MASTER_PRIORITY, mcfg);
last_interrupt_index++;

/* RX ERROR interrupt */
#if 0
mcfg->eri_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)sci_i2c_eri_isr;
set_sci_eri_link_event(last_interrupt_index, hw_channel);
set_sci_eri_link_event(last_interrupt_index, p_cfg->mcfg->channel);
R_BSP_IrqCfg((IRQn_Type)last_interrupt_index, I2C_MASTER_PRIORITY, mcfg);
last_interrupt_index++;
#endif
Expand All @@ -641,38 +647,45 @@ bool IRQManager::addPeripheral(Peripheral_t p, void *cfg) {
#endif
}
else if(p == IRQ_I2C_SLAVE && cfg != NULL) {
i2c_slave_cfg_t *p_cfg = (i2c_slave_cfg_t *)cfg;
p_cfg->ipl = I2C_SLAVE_PRIORITY;
p_cfg->eri_ipl = I2C_SLAVE_PRIORITY;
if (p_cfg->txi_irq == FSP_INVALID_VECTOR) {
I2CIrqReq_t *p_cfg = (I2CIrqReq_t *)cfg;
i2c_master_cfg_t *mcfg = (i2c_master_cfg_t *)p_cfg->mcfg;
i2c_slave_cfg_t *scfg = (i2c_slave_cfg_t *)p_cfg->scfg;
scfg->ipl = I2C_SLAVE_PRIORITY;
scfg->eri_ipl = I2C_SLAVE_PRIORITY;

if (scfg->txi_irq == FSP_INVALID_VECTOR) {
/* TX interrupt */
p_cfg->txi_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)iic_slave_txi_isr;
set_iic_tx_link_event(last_interrupt_index, p_cfg->channel);
mcfg->txi_irq = (IRQn_Type)last_interrupt_index;
scfg->txi_irq = (IRQn_Type)last_interrupt_index;
set_iic_tx_link_event(last_interrupt_index, scfg->channel);
last_interrupt_index++;

/* RX interrupt */
p_cfg->rxi_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)iic_slave_rxi_isr;
set_iic_rx_link_event(last_interrupt_index, p_cfg->channel);
scfg->rxi_irq = (IRQn_Type)last_interrupt_index;
mcfg->rxi_irq = (IRQn_Type)last_interrupt_index;
set_iic_rx_link_event(last_interrupt_index, scfg->channel);
last_interrupt_index++;

/* TEI interrupt */
p_cfg->tei_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)iic_slave_tei_isr;
set_iic_tei_link_event(last_interrupt_index, p_cfg->channel);
scfg->tei_irq = (IRQn_Type)last_interrupt_index;
mcfg->tei_irq = (IRQn_Type)last_interrupt_index;
set_iic_tei_link_event(last_interrupt_index, scfg->channel);
last_interrupt_index++;

/* ERI interrupt */
p_cfg->eri_irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)iic_slave_eri_isr;
set_iic_eri_link_event(last_interrupt_index, p_cfg->channel);
scfg->eri_irq = (IRQn_Type)last_interrupt_index;
mcfg->eri_irq = (IRQn_Type)last_interrupt_index;
set_iic_eri_link_event(last_interrupt_index, scfg->channel);
last_interrupt_index++;
}
R_BSP_IrqEnable (p_cfg->txi_irq);
R_BSP_IrqEnable (p_cfg->rxi_irq);
R_BSP_IrqEnable (p_cfg->tei_irq);
R_BSP_IrqEnable (p_cfg->eri_irq);
*(irq_ptr + scfg->txi_irq) = (uint32_t)iic_slave_txi_isr;
*(irq_ptr + scfg->rxi_irq) = (uint32_t)iic_slave_rxi_isr;
*(irq_ptr + scfg->tei_irq) = (uint32_t)iic_slave_tei_isr;
*(irq_ptr + scfg->eri_irq) = (uint32_t)iic_slave_eri_isr;
R_BSP_IrqEnable (scfg->txi_irq);
R_BSP_IrqEnable (scfg->rxi_irq);
R_BSP_IrqEnable (scfg->tei_irq);
R_BSP_IrqEnable (scfg->eri_irq);

}
#endif
Expand Down
16 changes: 4 additions & 12 deletions cores/arduino/IRQManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,10 @@ typedef struct rtc_irq {
#include "r_iic_master.h"
#include "r_iic_slave.h"

typedef struct i2c_master_irq {
iic_master_instance_ctrl_t *ctrl;
i2c_master_cfg_t *cfg;
uint8_t hw_channel;

} I2CIrqMasterReq_t;

typedef struct i2c_slave_irq {
iic_slave_instance_ctrl_t *ctrl;
i2c_slave_cfg_t *cfg;

} I2CIrqSlaveReq_t;
typedef struct i2c_irq_req {
i2c_master_cfg_t *mcfg;
i2c_slave_cfg_t *scfg;
} I2CIrqReq_t;
#endif

#if SPI_HOWMANY > 0
Expand Down
45 changes: 29 additions & 16 deletions libraries/Wire/Wire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,16 @@ bool TwoWire::cfg_pins(int max_index) {

/* -------------------------------------------------------------------------- */
void TwoWire::begin(void) {
/* -------------------------------------------------------------------------- */
end();
is_master = true;
_begin();

}


/* -------------------------------------------------------------------------- */
void TwoWire::_begin(void) {
/* -------------------------------------------------------------------------- */
init_ok = true;
int max_index = PINS_COUNT;
Expand Down Expand Up @@ -368,15 +378,11 @@ void TwoWire::begin(void) {
return;
}

if(is_master) {
I2CIrqMasterReq_t irq_req;
irq_req.ctrl = &m_i2c_ctrl;
irq_req.cfg = &m_i2c_cfg;
/* see note in the cfg_pins
the IRQ manager need to know the HW channel that in case of SCI
peripheral is not the one in the cfg structure but the one in
the Wire channel, so copy it in the request */
irq_req.hw_channel = channel;
I2CIrqReq_t irq_req;
irq_req.mcfg = &m_i2c_cfg;
irq_req.scfg = &s_i2c_cfg;

if(is_master) {
if(is_sci) {
init_ok &= IRQManager::getInstance().addPeripheral(IRQ_SCI_I2C_MASTER,&irq_req);
}
Expand All @@ -391,7 +397,7 @@ void TwoWire::begin(void) {
}
}
else {
init_ok &= IRQManager::getInstance().addPeripheral(IRQ_I2C_SLAVE,&s_i2c_cfg);
init_ok &= IRQManager::getInstance().addPeripheral(IRQ_I2C_SLAVE,&irq_req);
if(FSP_SUCCESS == s_open(&s_i2c_ctrl,&s_i2c_cfg)) {
init_ok &= true;
}
Expand All @@ -404,26 +410,23 @@ void TwoWire::begin(void) {
/* -------------------------------------------------------------------------- */
void TwoWire::begin(uint16_t address) {
/* -------------------------------------------------------------------------- */
end();
is_master = false;
slave_address = address;
/* Address is set inside begin() using slave_address member variable */
begin();
_begin();

}

/* -------------------------------------------------------------------------- */
void TwoWire::begin(int address) {
/* -------------------------------------------------------------------------- */
is_master = false;
slave_address = (uint16_t)address;
begin((uint16_t)address);
}

/* -------------------------------------------------------------------------- */
void TwoWire::begin(uint8_t address) {
/* -------------------------------------------------------------------------- */
is_master = false;
slave_address = (uint16_t)address;
begin((uint16_t)address);
}

Expand All @@ -434,12 +437,22 @@ void TwoWire::end(void) {
if(init_ok) {
if(is_master) {
if(m_close != nullptr) {
m_close(&m_i2c_ctrl);
m_close(&m_i2c_ctrl);
R_BSP_IrqDisable (m_i2c_cfg.txi_irq);
R_BSP_IrqDisable (m_i2c_cfg.rxi_irq);
R_BSP_IrqDisable (m_i2c_cfg.tei_irq);
R_BSP_IrqDisable (m_i2c_cfg.eri_irq);

}
}
else {
if(s_close != nullptr) {
s_close(&s_i2c_ctrl);
R_BSP_IrqDisable (s_i2c_cfg.txi_irq);
R_BSP_IrqDisable (s_i2c_cfg.rxi_irq);
R_BSP_IrqDisable (s_i2c_cfg.tei_irq);
R_BSP_IrqDisable (s_i2c_cfg.eri_irq);

}
}
}
Expand Down
2 changes: 2 additions & 0 deletions libraries/Wire/Wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ class TwoWire : public arduino::HardwareI2C {
static void WireSCIMasterCallback(i2c_master_callback_args_t *);
static void WireMasterCallback(i2c_master_callback_args_t *);
static void WireSlaveCallback(i2c_slave_callback_args_t *);

void _begin();

int scl_pin;
int sda_pin;
Expand Down

0 comments on commit d0354d4

Please sign in to comment.