mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #12778 from GaborAbonyi/add_i2c_to_musca_b1
Add I2C api to Musca-B1 targetpull/12811/head
commit
4c08455125
|
@ -30,6 +30,11 @@ typedef enum {
|
|||
UART_1
|
||||
} UARTName;
|
||||
|
||||
typedef enum {
|
||||
I2C_0 = 0,
|
||||
I2C_1
|
||||
} I2CName;
|
||||
|
||||
#define STDIO_UART_TX UART1_TX
|
||||
#define STDIO_UART_RX UART1_RX
|
||||
#define STDIO_UART UART_1
|
||||
|
|
|
@ -86,6 +86,12 @@ typedef enum {
|
|||
LED2 = PA3,
|
||||
LED3 = PA4,
|
||||
|
||||
/* I2C pins */
|
||||
I2C0_SDA = PA14, /* Alternate Function - 1 */
|
||||
I2C0_SCL = PA15, /* Alternate Function - 1 */
|
||||
I2C1_SDA = PA18,
|
||||
I2C1_SCL = PA19,
|
||||
|
||||
/* Not connected */
|
||||
NC = (int)0xFFFFFFFF
|
||||
} PinName;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,647 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Arm Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file i2c_ip6510_drv.h
|
||||
* \brief Driver for IP6510 I2C controller.
|
||||
*/
|
||||
|
||||
#ifndef __I2C_IP6510_DRV_H__
|
||||
#define __I2C_IP6510_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief I2C (IP6510) device state types.
|
||||
*/
|
||||
enum i2c_ip6510_state_t {
|
||||
I2C_IP6510_UNINITIALIZED = 0u,
|
||||
I2C_IP6510_INITIALIZED = 1u,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief I2C (IP6510) bus state types.
|
||||
*/
|
||||
enum i2c_ip6510_bus_state_t {
|
||||
I2C_IP6510_BUS_INACTIVE = 0u,
|
||||
I2C_IP6510_BUS_ACTIVE = 1u,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Allowed transfer direction options.
|
||||
*/
|
||||
enum i2c_ip6510_transf_dir_t {
|
||||
I2C_IP6510_TRANSMITTER = 0u,
|
||||
I2C_IP6510_RECEIVER = 1u,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Supported I2C (IP6510) device mode options.
|
||||
*/
|
||||
enum i2c_ip6510_device_mode_t {
|
||||
I2C_IP6510_SLAVE_MODE = 0u,
|
||||
I2C_IP6510_MASTER_MODE = 1u,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Supported I2C (IP6510) addressing options.
|
||||
*/
|
||||
enum i2c_ip6510_addr_mode_t {
|
||||
I2C_IP6510_EXT_ADDR_MODE = 0u,
|
||||
I2C_IP6510_NOR_ADDR_MODE = 1u,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Supported I2C (IP6510) bus data rate options.
|
||||
*/
|
||||
enum i2c_ip6510_speed_t {
|
||||
I2C_IP6510_SPEED_100KHZ = 0u,
|
||||
I2C_IP6510_SPEED_400KHZ = 1u,
|
||||
I2C_IP6510_SPEED_MAX_SUPPORTED = 2u,
|
||||
};
|
||||
|
||||
#define I2C_IP6510_INTR_COMP_OFF (0u)
|
||||
/*!< Transfer complete interrupt bit field offset */
|
||||
#define I2C_IP6510_INTR_DATA_OFF (1u)
|
||||
/*!< More data interrupt bit field offset */
|
||||
#define I2C_IP6510_INTR_NACK_OFF (2u)
|
||||
/*!< Transfer not ACKed interrupt bit field offset */
|
||||
#define I2C_IP6510_INTR_TO_OFF (3u)
|
||||
/*!< Transfer time out interrupt bit field offset */
|
||||
#define I2C_IP6510_INTR_SLVRDY_OFF (4u)
|
||||
/*!< Monitored slave ready interrupt bit field offset */
|
||||
#define I2C_IP6510_INTR_RXOVF_OFF (5u)
|
||||
/*!< Receive overflow interrupt bit field offset */
|
||||
#define I2C_IP6510_INTR_TXOVF_OFF (6u)
|
||||
/*!< FIFO transmit overflow interrupt bit field offset */
|
||||
#define I2C_IP6510_INTR_RXUNF_OFF (7u)
|
||||
/*!< FIFO receive underflow interrupt bit field offset */
|
||||
#define I2C_IP6510_INTR_ARBLOST_OFF (9u)
|
||||
/*!< Arbitration lost interrupt bit field offset */
|
||||
|
||||
#define I2C_IP6510_ALL_INTR_MASK (0x2FFu)
|
||||
|
||||
/**
|
||||
* \brief I2C (IP6510) interrupt data structure
|
||||
*/
|
||||
enum i2c_ip6510_intr_t {
|
||||
I2C_IP6510_INTR_COMP_MASK = (0x1u<<I2C_IP6510_INTR_COMP_OFF),
|
||||
I2C_IP6510_INTR_DATA_MASK = (0x1u<<I2C_IP6510_INTR_DATA_OFF),
|
||||
I2C_IP6510_INTR_NACK_MASK = (0x1u<<I2C_IP6510_INTR_NACK_OFF),
|
||||
I2C_IP6510_INTR_TO_MASK = (0x1u<<I2C_IP6510_INTR_TO_OFF),
|
||||
I2C_IP6510_INTR_SLVRDY_MASK = (0x1u<<I2C_IP6510_INTR_SLVRDY_OFF),
|
||||
I2C_IP6510_INTR_RXOVF_MASK = (0x1u<<I2C_IP6510_INTR_RXOVF_OFF),
|
||||
I2C_IP6510_INTR_TXOVF_MASK = (0x1u<<I2C_IP6510_INTR_TXOVF_OFF),
|
||||
I2C_IP6510_INTR_RXUNF_MASK = (0x1u<<I2C_IP6510_INTR_RXUNF_OFF),
|
||||
I2C_IP6510_INTR_ARBLOST_MASK = (0x1u<<I2C_IP6510_INTR_ARBLOST_OFF),
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief I2C (IP6510) error enumeration types.
|
||||
*/
|
||||
enum i2c_ip6510_error_t {
|
||||
I2C_IP6510_ERR_NONE = 0u,
|
||||
I2C_IP6510_ERR_NOT_INIT = 1u,
|
||||
I2C_IP6510_ERR_ALREADY_INIT = 2u,
|
||||
I2C_IP6510_ERR_INVALID_ARG = 3u,
|
||||
I2C_IP6510_ERR_NACK = 4u,
|
||||
I2C_IP6510_ERR_RXOVF = 5u,
|
||||
I2C_IP6510_ERR_TXOVF = 6u,
|
||||
I2C_IP6510_ERR_RXUNF = 7u,
|
||||
I2C_IP6510_ERR_TIMEOUT = 8u,
|
||||
I2C_IP6510_ERR = 9u,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief I2C (IP6510) device configuration structure.
|
||||
*/
|
||||
struct i2c_ip6510_dev_cfg_t {
|
||||
const uint32_t base;
|
||||
/*!< I2C device base address */
|
||||
const enum i2c_ip6510_speed_t default_bus_speed;
|
||||
/*!< I2C bus data rate */
|
||||
const enum i2c_ip6510_device_mode_t default_mode;
|
||||
/*!< I2C device mode (Master/Slave) */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief I2C (IP6510) device data structure.
|
||||
*/
|
||||
struct i2c_ip6510_dev_data_t {
|
||||
enum i2c_ip6510_state_t state; /*!< I2C device state */
|
||||
enum i2c_ip6510_device_mode_t mode; /*!< I2C device mode (Master/Slave) */
|
||||
enum i2c_ip6510_speed_t bus_speed; /*!< I2C bus operational data rate */
|
||||
uint32_t sys_clk; /*!< System clock frequency */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief I2C (IP6510) device structure.
|
||||
*/
|
||||
struct i2c_ip6510_dev_t {
|
||||
const struct i2c_ip6510_dev_cfg_t* const cfg;
|
||||
/*!< I2C (IP6510) configuration structure */
|
||||
struct i2c_ip6510_dev_data_t* const data;
|
||||
/*!< I2C (IP6510) data structure */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initializes I2C (IP6510) device.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] sys_clk System clock frequency used by the device.
|
||||
*
|
||||
* It configures the interface as I2C Master with the default data rate
|
||||
* and disables every I2C interrupts.
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note This API should be called before calling any of the below I2C APIs.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_init(struct i2c_ip6510_dev_t* dev,
|
||||
uint32_t sys_clk);
|
||||
|
||||
/**
|
||||
* \brief Uninitializes I2C (IP6510) device and resets registers.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_uninit(struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables Hold mode.
|
||||
*
|
||||
* Sets hold bit, so the master does not terminate automatically a read or
|
||||
* write transfer.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_hold_enable(const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables Hold mode.
|
||||
*
|
||||
* Resets hold bit, so the master can terminate automatically a read or
|
||||
* write transfer.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_hold_disable(const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns the I2C (IP6510) device operational state.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return Returns the I2C (IP6510) device state \ref i2c_ip6510_state_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_state_t i2c_ip6510_get_state(
|
||||
const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns the I2C interface mode.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return Returns the I2C interface mode \ref i2c_ip6510_device_mode_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_device_mode_t i2c_ip6510_get_device_mode(
|
||||
const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets the I2C data rate.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] speed New I2C data rate \ref i2c_ip6510_speed_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note The I2C device should be in valid state before calling this API.
|
||||
* \ref i2c_ip6510_get_state should return I2C_IP6510_INITIALIZED.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_set_speed(struct i2c_ip6510_dev_t* dev,
|
||||
enum i2c_ip6510_speed_t speed);
|
||||
|
||||
/**
|
||||
* \brief Returns the actual I2C data rate.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return Returns the actual I2C data rate \ref i2c_ip6510_speed_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_speed_t i2c_ip6510_get_speed(
|
||||
const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns the state of the I2C bus.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return Returns the I2C bus state \ref i2c_ip6510_bus_state_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_bus_state_t i2c_ip6510_get_bus_status(
|
||||
const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns the transfer size registers value.
|
||||
*
|
||||
* Transfer size registers value contains:
|
||||
* Master transmitter mode: number of data bytes still not transmitted
|
||||
* minus one.
|
||||
* Master receiver mode: number of data bytes that are still expected
|
||||
* to be received.
|
||||
* Slave transmitter mode: number of bytes remaining in the FIFO after
|
||||
* the master terminates the transfer.
|
||||
* Slave receiver mode: number of valid data bytes in the FIFO.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return Returns the transfer size registers value.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
int i2c_ip6510_get_transfer_size(const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns the I2C interrupt status.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return The returned status value can be checked against values from
|
||||
* the \ref i2c_ip6510_intr_t type.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t i2c_ip6510_get_irq_status(const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns the I2C interrupt mask status.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return The returned mask value can be checked against values from
|
||||
* the \ref i2c_ip6510_intr_t type.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t i2c_ip6510_get_irq_mask(const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Clears the specified I2C interrupts.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] mask Bit mask for clearing interrupts. Values from
|
||||
* \ref i2c_ip6510_intr_t could be used to create the mask.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_clear_irq(struct i2c_ip6510_dev_t* dev, uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Enables the specified I2C interrupts.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] mask Bit mask for enabling interrupts. Values from
|
||||
* \ref i2c_ip6510_intr_t could be used to create the mask.
|
||||
*
|
||||
* \note User is responsible to configure the interrupt vector and
|
||||
* the interrupt controller.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_enable_irq(struct i2c_ip6510_dev_t* dev, uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Disables I2C interrupts.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] mask Bit mask for disabling interrupts. Values from
|
||||
* \ref i2c_ip6510_intr_t could be used to create the mask.
|
||||
*
|
||||
* \note User is responsible to configure the interrupt vector and
|
||||
* the interrupt controller.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_disable_irq(struct i2c_ip6510_dev_t* dev, uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Sets the time out interval.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] interval New time out interval in number of scl cycles minus one.
|
||||
*
|
||||
* \note The default time out interval is 0x20.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_set_timeout(struct i2c_ip6510_dev_t* dev,
|
||||
uint8_t interval);
|
||||
|
||||
/**
|
||||
* \brief Sets the pause interval in slave monitor mode.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] interval New pause interval in number of scl cycles minus one.
|
||||
*
|
||||
* \note The default pause interval is 0 (continuous monitoring).
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_set_slave_monitor_pause_interval(struct i2c_ip6510_dev_t* dev,
|
||||
uint8_t interval);
|
||||
|
||||
/**
|
||||
* \brief Returns the pause interval of slave monitor mode.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return Returns the pause interval of slave monitor mode
|
||||
* in number of scl cycles minus one.
|
||||
*
|
||||
* \note The default pause interval is 0 (continuous monitoring).
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint8_t i2c_ip6510_get_slave_monitor_pause_interval(
|
||||
struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets the length of the glitch filter.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] length New length of the glitch filter [0(min) ... 15(max)].
|
||||
*
|
||||
* \note If length of glitch filter is set to 0 then the glitch filter is
|
||||
* bypassed. The default glitch filter length is 0.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_set_glitch_filter_length(struct i2c_ip6510_dev_t* dev,
|
||||
uint32_t length);
|
||||
|
||||
/**
|
||||
* \brief Returns the length of the glitch filter.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return Returns the actual length of the glitch filter.
|
||||
*
|
||||
* \note The default glitch filter length is 0.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint8_t i2c_ip6510_get_glitch_filter_length(const struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief The I2C device monitors if addressed I2C slave is present on the bus.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] addr Address of the monitored I2C device (7 bits or 10 bits).
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
* Return value is I2C_IP6510_ERR_NONE if the addressed I2C slave is
|
||||
* present on the bus.
|
||||
*
|
||||
* \note The I2C interface should be in Master mode before calling this API,
|
||||
* for better performance the function doesn't check this,
|
||||
* \ref i2c_ip6510_get_device_mode should return I2C_IP6510_MASTER_MODE.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_monitor_slave(struct i2c_ip6510_dev_t* dev,
|
||||
uint16_t addr);
|
||||
|
||||
/**
|
||||
* \brief Writes data to I2C device.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] addr I2C device address (7 bits or 10 bits).
|
||||
* \param[in] tx_data Data buffer pointer to write.
|
||||
* \param[in] stop If false, master does not generate STOP symbol.
|
||||
* \param[in,out] tx_length Data buffer length (number of bytes to write).
|
||||
* On return: stores the number of bytes written.
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note The I2C interface should be in Master mode before calling this API,
|
||||
* for better performance the function doesn't check this,
|
||||
* \ref i2c_ip6510_get_device_mode should return I2C_IP6510_MASTER_MODE.
|
||||
* \note This function doesn't check if the pointers are NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_master_write(struct i2c_ip6510_dev_t* dev,
|
||||
uint16_t addr,
|
||||
const uint8_t* tx_data,
|
||||
bool stop,
|
||||
uint32_t* tx_length);
|
||||
|
||||
/**
|
||||
* \brief Reads data from I2C device.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] addr I2C device address (7 bits or 10 bits).
|
||||
* \param[in] rx_data Buffer pointer to store the read data.
|
||||
* \param[in] stop If false, master does not generate STOP symbol.
|
||||
* \param[in,out] rx_length Buffer length (number of bytes to read).
|
||||
* On return: stores the number of read bytes.
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note The I2C interface should be in Master mode before calling this API,
|
||||
* for better performance the function doesn't check this,
|
||||
* \ref i2c_ip6510_get_device_mode should return I2C_IP6510_MASTER_MODE.
|
||||
* \note This function doesn't check if the pointers are NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_master_read(struct i2c_ip6510_dev_t* dev,
|
||||
uint16_t addr,
|
||||
uint8_t* rx_data,
|
||||
bool stop,
|
||||
uint32_t* rx_length);
|
||||
|
||||
/**
|
||||
* \brief Writes to and reads from I2C device (combined transfer).
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] addr I2C device address (7 bits or 10 bits).
|
||||
* \param[in] tx_data Data buffer pointer to write.
|
||||
* \param[in] rx_data Buffer pointer to store the read data.
|
||||
* \param[in,out] tx_length Data buffer length (number of bytes to write).
|
||||
* On return: stores the number of bytes written.
|
||||
* \param[in,out] rx_length Buffer length (number of bytes to read).
|
||||
* On return: stores the number of read bytes.
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note The I2C interface should be in Master mode before calling this API,
|
||||
* for better performance the function doesn't check this,
|
||||
* \ref i2c_ip6510_get_device_mode should return I2C_IP6510_MASTER_MODE.
|
||||
* \note This function doesn't check if the pointers are NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_master_write_read(
|
||||
struct i2c_ip6510_dev_t* dev,
|
||||
uint16_t addr,
|
||||
const uint8_t* tx_data,
|
||||
uint8_t* rx_data,
|
||||
uint32_t* tx_length,
|
||||
uint32_t* rx_length);
|
||||
|
||||
/*
|
||||
* \brief Writes one byte to I2C device
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] addr Address to write to, accepts both 7 and 10 bit
|
||||
* addresses
|
||||
* \param[in] tx_data Data pointer to write.
|
||||
* \param[in] set_addr Set true for the first data byte. If true,
|
||||
* overwrites address register, starting a new
|
||||
* transaction. Set false for all following bytes in
|
||||
* the same transaction.
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_master_byte_write(
|
||||
const struct i2c_ip6510_dev_t* dev,
|
||||
uint16_t addr,
|
||||
const uint8_t* tx_data,
|
||||
bool set_addr);
|
||||
|
||||
/*
|
||||
* \brief Reads one byte from I2C device
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] addr Address to read from, accepts both 7 and 10 bit
|
||||
* addresses
|
||||
* \param[in] last_byte If true ends transmission on the next byte received
|
||||
* \param[in] set_addr Set true for the first data byte. If true,
|
||||
* overwrites address register, starting a new
|
||||
* transaction. Set false for all following bytes in
|
||||
* the same transaction.
|
||||
* \param[out] rx_data Data pointer to read to.
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_master_byte_read(
|
||||
const struct i2c_ip6510_dev_t* dev,
|
||||
uint16_t addr,
|
||||
bool last_byte,
|
||||
bool set_addr,
|
||||
uint8_t* rx_data);
|
||||
|
||||
/**
|
||||
* \brief Sets the I2C interface to be in slave mode with the given address.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] addr Unique identifying address of the I2C interface.
|
||||
*
|
||||
* It sets the I2C interface to be in slave mode with an address which
|
||||
* identifies the interface on the I2C bus and sets the appropriate I2C
|
||||
* data rate for the slave mode.
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_set_slave_mode(
|
||||
struct i2c_ip6510_dev_t* dev,
|
||||
uint16_t addr);
|
||||
|
||||
/**
|
||||
* \brief Sets the I2C interface to be in master mode
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* It only sets the I2C interface to be in master mode thus it will not answer
|
||||
* to further transfer requests.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void i2c_ip6510_set_master_mode(struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns the direction of the transmission received from the Master.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
*
|
||||
* \return Received direction of the transmission \ref i2c_ip6510_transf_dir_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum i2c_ip6510_transf_dir_t i2c_ip6510_get_slave_tranf_dir(
|
||||
struct i2c_ip6510_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sends data over the I2C bus to the Master.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] tx_data Data buffer pointer to write.
|
||||
* \param[in,out] tx_length Data buffer length (number of bytes to write).
|
||||
* On return: stores the number of bytes written.
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note This API should be called only if transmission request has been
|
||||
* received from the Master.
|
||||
* \note The I2C interface should be in Slave mode before calling this API,
|
||||
* for better performance the function doesn't check this,
|
||||
* \ref i2c_ip6510_get_device_mode should return I2C_IP6510_SLAVE_MODE.
|
||||
* \note This function doesn't check if the pointers are NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_slave_write(struct i2c_ip6510_dev_t* dev,
|
||||
const uint8_t* tx_data,
|
||||
uint32_t* tx_length);
|
||||
|
||||
/**
|
||||
* \brief Receives data from I2C Master.
|
||||
*
|
||||
* \param[in] dev I2C (IP6510) device structure \ref i2c_ip6510_dev_t
|
||||
* \param[in] rx_data Buffer pointer to store the read data.
|
||||
* \param[in,out] rx_length Buffer length (number of bytes to read), a system
|
||||
* known parameter or must be communicated in advance.
|
||||
* On return: stores the number of bytes read.
|
||||
*
|
||||
* \return Returns error code as specified in \ref i2c_ip6510_error_t
|
||||
*
|
||||
* \note This API should be called only if transmission request has been
|
||||
* received from the Master.
|
||||
* \note The I2C interface should be in Slave mode before calling this API,
|
||||
* for better performance the function doesn't check this,
|
||||
* \ref i2c_ip6510_get_device_mode should return I2C_IP6510_SLAVE_MODE.
|
||||
* \note This function doesn't check if the pointers are NULL.
|
||||
*/
|
||||
enum i2c_ip6510_error_t i2c_ip6510_slave_read(struct i2c_ip6510_dev_t* dev,
|
||||
uint8_t* rx_data,
|
||||
uint32_t* rx_length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __I2C_IP6510_DRV_H__ */
|
|
@ -0,0 +1,425 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2020 Arm Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "i2c_api.h"
|
||||
#include "mbed_error.h"
|
||||
#include "i2c_ip6510_drv.h"
|
||||
#include "objects.h"
|
||||
#include "pinmap.h"
|
||||
#include "PeripheralNames.h"
|
||||
|
||||
/* Return error codes for the i2c_byte_write api */
|
||||
#define BYTE_TRANSFER_ERR_NACK (0)
|
||||
#define BYTE_TRANSFER_ERR_NONE (1)
|
||||
#define BYTE_TRANSFER_ERR_TIMEOUT (2)
|
||||
|
||||
/* Macros for frequency configuration */
|
||||
#define I2C_SPEED_100KHZ (100000)
|
||||
#define I2C_SPEED_400KHZ (400000)
|
||||
|
||||
#if DEVICE_I2CSLAVE
|
||||
/* Return values for slave addressing specified in mbed I2C slave driver */
|
||||
#define I2C_SLAVE_READ_ADDRESS (1)
|
||||
#define I2C_SLAVE_WRITE_ALL_ADDRESS (2)
|
||||
#define I2C_SLAVE_WRITE_ADDRESS (3)
|
||||
#define I2C_SLAVE_NOT_ADDRESSED (0)
|
||||
#endif
|
||||
|
||||
extern const PinMap PinMap_I2C_SDA[];
|
||||
extern const PinMap PinMap_I2C_SCL[];
|
||||
|
||||
/* Extend the return values defined in i2c_api.h */
|
||||
enum {
|
||||
I2C_ERROR_NONE = 0,
|
||||
/* I2C_ERROR_NO_SLAVE = -1,
|
||||
* I2C_ERROR_BUS_BUSY = -2, */
|
||||
I2C_ERROR_GENERAL = -3
|
||||
};
|
||||
|
||||
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
||||
{
|
||||
enum i2c_ip6510_error_t ret;
|
||||
|
||||
/* Determine the I2C to use */
|
||||
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
|
||||
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
|
||||
I2CName i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
|
||||
if (i2c == (I2CName)NC) {
|
||||
error("I2C pinout mapping failed, invalid pins.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the parent object */
|
||||
switch (i2c) {
|
||||
#ifdef I2C0_IP6510_DEV
|
||||
case I2C_0:
|
||||
obj->dev = &I2C0_IP6510_DEV;
|
||||
break;
|
||||
#endif
|
||||
#ifdef I2C1_IP6510_DEV
|
||||
case I2C_1:
|
||||
obj->dev = &I2C1_IP6510_DEV;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error("Failed to initialize I2C, bad reference.");
|
||||
return;
|
||||
}
|
||||
obj->last_address = 0U;
|
||||
obj->sda = sda;
|
||||
obj->scl = scl;
|
||||
obj->byte_state = BYTE_TRANSFER_STATE_NONE;
|
||||
|
||||
/* If already init, uninit */
|
||||
if (i2c_ip6510_get_state(obj->dev) == I2C_IP6510_INITIALIZED) {
|
||||
i2c_ip6510_uninit(obj->dev);
|
||||
}
|
||||
|
||||
/* Set the GPIO pins */
|
||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
||||
|
||||
/* Initialize peripheral */
|
||||
ret = i2c_ip6510_init(obj->dev, SystemCoreClock);
|
||||
i2c_ip6510_set_speed(obj->dev, I2C_IP6510_SPEED_100KHZ);
|
||||
i2c_ip6510_set_timeout(obj->dev, 0xFFU);
|
||||
|
||||
if (ret != I2C_IP6510_ERR_NONE) {
|
||||
error("Failed to initialize I2C, error occured in native driver.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_frequency(i2c_t *obj, int hz)
|
||||
{
|
||||
/* The peripheral only supports 100k and 400k clock in master mode */
|
||||
switch (hz) {
|
||||
case I2C_SPEED_100KHZ:
|
||||
i2c_ip6510_set_speed(obj->dev, I2C_IP6510_SPEED_100KHZ);
|
||||
break;
|
||||
|
||||
case I2C_SPEED_400KHZ:
|
||||
i2c_ip6510_set_speed(obj->dev, I2C_IP6510_SPEED_400KHZ);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Invalid I2C frequency.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_reset(i2c_t *obj)
|
||||
{
|
||||
i2c_ip6510_uninit(obj->dev);
|
||||
i2c_init(obj, obj->sda, obj->scl);
|
||||
}
|
||||
|
||||
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
||||
{
|
||||
enum i2c_ip6510_error_t ret;
|
||||
|
||||
/* Shifted 8 bit address is used in upper layer */
|
||||
address = ((uint32_t)address)>>1;
|
||||
|
||||
ret = i2c_ip6510_master_read(obj->dev, (uint16_t)address, (uint8_t*)data,
|
||||
stop, (uint32_t*)(&length));
|
||||
|
||||
if (ret != I2C_IP6510_ERR_NONE) {
|
||||
return I2C_ERROR_GENERAL;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
||||
{
|
||||
enum i2c_ip6510_error_t ret;
|
||||
|
||||
/* Shifted 8 bit address is used in upper layer */
|
||||
address = ((uint32_t)address)>>1;
|
||||
|
||||
/* Parameter checking */
|
||||
if (data == NULL || length == 0) {
|
||||
ret = i2c_ip6510_monitor_slave(obj->dev, (uint16_t)address);
|
||||
if (ret != I2C_IP6510_ERR_NONE) {
|
||||
return I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
ret = i2c_ip6510_master_write(obj->dev, (uint16_t)address, (uint8_t*)data,
|
||||
stop, (uint32_t*)(&length));
|
||||
|
||||
if (ret != I2C_IP6510_ERR_NONE) {
|
||||
return I2C_ERROR_GENERAL;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
int i2c_start(i2c_t *obj)
|
||||
{
|
||||
/** \note The peripheral does not support building up the transaction by
|
||||
* instructions. The functionality is achieved with a software
|
||||
* state machine.
|
||||
* The i2c transaction is started later, when the address and the
|
||||
* first data byte is written.
|
||||
*/
|
||||
obj->byte_state = BYTE_TRANSFER_STATE_START;
|
||||
obj->last_address = 0U;
|
||||
i2c_ip6510_hold_enable(obj->dev);
|
||||
|
||||
return I2C_ERROR_NONE;
|
||||
}
|
||||
|
||||
int i2c_stop(i2c_t *obj)
|
||||
{
|
||||
/* Both the master and slave api calls this function */
|
||||
if (i2c_ip6510_get_device_mode(obj->dev) == I2C_IP6510_MASTER_MODE) {
|
||||
|
||||
/** \note The peripheral does not support building up the transaction by
|
||||
* instructions. The functionality is achieved with a software
|
||||
* state machine.
|
||||
* STOP condition is generated on hold disable.
|
||||
*/
|
||||
i2c_ip6510_hold_disable(obj->dev);
|
||||
|
||||
/* If there was only one byte written (the slave address) before calling
|
||||
* stop, the state machine is in ADDRESS state. Writing just the address
|
||||
* is equal to a slave monitoring
|
||||
*/
|
||||
if (obj->byte_state == BYTE_TRANSFER_STATE_ADDRESS) {
|
||||
/* Return value is not needed because signalling to the caller is
|
||||
* not defined
|
||||
*/
|
||||
(void)i2c_ip6510_monitor_slave(obj->dev, obj->last_address);
|
||||
}
|
||||
|
||||
obj->byte_state = BYTE_TRANSFER_STATE_NONE;
|
||||
obj->last_address = 0U;
|
||||
|
||||
} else {
|
||||
/* In slave mode the the I2C controller only writes and reads data from
|
||||
* the I2C bus. The function just clears the interrupts for
|
||||
* further adressing detection.
|
||||
*/
|
||||
i2c_ip6510_clear_irq(obj->dev, I2C_IP6510_ALL_INTR_MASK);
|
||||
}
|
||||
return I2C_ERROR_NONE;
|
||||
}
|
||||
|
||||
int i2c_byte_read(i2c_t *obj, int last)
|
||||
{
|
||||
uint8_t read_byte = 0U;
|
||||
uint32_t slave_read_cntr = 1U;
|
||||
|
||||
/* Both the master and slave api calls this function */
|
||||
if (i2c_ip6510_get_device_mode(obj->dev) == I2C_IP6510_MASTER_MODE) {
|
||||
|
||||
/** \note The peripheral does not support building up the transaction by
|
||||
* instructions. The functionality is achieved with a software
|
||||
* state machine.
|
||||
*/
|
||||
switch (obj->byte_state) {
|
||||
case BYTE_TRANSFER_STATE_ADDRESS:
|
||||
obj->byte_state = BYTE_TRANSFER_STATE_DATA;
|
||||
i2c_ip6510_master_byte_read(
|
||||
obj->dev, obj->last_address, last, true, &read_byte);
|
||||
return read_byte;
|
||||
|
||||
case BYTE_TRANSFER_STATE_DATA:
|
||||
i2c_ip6510_master_byte_read(
|
||||
obj->dev, obj->last_address, last, false, &read_byte);
|
||||
return read_byte;
|
||||
|
||||
case BYTE_TRANSFER_STATE_NONE:
|
||||
case BYTE_TRANSFER_STATE_START:
|
||||
default:
|
||||
/* Reading is invalid in these states */
|
||||
return I2C_ERROR_GENERAL;
|
||||
}
|
||||
} else {
|
||||
/* In slave mode the driver only writes and reads data from the
|
||||
* I2C controller, no need to track states.
|
||||
*/
|
||||
i2c_ip6510_slave_read(
|
||||
obj->dev, &read_byte, &slave_read_cntr);
|
||||
return read_byte;
|
||||
}
|
||||
}
|
||||
|
||||
int i2c_byte_write(i2c_t *obj, int data)
|
||||
{
|
||||
enum i2c_ip6510_error_t ret = I2C_IP6510_ERR_NONE;
|
||||
uint32_t slave_write_cntr = 1U;
|
||||
|
||||
/* Both the master and slave api calls this function */
|
||||
if (i2c_ip6510_get_device_mode(obj->dev) == I2C_IP6510_MASTER_MODE) {
|
||||
|
||||
/** \note The peripheral does not support building up the transaction by
|
||||
* instructions. The functionality is achieved with a software
|
||||
* state machine.
|
||||
*/
|
||||
switch (obj->byte_state) {
|
||||
case BYTE_TRANSFER_STATE_NONE:
|
||||
/* Writing is invalid before start symbol
|
||||
* BYTE_TRANSFER_ERR_TIMEOUT is the only error code mbed defines,
|
||||
* this is the only way to signal an error
|
||||
*/
|
||||
return BYTE_TRANSFER_ERR_TIMEOUT;
|
||||
|
||||
case BYTE_TRANSFER_STATE_START:
|
||||
obj->byte_state = BYTE_TRANSFER_STATE_ADDRESS;
|
||||
obj->last_address = ((uint32_t)data)>>1;
|
||||
return BYTE_TRANSFER_ERR_NONE;
|
||||
|
||||
case BYTE_TRANSFER_STATE_ADDRESS:
|
||||
obj->byte_state = BYTE_TRANSFER_STATE_DATA;
|
||||
ret = i2c_ip6510_master_byte_write(
|
||||
obj->dev, obj->last_address, (uint8_t*)&data, true);
|
||||
break;
|
||||
|
||||
case BYTE_TRANSFER_STATE_DATA:
|
||||
ret = i2c_ip6510_master_byte_write(
|
||||
obj->dev, obj->last_address, (uint8_t*)&data, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
return BYTE_TRANSFER_ERR_TIMEOUT;
|
||||
}
|
||||
} else {
|
||||
/* In slave mode the driver only writes and reads data from the
|
||||
* I2C controller, no need to track states.
|
||||
*/
|
||||
ret = i2c_ip6510_slave_write(
|
||||
obj->dev, (uint8_t*)&data, &slave_write_cntr);
|
||||
}
|
||||
|
||||
if (ret != I2C_IP6510_ERR_NONE) {
|
||||
/* No need to reset the state machine. The host might try to resend
|
||||
* the data byte. Also the start and stop functions reset the states.
|
||||
*/
|
||||
if (ret == I2C_IP6510_ERR_NACK) {
|
||||
return BYTE_TRANSFER_ERR_NACK;
|
||||
}
|
||||
return BYTE_TRANSFER_ERR_TIMEOUT;
|
||||
}
|
||||
return BYTE_TRANSFER_ERR_NONE;
|
||||
}
|
||||
|
||||
#if DEVICE_I2CSLAVE
|
||||
|
||||
void i2c_slave_mode(i2c_t *obj, int enable_slave)
|
||||
{
|
||||
if (!enable_slave) {
|
||||
/* Check if master mode is already set */
|
||||
if (i2c_ip6510_get_device_mode(obj->dev) != I2C_IP6510_MASTER_MODE) {
|
||||
/* Set Master Mode */
|
||||
i2c_ip6510_set_master_mode(obj->dev);
|
||||
}
|
||||
} else {
|
||||
/* Check if slave mode is already set */
|
||||
if (i2c_ip6510_get_device_mode(obj->dev) != I2C_IP6510_SLAVE_MODE) {
|
||||
/* Set Slave Mode */
|
||||
i2c_ip6510_set_slave_mode(obj->dev, obj->last_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i2c_slave_receive(i2c_t *obj)
|
||||
{
|
||||
uint32_t irq_status = i2c_ip6510_get_irq_status(obj->dev);
|
||||
enum i2c_ip6510_transf_dir_t dir = i2c_ip6510_get_slave_tranf_dir(obj->dev);
|
||||
uint32_t transfer_size = i2c_ip6510_get_transfer_size(obj->dev);
|
||||
|
||||
if (irq_status & I2C_IP6510_INTR_DATA_MASK) {
|
||||
|
||||
if (dir == I2C_IP6510_TRANSMITTER) {
|
||||
/* Slave is adressed for writing */
|
||||
return I2C_SLAVE_WRITE_ADDRESS;
|
||||
}
|
||||
if ((dir == I2C_IP6510_RECEIVER) && (transfer_size != 0U)) {
|
||||
/* Slave is adressed for reading */
|
||||
return I2C_SLAVE_READ_ADDRESS;
|
||||
}
|
||||
}
|
||||
|
||||
if ((irq_status & I2C_IP6510_INTR_COMP_MASK)
|
||||
&& (dir == I2C_IP6510_RECEIVER) && (transfer_size != 0U)) {
|
||||
/* An I2C transfer is complete with less then FIFO_SIZE-2 bytes */
|
||||
return I2C_SLAVE_READ_ADDRESS;
|
||||
}
|
||||
|
||||
return I2C_SLAVE_NOT_ADDRESSED;
|
||||
}
|
||||
|
||||
int i2c_slave_read(i2c_t *obj, char *data, int length)
|
||||
{
|
||||
enum i2c_ip6510_error_t ret;
|
||||
|
||||
ret = i2c_ip6510_slave_read(
|
||||
obj->dev, (uint8_t*)data, (uint32_t*)&length);
|
||||
i2c_ip6510_clear_irq(obj->dev, I2C_IP6510_ALL_INTR_MASK);
|
||||
|
||||
if (ret != I2C_IP6510_ERR_NONE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int i2c_slave_write(i2c_t *obj, const char *data, int length)
|
||||
{
|
||||
enum i2c_ip6510_error_t ret;
|
||||
|
||||
ret = i2c_ip6510_slave_write(
|
||||
obj->dev, (uint8_t*)data, (uint32_t*)&length);
|
||||
i2c_ip6510_clear_irq(obj->dev, I2C_IP6510_ALL_INTR_MASK);
|
||||
|
||||
if (ret != I2C_IP6510_ERR_NONE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
|
||||
{
|
||||
/* Shifted 8 bit address is used in upper layer */
|
||||
i2c_ip6510_set_slave_mode(obj->dev, ((uint16_t)address)>>1);
|
||||
obj->last_address = address>>1;
|
||||
}
|
||||
|
||||
const PinMap *i2c_slave_sda_pinmap()
|
||||
{
|
||||
return PinMap_I2C_SDA;
|
||||
}
|
||||
|
||||
const PinMap *i2c_slave_scl_pinmap()
|
||||
{
|
||||
return PinMap_I2C_SCL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const PinMap *i2c_master_sda_pinmap()
|
||||
{
|
||||
return PinMap_I2C_SDA;
|
||||
}
|
||||
|
||||
const PinMap *i2c_master_scl_pinmap()
|
||||
{
|
||||
return PinMap_I2C_SCL;
|
||||
}
|
|
@ -32,6 +32,16 @@
|
|||
#include "rtx_lib.h"
|
||||
|
||||
|
||||
const PinMap PinMap_I2C_SDA[] = {
|
||||
{I2C0_SDA, I2C_0, ALTERNATE_FUNC_1},
|
||||
{I2C1_SDA, I2C_1, PRIMARY_FUNC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_I2C_SCL[] = {
|
||||
{I2C0_SCL, I2C_0, ALTERNATE_FUNC_1},
|
||||
{I2C1_SCL, I2C_1, PRIMARY_FUNC}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Translates between different pin mode enums
|
||||
*
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -108,6 +108,12 @@
|
|||
#define GP_TIMER_FREQ_HZ 32768UL /* System Ref Clock */
|
||||
#define GP_TIMER_BIT_WIDTH 32U
|
||||
|
||||
/* I2C IP6510 */
|
||||
#define I2C0_IP6510_NS
|
||||
#define I2C0_IP6510_DEV I2C0_IP6510_DEV_NS
|
||||
#define I2C1_IP6510_NS
|
||||
#define I2C1_IP6510_DEV I2C1_IP6510_DEV_NS
|
||||
|
||||
/**
|
||||
* mbed usec high-resolution ticker configuration
|
||||
*/
|
||||
|
|
|
@ -54,6 +54,23 @@ struct trng_s {
|
|||
};
|
||||
#endif // DEVICE_TRNG
|
||||
|
||||
#if DEVICE_I2C || DEVICE_I2CSLAVE
|
||||
enum byte_transfer_states {
|
||||
BYTE_TRANSFER_STATE_NONE = 0,
|
||||
BYTE_TRANSFER_STATE_START,
|
||||
BYTE_TRANSFER_STATE_ADDRESS,
|
||||
BYTE_TRANSFER_STATE_DATA,
|
||||
};
|
||||
|
||||
struct i2c_s {
|
||||
struct i2c_ip6510_dev_t *dev;
|
||||
uint16_t last_address;
|
||||
PinName sda;
|
||||
PinName scl;
|
||||
enum byte_transfer_states byte_state;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8452,6 +8452,8 @@
|
|||
],
|
||||
"device_has_add": [
|
||||
"INTERRUPTIN",
|
||||
"I2C",
|
||||
"I2CSLAVE",
|
||||
"LPTICKER",
|
||||
"SERIAL",
|
||||
"SLEEP",
|
||||
|
|
Loading…
Reference in New Issue