diff --git a/include/arm11/hardware/i2c.h b/include/arm11/hardware/i2c.h index a9c298b..5e1e104 100644 --- a/include/arm11/hardware/i2c.h +++ b/include/arm11/hardware/i2c.h @@ -97,3 +97,14 @@ * @return Returns true on success and false on failure. */ bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data); + +/** + * @brief Writes a byte to a I2C register without interrupts. + * + * @param[in] devId The device ID. Use the enum above. + * @param[in] regAddr The register address. + * @param[in] data The data to write. + * + * @return Returns true on success and false on failure. + */ +bool I2C_writeRegIntSafe(I2cDevice devId, u8 regAddr, u8 data); diff --git a/source/arm11/hardware/i2c.c b/source/arm11/hardware/i2c.c index ac816e5..0274dda 100644 --- a/source/arm11/hardware/i2c.c +++ b/source/arm11/hardware/i2c.c @@ -242,3 +242,52 @@ { return I2C_writeRegBuf(devId, regAddr, &data, 1); } + +bool I2C_writeRegIntSafe(I2cDevice devId, u8 regAddr, u8 data) +{ + const u8 busId = i2cDevTable[devId].busId; + const u8 devAddr = i2cDevTable[devId].devAddr; + I2cRegs *const regs = i2cGetBusRegsBase(busId); + + + u32 tries = 8; + do + { + while(regs->I2C_CNT & I2C_ENABLE); + + // Select device and start. + regs->I2C_DATA = devAddr; + regs->I2C_CNT = I2C_ENABLE | I2C_DIRE_WRITE | I2C_START; + while(regs->I2C_CNT & I2C_ENABLE); + if(!(regs->I2C_CNT & I2C_ACK)) // If ack flag is 0 it failed. + { + regs->I2C_CNT = I2C_ENABLE | I2C_ERROR | I2C_STOP; + continue; + } + + // Select register. + regs->I2C_DATA = regAddr; + regs->I2C_CNT = I2C_ENABLE | I2C_DIRE_WRITE; + while(regs->I2C_CNT & I2C_ENABLE); + if(!(regs->I2C_CNT & I2C_ACK)) + { + regs->I2C_CNT = I2C_ENABLE | I2C_ERROR | I2C_STOP; + continue; + } + + break; + } while(--tries > 0); + + if(tries == 0) return false; + + regs->I2C_DATA = data; + regs->I2C_CNT = I2C_ENABLE | I2C_DIRE_WRITE | I2C_STOP; + while(regs->I2C_CNT & I2C_ENABLE); + if(!(regs->I2C_CNT & I2C_ACK)) + { + regs->I2C_CNT = I2C_ENABLE | I2C_ERROR | I2C_STOP; + return false; + } + + return true; +} diff --git a/source/arm11/hardware/mcu.c b/source/arm11/hardware/mcu.c index c1b5093..7c1dd6c 100644 --- a/source/arm11/hardware/mcu.c +++ b/source/arm11/hardware/mcu.c @@ -70,12 +70,12 @@ void MCU_triggerPowerOff(void) { - I2C_writeReg(I2C_DEV_MCU, RegPower, 1); + I2C_writeRegIntSafe(I2C_DEV_MCU, RegPower, 1); } void MCU_triggerReboot(void) { - I2C_writeReg(I2C_DEV_MCU, RegPower, 1u << 2); + I2C_writeRegIntSafe(I2C_DEV_MCU, RegPower, 1u << 2); } u8 MCU_readBatteryLevel(void)