Improve I2C power-cycling logic:
We only power, clock and enable the peripepheral when / if we need it * We no longer automatically turn on the SERIAL PD when the CM3 is running * Make sure the I2C peripheral is accessible (powered and clocked) before any operation * If the peripheral is not accessible, automatically power it up and run the clock * Put SDA, SCL, SDA HP and SCL HP in a low-leakage state when shutting down * Don't automatically fire up the I2C controller when we wake up
This commit is contained in:
parent
0ad4b5f323
commit
34be012661
3 changed files with 108 additions and 14 deletions
|
@ -39,9 +39,55 @@
|
||||||
#include "contiki-conf.h"
|
#include "contiki-conf.h"
|
||||||
#include "ti-lib.h"
|
#include "ti-lib.h"
|
||||||
#include "board-i2c.h"
|
#include "board-i2c.h"
|
||||||
|
#include "lpm.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#define NO_INTERFACE 0xFF
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static uint8_t slave_addr = 0x00;
|
static uint8_t slave_addr = 0x00;
|
||||||
static uint8_t interface = 0xFF;
|
static uint8_t interface = NO_INTERFACE;
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static bool
|
||||||
|
accessible(void)
|
||||||
|
{
|
||||||
|
/* First, check the PD */
|
||||||
|
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
|
||||||
|
!= PRCM_DOMAIN_POWER_ON) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then check the 'run mode' clock gate */
|
||||||
|
if(!(HWREG(PRCM_BASE + PRCM_O_I2CCLKGR) & PRCM_I2CCLKGR_CLK_EN)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
board_i2c_wakeup()
|
||||||
|
{
|
||||||
|
/* First, make sure the SERIAL PD is on */
|
||||||
|
ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL);
|
||||||
|
while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
|
||||||
|
!= PRCM_DOMAIN_POWER_ON));
|
||||||
|
|
||||||
|
/* Enable the clock to I2C */
|
||||||
|
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_I2C0);
|
||||||
|
ti_lib_prcm_load_set();
|
||||||
|
while(!ti_lib_prcm_load_get());
|
||||||
|
|
||||||
|
/* Reset the I2C controller */
|
||||||
|
HWREG(PRCM_BASE + PRCM_O_RESETI2C) = PRCM_RESETI2C_I2C;
|
||||||
|
|
||||||
|
/* Enable and initialize the I2C master module */
|
||||||
|
ti_lib_i2c_master_init_exp_clk(I2C0_BASE,
|
||||||
|
ti_lib_sys_ctrl_peripheral_clock_get(
|
||||||
|
PRCM_PERIPH_I2C0, SYSCTRL_SYSBUS_ON),
|
||||||
|
true);
|
||||||
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static bool
|
static bool
|
||||||
i2c_status()
|
i2c_status()
|
||||||
|
@ -57,21 +103,34 @@ i2c_status()
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
board_i2c_init()
|
board_i2c_shutdown()
|
||||||
{
|
{
|
||||||
/* The I2C peripheral must be enabled */
|
interface = NO_INTERFACE;
|
||||||
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_I2C0);
|
|
||||||
|
if(accessible()) {
|
||||||
|
ti_lib_i2c_master_disable(I2C0_BASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_I2C0);
|
||||||
ti_lib_prcm_load_set();
|
ti_lib_prcm_load_set();
|
||||||
while(!ti_lib_prcm_load_get());
|
while(!ti_lib_prcm_load_get());
|
||||||
|
|
||||||
/* Reset the I2C controller */
|
/*
|
||||||
HWREG(PRCM_BASE + PRCM_O_RESETI2C) = PRCM_RESETI2C_I2C;
|
* Set all pins to GPIO Input and disable the output driver. Set internal
|
||||||
|
* pull to match external pull
|
||||||
|
*
|
||||||
|
* SDA and SCL: external PU resistor
|
||||||
|
* SDA HP and SCL HP: MPU PWR low
|
||||||
|
*/
|
||||||
|
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA_HP);
|
||||||
|
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA_HP, IOC_IOPULL_DOWN);
|
||||||
|
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL_HP);
|
||||||
|
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL_HP, IOC_IOPULL_DOWN);
|
||||||
|
|
||||||
/* Enable and initialize the I2C master module */
|
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA);
|
||||||
ti_lib_i2c_master_init_exp_clk(I2C0_BASE,
|
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA, IOC_IOPULL_UP);
|
||||||
ti_lib_sys_ctrl_peripheral_clock_get(
|
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL);
|
||||||
PRCM_PERIPH_I2C0, SYSCTRL_SYSBUS_ON),
|
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, IOC_IOPULL_UP);
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
bool
|
bool
|
||||||
|
@ -248,8 +307,15 @@ board_i2c_select(uint8_t new_interface, uint8_t address)
|
||||||
{
|
{
|
||||||
slave_addr = address;
|
slave_addr = address;
|
||||||
|
|
||||||
|
if(accessible() == false) {
|
||||||
|
board_i2c_wakeup();
|
||||||
|
}
|
||||||
|
|
||||||
if(new_interface != interface) {
|
if(new_interface != interface) {
|
||||||
interface = new_interface;
|
interface = new_interface;
|
||||||
|
|
||||||
|
ti_lib_i2c_master_disable(I2C0_BASE);
|
||||||
|
|
||||||
if(interface == BOARD_I2C_INTERFACE_0) {
|
if(interface == BOARD_I2C_INTERFACE_0) {
|
||||||
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA, IOC_NO_IOPULL);
|
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA, IOC_NO_IOPULL);
|
||||||
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, IOC_NO_IOPULL);
|
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, IOC_NO_IOPULL);
|
||||||
|
@ -263,6 +329,12 @@ board_i2c_select(uint8_t new_interface, uint8_t address)
|
||||||
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA);
|
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA);
|
||||||
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL);
|
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enable and initialize the I2C master module */
|
||||||
|
ti_lib_i2c_master_init_exp_clk(I2C0_BASE,
|
||||||
|
ti_lib_sys_ctrl_peripheral_clock_get(
|
||||||
|
PRCM_PERIPH_I2C0, SYSCTRL_SYSBUS_ON),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -101,6 +101,27 @@ bool board_i2c_write_single(uint8_t data);
|
||||||
*/
|
*/
|
||||||
bool board_i2c_write_read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata,
|
bool board_i2c_write_read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata,
|
||||||
uint8_t rlen);
|
uint8_t rlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Enables the I2C peripheral with defaults
|
||||||
|
*
|
||||||
|
* This function is called to wakeup and initialise the I2C.
|
||||||
|
*
|
||||||
|
* This function can be called explicitly, but it will also be called
|
||||||
|
* automatically by board_i2c_select() when required. One of those two
|
||||||
|
* functions MUST be called before any other I2C operation after a chip
|
||||||
|
* sleep / wakeup cycle or after a call to board_i2c_shutdown(). Failing to do
|
||||||
|
* so will lead to a bus fault.
|
||||||
|
*/
|
||||||
|
void board_i2c_wakeup(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Stops the I2C peripheral and restores pins to s/w control
|
||||||
|
*
|
||||||
|
* This function is called automatically by the board's LPM logic, but it
|
||||||
|
* can also be called explicitly.
|
||||||
|
*/
|
||||||
|
void board_i2c_shutdown(void);
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#endif /* BOARD_I2C_H_ */
|
#endif /* BOARD_I2C_H_ */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -65,8 +65,6 @@ static void
|
||||||
lpm_wakeup_handler(void)
|
lpm_wakeup_handler(void)
|
||||||
{
|
{
|
||||||
power_domains_on();
|
power_domains_on();
|
||||||
|
|
||||||
board_i2c_init();
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -80,6 +78,9 @@ shutdown_handler(uint8_t mode)
|
||||||
SENSORS_DEACTIVATE(hdc_1000_sensor);
|
SENSORS_DEACTIVATE(hdc_1000_sensor);
|
||||||
mpu_9250_sensor.configure(MPU_9250_SENSOR_SHUTDOWN, 0);
|
mpu_9250_sensor.configure(MPU_9250_SENSOR_SHUTDOWN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In all cases, stop the I2C */
|
||||||
|
board_i2c_shutdown();
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/*
|
/*
|
||||||
|
@ -125,7 +126,6 @@ board_init()
|
||||||
ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP);
|
ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP);
|
||||||
|
|
||||||
/* I2C controller */
|
/* I2C controller */
|
||||||
board_i2c_init();
|
|
||||||
|
|
||||||
/* Sensor interface */
|
/* Sensor interface */
|
||||||
ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT);
|
ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT);
|
||||||
|
@ -139,6 +139,7 @@ board_init()
|
||||||
/* Flash interface */
|
/* Flash interface */
|
||||||
ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS);
|
ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS);
|
||||||
ti_lib_gpio_pin_write(BOARD_FLASH_CS, 1);
|
ti_lib_gpio_pin_write(BOARD_FLASH_CS, 1);
|
||||||
|
board_i2c_wakeup();
|
||||||
|
|
||||||
buzzer_init();
|
buzzer_init();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue