mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
cpu/qn908x/periph_i2c: enable internal pull-up on SCL
Always enable the internal pull-up on the SCL line to always have a functional I2C bus. This may increase power consumption where an external pull up is present as well. But let's wait for a real world use case where this would help to extend battery life before making this configurable. This fixes https://github.com/RIOT-OS/RIOT/issues/19021
This commit is contained in:
parent
0e09b43f6d
commit
98b38399df
@ -57,7 +57,7 @@ int flexcomm_init(FLEXCOMM_Type *dev, flexcom_pselid_t mode);
|
|||||||
* For example, the flexcomm block number of FLEXCOMM2, the pointer to the
|
* For example, the flexcomm block number of FLEXCOMM2, the pointer to the
|
||||||
* FLEXCOMM_Type block is 2. If an invalid address is passed returns -1.
|
* FLEXCOMM_Type block is 2. If an invalid address is passed returns -1.
|
||||||
*/
|
*/
|
||||||
int flexcomm_instance_from_addr(FLEXCOMM_Type *dev);
|
int flexcomm_instance_from_addr(const FLEXCOMM_Type *dev);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "vendor/drivers/fsl_clock.h"
|
#include "vendor/drivers/fsl_clock.h"
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG 0
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
int flexcomm_init(FLEXCOMM_Type *dev, flexcom_pselid_t mode)
|
int flexcomm_init(FLEXCOMM_Type *dev, flexcom_pselid_t mode)
|
||||||
@ -59,7 +61,7 @@ int flexcomm_init(FLEXCOMM_Type *dev, flexcom_pselid_t mode)
|
|||||||
return flexcomm_num;
|
return flexcomm_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flexcomm_instance_from_addr(FLEXCOMM_Type *dev)
|
int flexcomm_instance_from_addr(const FLEXCOMM_Type *dev)
|
||||||
{
|
{
|
||||||
static const FLEXCOMM_Type *flexcomm_addrs[] = FLEXCOMM_BASE_PTRS;
|
static const FLEXCOMM_Type *flexcomm_addrs[] = FLEXCOMM_BASE_PTRS;
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "periph/i2c.h"
|
#include "periph/i2c.h"
|
||||||
|
|
||||||
#include "vendor/drivers/fsl_clock.h"
|
#include "vendor/drivers/fsl_clock.h"
|
||||||
|
#include "vendor/drivers/fsl_iocon.h"
|
||||||
|
|
||||||
#include "gpio_mux.h"
|
#include "gpio_mux.h"
|
||||||
#include "flexcomm.h"
|
#include "flexcomm.h"
|
||||||
@ -41,6 +42,22 @@
|
|||||||
|
|
||||||
static mutex_t locks[I2C_NUMOF];
|
static mutex_t locks[I2C_NUMOF];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Definitions for MSTSTATE bits in I2C Status register STAT
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* Controller Idle State Code */
|
||||||
|
#define I2C_STAT_MSTSTATE_IDLE (0)
|
||||||
|
/* Controller Receive Ready State Code */
|
||||||
|
#define I2C_STAT_MSTSTATE_RXREADY (1)
|
||||||
|
/* Controller Transmit Ready State Code */
|
||||||
|
#define I2C_STAT_MSTSTATE_TXREADY (2)
|
||||||
|
/* Controller NACK by peripheral on address State Code */
|
||||||
|
#define I2C_STAT_MSTSTATE_NACKADR (3)
|
||||||
|
/* Controller NACK by peripheral on data State Code */
|
||||||
|
#define I2C_STAT_MSTSTATE_NACKDAT (4)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Limit value I2C CLKDIV register.
|
* @brief Limit value I2C CLKDIV register.
|
||||||
*/
|
*/
|
||||||
@ -99,16 +116,41 @@ static void _i2c_init_pins(i2c_t dev)
|
|||||||
*/
|
*/
|
||||||
static const uint32_t func5_mask =
|
static const uint32_t func5_mask =
|
||||||
(1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 20) | (1 << 21);
|
(1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 20) | (1 << 21);
|
||||||
/* TODO: Have a way to configure IOCON_MODE_PULLUP and IOCON_DRIVE_HIGH
|
|
||||||
* from the board. */
|
uint32_t sda_mode = IOCON_FUNC4;
|
||||||
gpio_init_mux(conf->pin_sda,
|
if ((1u << GPIO_T_PIN(conf->pin_sda)) & func5_mask) {
|
||||||
((1u << GPIO_T_PIN(conf->pin_sda)) & func5_mask) ? 5 : 4);
|
sda_mode = IOCON_FUNC5;
|
||||||
gpio_init_mux(conf->pin_scl,
|
}
|
||||||
((1u << GPIO_T_PIN(conf->pin_scl)) & func5_mask) ? 5 : 4);
|
|
||||||
|
uint32_t scl_mode = IOCON_FUNC4;
|
||||||
|
if ((1u << GPIO_T_PIN(conf->pin_scl)) & func5_mask) {
|
||||||
|
sda_mode = IOCON_FUNC5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Using the internal pull up will make sure the I2C bus is also working
|
||||||
|
* when no external pull up is present. It can waste power by when both
|
||||||
|
* external and internal pull up are present. If a real world example
|
||||||
|
* shows up where disabling the internal pull up is helpful, we can extend
|
||||||
|
* i2c_conf_t to make it configurable */
|
||||||
|
scl_mode |= IOCON_MODE_PULLUP;
|
||||||
|
|
||||||
|
gpio_init_mux(conf->pin_sda, sda_mode);
|
||||||
|
gpio_init_mux(conf->pin_scl, scl_mode);
|
||||||
|
|
||||||
mutex_unlock(&locks[dev]);
|
mutex_unlock(&locks[dev]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _enable(I2C_Type *const i2c_dev)
|
||||||
|
{
|
||||||
|
i2c_dev->CFG = I2C_CFG_MSTEN_MASK;
|
||||||
|
while ((i2c_dev->STAT & I2C_STAT_MSTPENDING_MASK) == 0) {
|
||||||
|
/* I2C peripheral not yet available, spin more ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* I2C peripheral is online, check state is indeed idle */
|
||||||
|
assert((i2c_dev->STAT & I2C_STAT_MSTSTATE_MASK) == I2C_STAT_MSTSTATE_IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
void i2c_init(i2c_t dev)
|
void i2c_init(i2c_t dev)
|
||||||
{
|
{
|
||||||
assert(dev < I2C_NUMOF);
|
assert(dev < I2C_NUMOF);
|
||||||
@ -126,7 +168,7 @@ void i2c_init(i2c_t dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Enable controller mode, no timeout, no monitor, no clock stretching. */
|
/* Enable controller mode, no timeout, no monitor, no clock stretching. */
|
||||||
i2c_dev->CFG = I2C_CFG_MSTEN_MASK;
|
_enable(i2c_dev);
|
||||||
_i2c_controller_set_speed(i2c_dev, conf->speed);
|
_i2c_controller_set_speed(i2c_dev, conf->speed);
|
||||||
locks[dev] = (mutex_t)MUTEX_INIT_LOCKED;
|
locks[dev] = (mutex_t)MUTEX_INIT_LOCKED;
|
||||||
|
|
||||||
@ -192,18 +234,6 @@ static uint32_t _i2c_stop(I2C_Type *i2c_dev)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Definitions for MSTSTATE bits in I2C Status register STAT */
|
|
||||||
|
|
||||||
/* Controller Idle State Code */
|
|
||||||
#define I2C_STAT_MSTSTATE_IDLE (0)
|
|
||||||
/* Controller Receive Ready State Code */
|
|
||||||
#define I2C_STAT_MSTSTATE_RXREADY (1)
|
|
||||||
/* Controller Transmit Ready State Code */
|
|
||||||
#define I2C_STAT_MSTSTATE_TXREADY (2)
|
|
||||||
/* Controller NACK by peripheral on address State Code */
|
|
||||||
#define I2C_STAT_MSTSTATE_NACKADR (3)
|
|
||||||
/* Controller NACK by peripheral on data State Code */
|
|
||||||
#define I2C_STAT_MSTSTATE_NACKDAT (4)
|
|
||||||
|
|
||||||
static int _i2c_transfer_blocking(i2c_t dev, uint32_t addr_dir, uint8_t *data,
|
static int _i2c_transfer_blocking(i2c_t dev, uint32_t addr_dir, uint8_t *data,
|
||||||
size_t len, uint8_t flags)
|
size_t len, uint8_t flags)
|
||||||
|
Loading…
Reference in New Issue
Block a user