/* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* Copyright (c) 2016 King Kévin */ /* this library handles communication with the I2C RTC IC Maxim DS1307 */ /* peripherals used: I2C (check source for details) */ /* standard libraries */ #include // standard integer types #include // standard I/O facilities #include // general utilities /* STM32 (including CM3) libraries */ #include // real-time control clock library #include // general purpose input output library #include // I2C library #include // interrupt handler #include // Cortex M3 utilities #include "rtc_ds1307.h" // RTC header and definitions /* which I2C to use */ #define I2C I2C1 #define I2C_RCC RCC_I2C1 #define I2C_IRQ NVIC_I2C1_IRQ #define I2C_PORT GPIOB #define I2C_PIN_SDA GPIO_I2C1_SDA // on PB7 #define I2C_PIN_SCL GPIO_I2C1_SCL // on PB6 #define I2C_ADDR 0b1101000 // DS1307 fixed slave address /* setup communication with RTC IC */ void rtc_setup(void) { /* enable peripheral */ rcc_periph_clock_enable(RCC_AFIO); // enable clock for alternate function rcc_periph_clock_enable(I2C_RCC); // enable clock for I2C peripheral gpio_set_mode(I2C_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, I2C_PIN_SDA | I2C_PIN_SCL); // setup I2C pin /* configure I2C peripheral (see RM008 26.3.3, I2C master) */ i2c_reset(I2C); // reset configuration i2c_peripheral_disable(I2C); // I2C needs to be disable to be configured i2c_set_clock_frequency(I2C, rcc_apb1_frequency/1E6); // configure the peripheral clock to the APB1 freq (where it is connected to) 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_peripheral_enable(I2C); // enable I2C after configuration completed } /* read memory from RTC IC * read data into * return if read succeeded */ static bool rtc_read_memory(uint8_t* data, size_t len) { bool to_return = false; // return if read succeeded if (data==NULL || len==0) { // verify there it data to be read goto error; } i2c_send_start(I2C); // send start condition to start transaction while (!(I2C_SR1(I2C) & I2C_SR1_SB)); // wait until start bit is transmitted if (!(I2C_SR2(I2C) & I2C_SR2_MSL)) { // verify if in master mode goto error; } i2c_send_7bit_address(I2C, I2C_ADDR, I2C_READ); // transmit address while (!(I2C_SR1(I2C) & I2C_SR1_ADDR)); // wait until address is transmitted if (I2C_SR2(I2C) & I2C_SR2_TRA) { // verify we are in receive mode (and read SR2 to clear ADDR) goto error; } for (size_t i=0; i