atsamd: Add i2c_read() implementation

Signed-off-by: Simon Kühling <mail@simonkuehling.de>
This commit is contained in:
Simon Kühling 2021-09-03 20:58:22 +02:00 committed by KevinOConnor
parent 2822680eb4
commit d90da37433
1 changed files with 43 additions and 1 deletions

View File

@ -102,5 +102,47 @@ void
i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg
, uint8_t read_len, uint8_t *read)
{
shutdown("i2c_read not supported on samd21");
SercomI2cm *si = (SercomI2cm *)config.si;
// start in write mode and write register if provided
if(reg_len) {
// start in write mode
si->ADDR.reg = config.addr;
while (!(si->INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB));
// write registers
while (reg_len--){
si->DATA.reg = *reg++;
while (!(si->INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB));
}
}
// start with read bit enabled
si->ADDR.reg = (config.addr | 0x1);
// read bytes from slave
while (read_len--){
while (!(si->INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB));
if (read_len){
// set ACK response
si->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
while (si->SYNCBUSY.bit.SYSOP);
// execute ACK succeded by byte read
si->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(2);
while (si->SYNCBUSY.bit.SYSOP);
} else {
// set NACK response
si->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
while (si->SYNCBUSY.bit.SYSOP);
// execute NACK succeded by stop condition
si->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
while (si->SYNCBUSY.bit.SYSOP);
}
// read received data byte
*read++ = si->DATA.reg;
}
}