use interrupt so to sleep instead of busy wait

This commit is contained in:
King Kévin 2016-03-23 10:41:30 +01:00
parent a421098cf7
commit d6f3efb001
1 changed files with 29 additions and 8 deletions

View File

@ -42,7 +42,9 @@
/** I2C peripheral clock */
#define I2C_RCC RCC_I2C1
/** I2C peripheral interrupt */
#define I2C_IRQ NVIC_I2C1_IRQ
#define I2C_IRQ NVIC_I2C1_EV_IRQ
/** I2C event interrupt service routine */
#define I2C_ISR i2c1_ev_isr
/** I2C peripheral port */
#define I2C_PORT GPIOB
/** I2C peripheral data pin (PB7) */
@ -67,6 +69,8 @@ void rtc_setup(void)
i2c_set_standard_mode(I2C); // the DS1307 has a maximum I2C SCL freq if 100 kHz (corresponding to the standard mode)
i2c_set_ccr(I2C, rcc_apb1_frequency/(100E3*2)); // set Thigh/Tlow to generate frequency of 100 kHz
i2c_set_trise(I2C, rcc_apb1_frequency/1E6); // max rise time for 100 kHz is 1000 ns (~1 MHz)
i2c_enable_interrupt(I2C, I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); // enable interrupts for events and buffer changes
nvic_enable_irq(I2C_IRQ); // enable interrupts for I2C
i2c_peripheral_enable(I2C); // enable I2C after configuration completed
}
@ -83,21 +87,31 @@ static bool rtc_read_memory(uint8_t addr, uint8_t* data, size_t len)
goto error;
}
i2c_send_start(I2C); // send start condition to start transaction
while (!(I2C_SR1(I2C) & I2C_SR1_SB)); // wait until start condition is transmitted
while (!(I2C_SR1(I2C) & I2C_SR1_SB)) { // wait until start condition is transmitted
__WFI(); // go to sleep
}
if (!(I2C_SR2(I2C) & I2C_SR2_MSL)) { // verify if in master mode
goto error;
}
i2c_send_7bit_address(I2C, I2C_ADDR, I2C_WRITE); // select slave
while (!(I2C_SR1(I2C) & I2C_SR1_ADDR)); // wait until address is transmitted
while (!(I2C_SR1(I2C) & I2C_SR1_ADDR)) { // wait until address is transmitted
__WFI(); // go to sleep
}
if (!((I2C_SR2(I2C) & I2C_SR2_TRA))) { // verify we are in transmit mode (and read SR2 to clear ADDR)
goto error;
}
i2c_send_data(I2C, addr); // send memory address we want to read
while (!(I2C_SR1(I2C) & I2C_SR1_TxE)); // wait until byte has been transmitted
while (!(I2C_SR1(I2C) & I2C_SR1_TxE)) { // wait until byte has been transmitted
__WFI(); // go to sleep
}
i2c_send_start(I2C); // send restart condition to switch from write to read mode
while (!(I2C_SR1(I2C) & I2C_SR1_SB)); // wait until start condition is transmitted
while (!(I2C_SR1(I2C) & I2C_SR1_SB)) { // wait until start condition is transmitted
__WFI(); // go to sleep
}
i2c_send_7bit_address(I2C, I2C_ADDR, I2C_READ); // select slave
while (!(I2C_SR1(I2C) & I2C_SR1_ADDR)); // wait until address is transmitted
while (!(I2C_SR1(I2C) & I2C_SR1_ADDR)) { // wait until address is transmitted
__WFI(); // go to sleep
}
if ((I2C_SR2(I2C) & I2C_SR2_TRA)) { // verify we are in read mode (and read SR2 to clear ADDR)
goto error;
}
@ -108,7 +122,9 @@ static bool rtc_read_memory(uint8_t addr, uint8_t* data, size_t len)
} else {
i2c_enable_ack(I2C); // ACK received byte to continue slave transmission
}
while (!(I2C_SR1(I2C) & I2C_SR1_RxNE)); // wait until byte has been received
while (!(I2C_SR1(I2C) & I2C_SR1_RxNE)) { // wait until byte has been received
__WFI(); // go to sleep
}
data[i] = i2c_get_data(I2C); // read received byte
}
to_return = true;
@ -116,7 +132,9 @@ error:
if (I2C_SR2(I2C) & I2C_SR2_BUSY) { // release bus if busy
i2c_send_stop(I2C); // send stop to release bus
}
while (I2C_SR2(I2C) & I2C_SR2_MSL); // wait until bus released (non master mode)
while (I2C_SR2(I2C) & I2C_SR2_MSL) { // wait until bus released (non master mode)
__WFI(); // go to sleep
}
return to_return;
}
@ -395,3 +413,6 @@ bool rtc_write_time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t day
return rtc_write_memory(0, data, LENGTH(data)); // write time values on RTC
}
void I2C_ISR(void) { // I2C event ISR
// do nothing except wake up
}