openmv/lib/alif/Alif_CMSIS/Source/Driver_I2C.c
iabdalkader daf2bb30da misc: Restructure repo.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-13 08:28:34 +02:00

2129 lines
60 KiB
C

/* Copyright (C) 2023 Alif Semiconductor - All Rights Reserved.
* Use, distribution and modification of this code is permitted under the
* terms stated in the Alif Semiconductor Software License Agreement
*
* You should have received a copy of the Alif Semiconductor Software
* License Agreement with this file. If not, please write to:
* contact@alifsemi.com, or visit: https://alifsemi.com/license
*
*/
/* Includes */
#include <stddef.h>
#include <stdint.h>
#include "stdio.h"
/* system includes */
#include "Driver_I2C.h"
#include "Driver_I2C_Private.h"
#include "i2c.h"
/* Driver version */
#define ARM_I2C_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0)
/* Driver Version */
static const ARM_DRIVER_VERSION DriverVersion = {
ARM_I2C_API_VERSION,
ARM_I2C_DRV_VERSION
};
/* Driver Capabilities */
static const ARM_I2C_CAPABILITIES DriverCapabilities = {
1, /* supports 10-bit addressing */
0 /* reserved */
};
/**
* @brief get i2c version
* @note none
* @param none
* @retval driver version
*/
static ARM_DRIVER_VERSION ARM_I2C_GetVersion(void)
{
return DriverVersion;
}
/**
* @brief get i2c capabilites
* @note none
* @param none
* @retval driver capabilites
*/
static ARM_I2C_CAPABILITIES ARM_I2C_GetCapabilities(void)
{
return DriverCapabilities;
}
/**
* @brief Set i2c Target address
* @param I2C : Pointer to I2C resources structure
* @param addr : Target slave address
* @retval none
*/
static void I2C_SetTargetAddress(I2C_RESOURCES *I2C, const uint32_t addr)
{
/* addr is different from current target address */
if ((addr & (~ARM_I2C_ADDRESS_10BIT)) != I2C->tar_addr)
{
if(addr & ARM_I2C_ADDRESS_10BIT)
{
I2C->addr_mode = I2C_10BIT_ADDRESS;
}
else
{
I2C->addr_mode = I2C_7BIT_ADDRESS;
}
/* set target address */
i2c_set_target_addr(I2C->regs, addr, I2C->addr_mode, I2C->transfer.curr_stat);
I2C->tar_addr = (addr & (~ARM_I2C_ADDRESS_10BIT));
}
}
/**
* @brief get i2c bus speed
* @note implemented only ARM_I2C_BUS_SPEED_STANDARD
* @param I2C : Pointer to I2C resources structure
* @param i2c_bus_speed : i2c bus speed
* ARM_I2C_BUS_SPEED_STANDARD /
* ARM_I2C_BUS_SPEED_FAST /
* ARM_I2C_BUS_SPEED_FAST_PLUS
* @retval none
*/
static int32_t I2C_GetBusSpeed(I2C_RESOURCES *I2C, uint32_t i2c_bus_speed)
{
int32_t speed;
switch (i2c_bus_speed)
{
case ARM_I2C_BUS_SPEED_STANDARD:
/* Standard Speed (100kHz) */
speed = I2C_IC_CON_SPEED_STANDARD;
I2C->speed_mode = I2C_SPEED_STANDARD;
break;
case ARM_I2C_BUS_SPEED_FAST:
/* Fast Speed (400kHz) */
speed = I2C_IC_CON_SPEED_FAST;
I2C->speed_mode = I2C_SPEED_FAST;
break;
case ARM_I2C_BUS_SPEED_FAST_PLUS:
/* Fast+ Speed (1MHz) */
speed = I2C_IC_CON_SPEED_FAST;
I2C->speed_mode = I2C_SPEED_FASTPLUS;
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return speed;
}
#if I2C_DMA_ENABLE
/**
* @brief Initialises I2C DMA
* @param dma_periph : Pointer to DMA resources
* @retval execution_status
*/
__STATIC_INLINE int32_t I2C_DMA_Initialize(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Initializes DMA interface */
status = dma_drv->Initialize();
if(status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
* @brief PowerControls I2C DMA
* @param state : Power state
* @param dma_periph : Pointer to DMA resources
* @retval execution_status
*/
__STATIC_INLINE int32_t I2C_DMA_PowerControl(ARM_POWER_STATE state,
DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Controls power of DMA interface */
status = dma_drv->PowerControl(state);
if(status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
* @brief Allocate a channel for I2C
* @param dma_periph : Pointer to DMA resources
* @retval execution_status
*/
__STATIC_INLINE int32_t I2C_DMA_Allocate(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Allocate handle for peripheral */
status = dma_drv->Allocate(&dma_periph->dma_handle);
if(status)
{
return ARM_DRIVER_ERROR;
}
/* Enable the channel in the Event Router */
if(dma_periph->evtrtr_cfg.instance == 0)
{
evtrtr0_enable_dma_channel(dma_periph->evtrtr_cfg.channel,
dma_periph->evtrtr_cfg.group,
DMA_ACK_COMPLETION_PERIPHERAL);
evtrtr0_enable_dma_handshake(dma_periph->evtrtr_cfg.channel,
dma_periph->evtrtr_cfg.group);
}
else
{
evtrtrlocal_enable_dma_channel(dma_periph->evtrtr_cfg.channel,
DMA_ACK_COMPLETION_PERIPHERAL);
}
return ARM_DRIVER_OK;
}
/**
* @brief De-allocate a channel for I2C
* @param dma_periph : Pointer to DMA resources
* @retval execution_status
*/
__STATIC_INLINE int32_t I2C_DMA_DeAllocate(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* De-Allocate handle */
status = dma_drv->DeAllocate(&dma_periph->dma_handle);
if(status)
{
return ARM_DRIVER_ERROR;
}
/* Disable the channel in the Event Router */
if(dma_periph->evtrtr_cfg.instance == 0)
{
evtrtr0_disable_dma_channel(dma_periph->evtrtr_cfg.channel);
evtrtr0_disable_dma_handshake(dma_periph->evtrtr_cfg.channel,
dma_periph->evtrtr_cfg.group);
}
else
{
evtrtrlocal_disable_dma_channel(dma_periph->evtrtr_cfg.channel);
}
return ARM_DRIVER_OK;
}
/**
* @brief Start I2C DMA transfer
* @param dma_periph : Pointer to DMA resources
* @param dma_params : Pointer to DMA parameters
* @retval execution_status
*/
__STATIC_INLINE int32_t I2C_DMA_Start(DMA_PERIPHERAL_CONFIG *dma_periph,
ARM_DMA_PARAMS *dma_params)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Start transfer */
status = dma_drv->Start(&dma_periph->dma_handle, dma_params);
if(status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
* @brief Stop I2C DMA transfer
* @param dma_periph : Pointer to DMA resources
* @retval execution_status
*/
__STATIC_INLINE int32_t I2C_DMA_Stop(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Stop transfer */
status = dma_drv->Stop(&dma_periph->dma_handle);
if(status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
#endif /* I2C_DMA_ENABLE */
/**
* @brief CMSIS-Driver i2c initialize
* @note it will use interrupt method for data send and receive.
* @param cb_event : Pointer to \ref ARM_I2C_SignalEvent
* @param i2c : Pointer to i2c resources structure
* @retval ARM_DRIVER_OK : successfully initialized
*/
static int32_t ARM_I2C_Initialize(ARM_I2C_SignalEvent_t cb_event,
I2C_RESOURCES *I2C)
{
/* Driver is already initialized */
if (I2C->state.initialized == 1)
return ARM_DRIVER_OK;
/* default setting */
I2C->addr_mode = I2C_7BIT_ADDRESS;
I2C->tar_addr = I2C_0_TARADDR;
I2C->tar_addr &= I2C_7BIT_ADDRESS_MASK;
I2C->slv_addr &= I2C_7BIT_ADDRESS_MASK;
/* Disable device before init it */
i2c_disable(I2C->regs);
I2C->transfer.err_state = I2C_ERR_NONE;
I2C->transfer.next_cond = I2C_MODE_STOP;
I2C->transfer.tx_over = 0U;
I2C->transfer.rx_over = 0;
/* set the user callback event. */
I2C->cb_event = cb_event;
/* Get the SYST_PCLK */
I2C->clk = GetSystemAPBClock();
/* set the flag as initialized. */
I2C->state.initialized = 1;
#if I2C_DMA_ENABLE
if(I2C->dma_enable)
{
I2C->dma_cfg->dma_rx.dma_handle = -1;
I2C->dma_cfg->dma_tx.dma_handle = -1;
/* Initialize DMA for I2C-Tx */
if(I2C_DMA_Initialize(&I2C->dma_cfg->dma_tx) != ARM_DRIVER_OK)
return ARM_DRIVER_ERROR;
/* Initialize DMA for I2C-Rx */
if(I2C_DMA_Initialize(&I2C->dma_cfg->dma_rx) != ARM_DRIVER_OK)
return ARM_DRIVER_ERROR;
}
#endif
return ARM_DRIVER_OK;
}
/**
* @brief CMSIS-Driver i2c uninitialize
* @note none
* @param i2c : Pointer to i2c resources structure
* @retval ARM_DRIVER_OK : successfully uninitialized
*/
static int32_t ARM_I2C_Uninitialize(I2C_RESOURCES *I2C)
{
int ret = ARM_DRIVER_OK;
/* check i2c driver is initialized or not */
if (I2C->state.initialized == 0)
return ARM_DRIVER_OK;
/* check i2c driver is powered or not */
if (I2C->state.powered == 1)
return ARM_DRIVER_ERROR;
#if I2C_DMA_ENABLE
if(I2C->dma_enable)
{
I2C->dma_cfg->dma_rx.dma_handle = -1;
I2C->dma_cfg->dma_tx.dma_handle = -1;
}
#endif
i2c_disable(I2C->regs);
/* initialize all variables to 0 */
/* initialize the tx_buffer */
I2C->transfer.tx_buf = NULL;
I2C->transfer.tx_total_num = 0U;
I2C->transfer.tx_curr_cnt = 0U;
I2C->transfer.curr_cnt = 0U;
I2C->transfer.tx_over = 0U;
/* initialize the rx_buffer */
I2C->transfer.rx_buf = NULL;
I2C->transfer.rx_total_num = 0U;
I2C->transfer.rx_curr_cnt = 0U;
I2C->transfer.rx_curr_tx_index = 0U;
I2C->transfer.rx_over = 0U;
I2C->transfer.next_cond = I2C_MODE_STOP;
I2C->transfer.err_state = I2C_ERR_NONE;
I2C->transfer.curr_stat = I2C_TRANSFER_NONE;
/* Clear driver status \ref ARM_I2C_STATUS */
I2C->status.busy = 0U;
I2C->status.mode = 0U;
I2C->status.direction = 0U;
I2C->status.arbitration_lost = 0U;
I2C->status.bus_error = 0U;
I2C->addr_mode = I2C_7BIT_ADDRESS;
I2C->tar_addr = 0U;
/* Reset the flags. */
I2C->state.initialized = 0U;
return ret;
}
/**
* @func : CMSIS Driver I2C Power Control
* @brief : Power the driver and enable the NVIC
* @param : state : Power state
* @param : I2C : Pointer to i2c resources structure
* @return : ARM_DRIVER_OK
*/
static int32_t ARM_I2C_PowerControl(ARM_POWER_STATE state, I2C_RESOURCES *I2C)
{
switch (state)
{
case ARM_POWER_FULL:
/* check for Driver initialization */
if (I2C->state.initialized == 0)
{
return ARM_DRIVER_ERROR;
}
/* check for the power is done before initialization or not */
if (I2C->state.powered == 1)
{
return ARM_DRIVER_OK;
}
/* Disable all interrupts */
i2c_master_disable_tx_interrupt(I2C->regs);
i2c_master_disable_rx_interrupt(I2C->regs);
i2c_slave_disable_tx_interrupt(I2C->regs);
i2c_slave_disable_rx_interrupt(I2C->regs);
/* Clear Any Pending Irq */
NVIC_ClearPendingIRQ(I2C->irq_num);
/* Set Priority */
NVIC_SetPriority(I2C->irq_num, I2C->irq_priority);
/* Enable IRQ */
NVIC_EnableIRQ(I2C->irq_num);
i2c_set_tx_threshold(I2C->regs, I2C->tx_fifo_threshold);
i2c_set_rx_threshold(I2C->regs, I2C->rx_fifo_threshold);
#if I2C_DMA_ENABLE
if(I2C->dma_enable)
{
/* Power On DMA for I2C-Tx */
if(I2C_DMA_PowerControl(state, &I2C->dma_cfg->dma_tx) != ARM_DRIVER_OK)
return ARM_DRIVER_ERROR;
/* Power On DMA for I2C-Rx */
if(I2C_DMA_PowerControl(state, &I2C->dma_cfg->dma_rx) != ARM_DRIVER_OK)
return ARM_DRIVER_ERROR;
/* Allocate DMA Tx channel */
if(I2C_DMA_Allocate(&I2C->dma_cfg->dma_tx) == ARM_DRIVER_ERROR)
return ARM_DRIVER_ERROR;
/* Allocate DMA Rx channel */
if(I2C_DMA_Allocate(&I2C->dma_cfg->dma_rx) == ARM_DRIVER_ERROR)
return ARM_DRIVER_ERROR;
}
#endif
I2C->state.powered = 1;
break;
case ARM_POWER_OFF:
if (I2C->state.powered == 0)
{
return ARM_DRIVER_OK;
}
#if I2C_DMA_ENABLE
if(I2C->dma_enable)
{
i2c_disable_tx_dma(I2C->regs);
i2c_disable_rx_dma(I2C->regs);
/* Deallocate DMA Tx channel */
if(I2C_DMA_DeAllocate(&I2C->dma_cfg->dma_tx) == ARM_DRIVER_ERROR)
return ARM_DRIVER_ERROR;
/* Deallocate DMA Rx channel */
if(I2C_DMA_DeAllocate(&I2C->dma_cfg->dma_rx) == ARM_DRIVER_ERROR)
return ARM_DRIVER_ERROR;
/* Power Off DMA for I2C-Tx */
if(I2C_DMA_PowerControl(state, &I2C->dma_cfg->dma_tx) != ARM_DRIVER_OK)
return ARM_DRIVER_ERROR;
/* Power Off DMA for I2C-Rx */
if(I2C_DMA_PowerControl(state, &I2C->dma_cfg->dma_rx) != ARM_DRIVER_OK)
return ARM_DRIVER_ERROR;
}
#endif
/* Disabling interrupts */
if (I2C->mode == I2C_MASTER_MODE)
{
i2c_master_disable_tx_interrupt(I2C->regs);
i2c_master_disable_rx_interrupt(I2C->regs);
}
else
{
i2c_slave_disable_tx_interrupt(I2C->regs);
i2c_slave_disable_rx_interrupt(I2C->regs);
}
/* Disable the IRQ */
NVIC_DisableIRQ(I2C->irq_num);
/* Clearing pending */
NVIC_ClearPendingIRQ(I2C->irq_num);
I2C->state.powered = 0;
break;
case ARM_POWER_LOW:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}
/**
* @brief CMSIS-Driver i2c master transmit
* Start sending data to i2c transmitter.
* @note I2C_FLAG_MASTER_SETUP flag should be enabled first /ref ARM_I2C_BUS_SPEED
* @param data : Pointer to buffer with data to send to i2c transmitter
* @param num : Number of data items to send
* @param I2C : Pointer to i2c resources structure
* @param xfer_pending : Transfer operation is pending - Stop condition will not be
* generated
* @retval ARM_DRIVER_ERROR_PARAMETER : error in parameter
* @retval ARM_DRIVER_ERROR : error in driver
* @retval ARM_DRIVER_OK : success in interrupt case
* @retval ARM_DRIVER_ERROR_BUSY : driver busy in interrupt case
*/
static int32_t ARM_I2C_MasterTransmit(I2C_RESOURCES *I2C,
uint32_t addr,
const uint8_t *data,
uint32_t num,
bool xfer_pending)
{
#if I2C_DMA_ENABLE
ARM_DMA_PARAMS dma_params;
#endif
/* check i2c driver is initialized or not */
if (I2C->state.initialized == 0)
return ARM_DRIVER_ERROR;
/* check i2c driver is powered or not */
if (I2C->state.powered == 0)
return ARM_DRIVER_ERROR;
/* Error when RESTART is requested */
if (xfer_pending)
return ARM_DRIVER_ERROR_UNSUPPORTED;
/* addr 7bit addr: 0x7F , 10bit addr: 0x3FF */
if ((data == NULL) || (num == 0U) ||
((addr & (~ARM_I2C_ADDRESS_10BIT)) > 0x3FF))
{
/* Invalid parameters */
return ARM_DRIVER_ERROR_PARAMETER;
}
if (I2C->state.master_setup == 0U)
{
/* error master mode is not configured (mode not selected)
* master_setup should be enabled first \ref ARM_I2C_BUS_SPEED
*/
return ARM_DRIVER_ERROR;
}
if (I2C->status.busy)
{
/* Transfer operation in progress */
return ARM_DRIVER_ERROR_BUSY;
}
/* Update driver status \ref ARM_I2C_STATUS */
I2C->status.busy = 1;
I2C->status.mode = I2C_MASTER_MODE;
I2C->status.direction = I2C_DIR_TRANSMITTER;
I2C->status.arbitration_lost = 0;
I2C->status.bus_error = 0;
/* fill the I2C transfer structure as per user detail */
I2C->transfer.tx_curr_cnt = 0U;
I2C->transfer.curr_cnt = 0U;
I2C->transfer.tx_over = 0U;
I2C->transfer.curr_stat = I2C_TRANSFER_MST_TX;
I2C_SetTargetAddress(I2C, addr);
#if I2C_DMA_ENABLE
if(I2C->dma_enable)
{
/* Nullify Tx buf pointer, total num bytes and pending
* fields of I2C transfer structure */
I2C->transfer.tx_buf = (uint8_t *)NULL;
I2C->transfer.tx_total_num = 0U;
I2C->transfer.pending = false;
/* Start the DMA engine for sending the data to I2C */
dma_params.peri_reqno = (int8_t)I2C->dma_cfg->dma_tx.dma_periph_req;
dma_params.dir = ARM_DMA_MEM_TO_DEV;
dma_params.cb_event = I2C->dma_cb;
dma_params.src_addr = (const void*)data;
dma_params.dst_addr = i2c_get_data_addr(I2C->regs);
dma_params.num_bytes = (num * 2U);
dma_params.irq_priority = I2C->dma_irq_priority;
/* i2c TX/RX FIFO is 2-byte aligned */
dma_params.burst_size = BS_BYTE_2;
/* Max DMA burst length can be 16*/
if((32U - I2C->tx_fifo_threshold) > 16U)
{
dma_params.burst_len = 16U;
}
else
{
dma_params.burst_len = (32U - I2C->tx_fifo_threshold);
}
/* Prepare the I2C controller for DMA transmission */
i2c_enable_tx_dma(I2C->regs);
i2c_set_dma_tx_level(I2C->regs, dma_params.burst_len);
/* Start DMA transfer */
if(I2C_DMA_Start(&I2C->dma_cfg->dma_tx, &dma_params) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
i2c_enable_dma_master_tx(I2C->regs);
}
else
#endif
{
/* Update Tx buf pointer, total num bytes and pending
* fields of I2C transfer structure as per user detail */
I2C->transfer.tx_buf = (const uint8_t *)data;
I2C->transfer.tx_total_num = num;
/* Enabling the tx interrupt */
i2c_master_enable_tx_interrupt(I2C->regs);
}
return ARM_DRIVER_OK;
}
/**
* @brief CMSIS-Driver i2c master receive
* Start receiving data from i2c receiver.
* @note none
* @param data : Pointer to buffer for data to receive from i2c receiver
* @param addr : Target slave address
* @param num : Number of data items to receive
* @param I2C : Pointer to i2c resources structure
* @param xfer_pending : Transfer operation is pending - Stop condition will not be
* generated
* @retval ARM_DRIVER_ERROR_PARAMETER : error in parameter
* @retval ARM_DRIVER_ERROR : error in driver
* @retval ARM_DRIVER_OK : success in interrupt case
* @retval ARM_DRIVER_ERROR_BUSY : driver busy in interrupt case
*/
static int32_t ARM_I2C_MasterReceive(I2C_RESOURCES *I2C,
uint32_t addr,
uint8_t *data,
uint32_t num,
bool xfer_pending)
{
#if I2C_DMA_ENABLE
ARM_DMA_PARAMS dma_params;
#endif
/* check i2c driver is initialized or not */
if (I2C->state.initialized == 0)
return ARM_DRIVER_ERROR;
/* check i2c driver is powered or not */
if (I2C->state.powered == 0)
return ARM_DRIVER_ERROR;
/* Error when RESTART is requested */
if (xfer_pending)
return ARM_DRIVER_ERROR_UNSUPPORTED;
/* addr 7bit addr: 0x7F , 10bit addr: 0x3FF */
if ((data == NULL) || (num == 0U) || ((addr & (~ARM_I2C_ADDRESS_10BIT)) > 0x3FF))
{
/* Invalid parameters */
return ARM_DRIVER_ERROR_PARAMETER;
}
if (I2C->state.master_setup == 0U)
{
/* error master mode is not configured (mode not selected)
* master_setup should be enabled first \ref ARM_I2C_BUS_SPEED
*/
return ARM_DRIVER_ERROR;
}
if (I2C->status.busy)
{
/* Transfer operation in progress */
return ARM_DRIVER_ERROR_BUSY;
}
/* Update driver status \ref ARM_I2C_STATUS */
I2C->status.busy = 1;
I2C->status.mode = I2C_MASTER_MODE;
I2C->status.direction = I2C_DIR_RECEIVER;
I2C->status.arbitration_lost = 0;
I2C->status.bus_error = 0;
/* fill the i2c transfer structure as per user detail */
I2C->transfer.rx_buf = (uint8_t *)data;
I2C->transfer.rx_total_num = num;
I2C->transfer.rx_curr_cnt = 0U;
I2C->transfer.curr_cnt = 0U;
I2C->transfer.rx_curr_tx_index = 0U;
I2C->transfer.rx_over = 0U;
I2C->transfer.curr_stat = I2C_TRANSFER_MST_RX;
I2C_SetTargetAddress(I2C, addr);
#if I2C_DMA_ENABLE
/* Check if DMA is enabled for this */
if (I2C->dma_enable)
{
/* Start the DMA engine for sending the data to I2C */
dma_params.peri_reqno = (int8_t)I2C->dma_cfg->dma_rx.dma_periph_req;
dma_params.dir = ARM_DMA_DEV_TO_MEM;
dma_params.cb_event = I2C->dma_cb;
dma_params.src_addr = i2c_get_data_addr(I2C->regs);
dma_params.dst_addr = (void*)data;
dma_params.num_bytes = (num * 2U);
dma_params.irq_priority = I2C->dma_irq_priority;
/* i2c TX/RX FIFO is 2-byte aligned */
dma_params.burst_size = BS_BYTE_2;
/* Maximum DMA Rx burst length can be 1*/
dma_params.burst_len = 1U;
i2c_enable_rx_dma(I2C->regs);
i2c_set_dma_rx_level(I2C->regs, (dma_params.burst_len - 1U));
/* Start DMA transfer */
if(I2C_DMA_Start(&I2C->dma_cfg->dma_rx, &dma_params) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
i2c_enable_dma_master_rx(I2C->regs);
}
else
#endif
{
/* Enabling the rx interrupt */
i2c_master_enable_rx_interrupt(I2C->regs);
}
return ARM_DRIVER_OK;
}
/**
* @brief CMSIS-Driver i2c slave transmit
* Start sending data to i2c master.
* @note master_setup bit should be enabled first /ref ARM_I2C_BUS_SPEED
* @param addr : Target slave address
* @param data : Pointer to buffer with data to send to i2c master
* @param num : Number of data items to send
* @param I2C : Pointer to i2c resources structure
* @retval ARM_DRIVER_ERROR_PARAMETER : error in parameter
* @retval ARM_DRIVER_ERROR : error in driver
* @retval ARM_DRIVER_OK : success in interrupt case
* @retval ARM_DRIVER_ERROR_BUSY : driver busy in interrupt case
* @retval transmit count : For data transmit count /ref ARM_I2C_GetDataCount
*/
static int32_t ARM_I2C_SlaveTransmit(I2C_RESOURCES *I2C,
const uint8_t *data,
uint32_t num)
{
#if I2C_DMA_ENABLE
ARM_DMA_PARAMS dma_params;
#endif
/* check i2c driver is initialized or not */
if (I2C->state.initialized == 0)
return ARM_DRIVER_ERROR;
/* check i2c driver is powered or not */
if (I2C->state.powered == 0)
return ARM_DRIVER_ERROR;
if((data == NULL) || (num == 0U))
return ARM_DRIVER_ERROR_PARAMETER;
/* Check Slave mode is enabled */
if (I2C->state.slave_setup == 0U)
{
/* error master mode is not configured (mode not selected)
* master_setup should be enabled first \ref ARM_I2C_BUS_SPEED
*/
return ARM_DRIVER_ERROR;
}
if (I2C->status.busy)
{
/* Transfer operation in progress */
return ARM_DRIVER_ERROR_BUSY;
}
/* Update driver status \ref ARM_I2C_STATUS */
I2C->status.busy = 1;
I2C->status.mode = I2C_SLAVE_MODE;
I2C->status.direction = I2C_DIR_TRANSMITTER;
I2C->status.arbitration_lost = 0;
I2C->status.bus_error = 0;
/* fill the i2c transfer structure as per user detail */
I2C->transfer.tx_curr_cnt = 0U;
I2C->transfer.curr_cnt = 0U;
I2C->transfer.tx_over = 0U;
I2C->transfer.curr_stat = I2C_TRANSFER_SLV_TX;
#if I2C_DMA_ENABLE
if(I2C->dma_enable)
{
/* Nullify Tx buf pointer and total num bytes
* of I2C transfer structure */
I2C->transfer.tx_buf = (uint8_t *)NULL;
I2C->transfer.tx_total_num = 0U;
/* Start the DMA engine for sending the data to I2C */
dma_params.peri_reqno = (int8_t)I2C->dma_cfg->dma_tx.dma_periph_req;
dma_params.dir = ARM_DMA_MEM_TO_DEV;
dma_params.cb_event = I2C->dma_cb;
dma_params.src_addr = (const void*)data;
dma_params.dst_addr = i2c_get_data_addr(I2C->regs);
dma_params.num_bytes = (num * 2U);
dma_params.irq_priority = I2C->dma_irq_priority;
/* i2c TX/RX FIFO is 2-byte aligned */
dma_params.burst_size = BS_BYTE_2;
/* Max DMA burst length can be 16*/
if((32U - I2C->tx_fifo_threshold) > 16U)
{
dma_params.burst_len = 16U;
}
else
{
dma_params.burst_len = (32U - I2C->tx_fifo_threshold);
}
/* Prepare the I2C controller for DMA transmission */
i2c_enable_tx_dma(I2C->regs);
i2c_set_dma_tx_level(I2C->regs, dma_params.burst_len);
/* Start DMA transfer */
if(I2C_DMA_Start(&I2C->dma_cfg->dma_tx, &dma_params) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
i2c_enable_dma_slave_tx(I2C->regs);
}
else
#endif
{
/* Update Tx buf pointer and total num bytes
* of I2C transfer structure as per user detail */
I2C->transfer.tx_buf = (const uint8_t *)data;
I2C->transfer.tx_total_num = num;
/* Enabling the tx interrupt */
i2c_slave_enable_tx_interrupt(I2C->regs);
}
return ARM_DRIVER_OK;
}
/**
* @brief CMSIS-Driver i2c slave receive
* Start receiving data from i2c master.
* @note none
* @param data : Pointer to buffer for data to receive from i2c master
* @param num : Number of data items to receive
* @param I2C : Pointer to i2c resources structure
* @retval ARM_DRIVER_ERROR_PARAMETER : error in parameter
* @retval ARM_DRIVER_ERROR : error in driver
* @retval ARM_DRIVER_OK : success in interrupt case
* @retval ARM_DRIVER_ERROR_BUSY : driver busy in interrupt case
* @retval received count : For data receive count /ref ARM_I2C_GetDataCount
*/
static int32_t ARM_I2C_SlaveReceive(I2C_RESOURCES *I2C,
uint8_t *data,
uint32_t num)
{
#if I2C_DMA_ENABLE
ARM_DMA_PARAMS dma_params;
#endif
/* check i2c driver is initialized or not */
if (I2C->state.initialized == 0)
return ARM_DRIVER_ERROR;
/* check i2c driver is powered or not */
if (I2C->state.powered == 0)
return ARM_DRIVER_ERROR;
if((data == NULL) || (num == 0U))
return ARM_DRIVER_ERROR_PARAMETER;
/* Check Slave mode is enabled */
if (I2C->state.slave_setup == 0U)
{
/* error master mode is not configured (mode not selected)
* master_setup should be enabled first \ref ARM_I2C_BUS_SPEED
*/
return ARM_DRIVER_ERROR;
}
if (I2C->status.busy)
{
/* Transfer operation in progress */
return ARM_DRIVER_ERROR_BUSY;
}
/* Update driver status \ref ARM_I2C_STATUS */
I2C->status.busy = 1;
I2C->status.mode = I2C_SLAVE_MODE;
I2C->status.direction = I2C_DIR_RECEIVER;
I2C->status.bus_error = 0;
/* fill the i2c transfer structure as per user detail */
I2C->transfer.rx_curr_cnt = 0U;
I2C->transfer.curr_cnt = 0U;
I2C->transfer.curr_stat = I2C_TRANSFER_SLV_RX;
I2C->transfer.rx_over = 0U;
#if I2C_DMA_ENABLE
if(I2C->dma_enable)
{
/* Nullify Rx buf pointer and total num bytes
* of I2C transfer structure */
I2C->transfer.rx_buf = (uint8_t *)NULL;
I2C->transfer.rx_total_num = 0U;
/* Start the DMA engine for sending the data to I2C */
dma_params.peri_reqno = (int8_t)I2C->dma_cfg->dma_rx.dma_periph_req;
dma_params.dir = ARM_DMA_DEV_TO_MEM;
dma_params.cb_event = I2C->dma_cb;
dma_params.src_addr = i2c_get_data_addr(I2C->regs);
dma_params.dst_addr = (void*)data;
dma_params.num_bytes = (num * 2);
dma_params.irq_priority = I2C->dma_irq_priority;
/* i2c TX/RX FIFO is 2-byte aligned */
dma_params.burst_size = BS_BYTE_2;
/* Maximum DMA Rx burst length can be 1*/
dma_params.burst_len = 1U;
i2c_enable_rx_dma(I2C->regs);
i2c_set_dma_rx_level(I2C->regs, (dma_params.burst_len - 1U));
/* Start DMA transfer */
if(I2C_DMA_Start(&I2C->dma_cfg->dma_rx, &dma_params) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
i2c_enable_dma_slave_rx(I2C->regs);
}
else
#endif
{
/* Update Rx buf pointer and total num bytes
* of I2C transfer structure as per user detail */
I2C->transfer.rx_buf = (uint8_t *)data;
I2C->transfer.rx_total_num = num;
/* Enabling the rx interrupt */
i2c_slave_enable_rx_interrupt(I2C->regs);
}
return ARM_DRIVER_OK;
}
/**
* @brief CMSIS-Driver i2c get transfer data count
* @note it can be either transmit or receive data count which perform last
* (useful only in interrupt mode)
* @param I2C : Pointer to i2c resources structure
* @retval transfer data count
*/
static int32_t ARM_I2C_GetDataCount(const I2C_RESOURCES *I2C)
{
/* return common count for both tx/rx */
return ((int32_t)I2C->transfer.curr_cnt);
}
/**
* @brief CMSIS-Driver i2c control
* Control i2c Interface.
* @note none
* @param control : Operation
* @param arg : Argument of operation (optional)
* @param I2C : Pointer to i2c resources structure
* @retval common \ref execution_status and driver specific \ref i2c_execution_status
*/
static int32_t ARM_I2C_Control(I2C_RESOURCES *I2C,
uint32_t control,
uint32_t arg)
{
int32_t speed;
/* check i2c driver is initialized or not */
if (I2C->state.initialized == 0)
return ARM_DRIVER_ERROR;
/* check i2c driver is powered or not */
if (I2C->state.powered == 0)
return ARM_DRIVER_ERROR;
switch (control)
{
case ARM_I2C_OWN_ADDRESS:
speed = I2C_GetBusSpeed(I2C, ARM_I2C_BUS_SPEED_STANDARD);
if(arg & ARM_I2C_ADDRESS_10BIT)
{
/* Sets 10 bit addr mode */
I2C->addr_mode = I2C_10BIT_ADDRESS;
}
else
{
/* Sets 7 bit addr mode */
I2C->addr_mode = I2C_7BIT_ADDRESS;
}
i2c_slave_init(I2C->regs, arg, I2C->addr_mode);
/* Sets bus speed*/
i2c_set_bus_speed(I2C->regs, speed);
I2C->mode = I2C_SLAVE_MODE;
/* setup slave flag */
I2C->state.slave_setup = 1;
break;
case ARM_I2C_BUS_SPEED:
speed = I2C_GetBusSpeed(I2C, arg);
/* arg is i2c bus speed */
i2c_master_init(I2C->regs, I2C->tar_addr);
/* Sets master clock settings*/
i2c_master_set_clock(I2C->regs, (I2C->clk / 1000), I2C->speed_mode);
/* Sets bus speed*/
i2c_set_bus_speed(I2C->regs, speed);
I2C->mode = I2C_MASTER_MODE;
/* setup master flag */
I2C->state.master_setup = 1;
break;
case ARM_I2C_BUS_CLEAR:
/* disable device, clear all the interrupt, enable device. */
i2c_disable(I2C->regs);
i2c_clear_all_interrupt(I2C->regs);
I2C->transfer.next_cond = I2C_MODE_STOP;
I2C->transfer.curr_stat = I2C_TRANSFER_NONE;
I2C->transfer.err_state = I2C_ERR_NONE;
I2C->transfer.tx_over = 0U;
I2C->transfer.rx_over = 0U;
i2c_enable(I2C->regs);
break;
case ARM_I2C_ABORT_TRANSFER:
#if I2C_DMA_ENABLE
if (I2C->dma_enable)
{
/* Transmit mode */
if (I2C->status.direction == I2C_DIR_TRANSMITTER)
{
if (I2C_DMA_Stop(&I2C->dma_cfg->dma_tx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
/* Reception mode */
else if(I2C->status.direction == I2C_DIR_RECEIVER)
{
if (I2C_DMA_Stop(&I2C->dma_cfg->dma_rx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
i2c_disable_tx_dma(I2C->regs);
i2c_disable_rx_dma(I2C->regs);
}
#endif
/* only useful in interrupt method,
* no effect on polling method.
*/
/* i2c is half-duplex, at a time it can be either tx or rx
* not sure which one is running, so clearing both. */
/* if tx interrupt flag is enable then only disable transmit interrupt */
if (I2C->mode == I2C_MASTER_MODE)
{
i2c_master_disable_tx_interrupt(I2C->regs);
}
else
{
i2c_slave_disable_tx_interrupt(I2C->regs);
}
if (I2C->mode == I2C_MASTER_MODE)
{
i2c_master_disable_rx_interrupt(I2C->regs);
}
else
{
i2c_slave_disable_rx_interrupt(I2C->regs);
}
/* Reset the tx_buffer */
I2C->transfer.tx_total_num = 0U;
I2C->transfer.rx_total_num = 0U;
I2C->transfer.curr_stat = I2C_TRANSFER_NONE;
/* clear busy status bit. */
I2C->status.busy = 0U;
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}
/**
* @brief CMSIS-Driver i2c get status
* @note none
* @param I2C : Pointer to i2c resources structure
* @retval ARM_i2c_STATUS
*/
static ARM_I2C_STATUS ARM_I2C_GetStatus(const I2C_RESOURCES *I2C)
{
return I2C->status;
}
#if I2C_DMA_ENABLE
/**
* @brief Callback function from DMA for I2C
* @param event : Event from DMA
* @param peri_num : Peripheral number
* @param I2C : Pointer to I2C resources
* @retval execution_status
*/
static void I2C_DMACallback(uint32_t event, int8_t peri_num,
I2C_RESOURCES *I2C)
{
(void)peri_num;
if(!I2C->cb_event)
return;
/* Abort Occurred */
if(event & ARM_DMA_EVENT_ABORT)
{
I2C->cb_event(ARM_I2C_EVENT_TRANSFER_INCOMPLETE);
}
}
#endif
/* I2C0 Driver Instance */
#if (RTE_I2C0)
#if RTE_I2C0_DMA_ENABLE
static void I2C0_DMACallback(uint32_t event, int8_t peri_num);
static I2C_DMA_HW_CONFIG I2C0_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(I2C0_DMA),
.dma_periph_req = I2C0_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = I2C0_DMA,
.group = I2C0_DMA_GROUP,
.channel = I2C0_DMA_RX_PERIPH_REQ,
.enable_handshake = I2C0_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(I2C0_DMA),
.dma_periph_req = I2C0_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = I2C0_DMA,
.group = I2C0_DMA_GROUP,
.channel = I2C0_DMA_TX_PERIPH_REQ,
.enable_handshake = I2C0_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
/* I2C0 Driver Resources */
static I2C_RESOURCES I2C0_RES =
{
.regs = (I2C_Type *)I2C0_BASE,
.irq_num = (IRQn_Type)I2C0_IRQ_IRQn,
.irq_priority = (uint32_t)RTE_I2C0_IRQ_PRIORITY,
#if RTE_I2C0_DMA_ENABLE
.dma_enable = RTE_I2C0_DMA_ENABLE,
.dma_irq_priority = RTE_I2C0_DMA_IRQ_PRI,
.dma_cb = I2C0_DMACallback,
.dma_cfg = &I2C0_DMA_HW_CONFIG,
#endif
.tx_fifo_threshold = RTE_I2C0_TX_FIFO_THRESHOLD,
.rx_fifo_threshold = RTE_I2C0_RX_FIFO_THRESHOLD
};
static int32_t I2C0_Initialize(ARM_I2C_SignalEvent_t cb_event)
{
return ARM_I2C_Initialize(cb_event, &I2C0_RES);
}
static int32_t I2C0_Uninitialize(void)
{
return ARM_I2C_Uninitialize(&I2C0_RES);
}
static int32_t I2C0_PowerControl(ARM_POWER_STATE state)
{
return ARM_I2C_PowerControl(state, &I2C0_RES);
}
static int32_t I2C0_MasterTransmit(uint32_t addr, const uint8_t *data,
uint32_t num, bool xfer_pending)
{
return ARM_I2C_MasterTransmit(&I2C0_RES, addr, data, num, xfer_pending);
}
static int32_t I2C0_MasterReceive(uint32_t addr, uint8_t *data,
uint32_t num, bool xfer_pending)
{
return (ARM_I2C_MasterReceive(&I2C0_RES, addr, data, num, xfer_pending));
}
static int32_t I2C0_SlaveTransmit(const uint8_t *data, uint32_t num)
{
return (ARM_I2C_SlaveTransmit(&I2C0_RES, data, num));
}
static int32_t I2C0_SlaveReceive(uint8_t *data, uint32_t num)
{
return (ARM_I2C_SlaveReceive(&I2C0_RES, data, num));
}
static int32_t I2C0_GetDataCount(void)
{
return (ARM_I2C_GetDataCount(&I2C0_RES));
}
static int32_t I2C0_Control(uint32_t control, uint32_t arg)
{
return (ARM_I2C_Control(&I2C0_RES, control, arg));
}
static ARM_I2C_STATUS I2C0_GetStatus(void)
{
return (ARM_I2C_GetStatus(&I2C0_RES));
}
void I2C0_IRQHandler(void)
{
i2c_transfer_info_t *transfer = &(I2C0_RES.transfer);
ARM_I2C_STATUS *i2c_stat = &(I2C0_RES.status);
/* Check for master mode */
if (I2C0_RES.mode == I2C_MASTER_MODE)
{
if (transfer->curr_stat == I2C_TRANSFER_MST_TX)
{
/* Master transmit*/
i2c_master_tx_isr(I2C0_RES.regs, transfer);
}
if(transfer->curr_stat == I2C_TRANSFER_MST_RX)
{
/* Master receive */
i2c_master_rx_isr(I2C0_RES.regs, transfer);
}
}
else /* Slave mode */
{
if(transfer->curr_stat == I2C_TRANSFER_SLV_TX)
{
/* slave transmit*/
i2c_slave_tx_isr(I2C0_RES.regs, transfer);
}
if(transfer->curr_stat == I2C_TRANSFER_SLV_RX)
{
/* slave receive */
i2c_slave_rx_isr(I2C0_RES.regs, transfer);
}
}/* Slave mode */
/* Check the ISR response */
if (transfer->status & I2C_TRANSFER_STATUS_DONE)
{
/* set busy flag to 0U */
i2c_stat->busy = 0U;
I2C0_RES.cb_event(ARM_I2C_EVENT_TRANSFER_DONE);
}
else if (transfer->status & I2C_TRANSFER_STATUS_GENERAL_CALL)
{
I2C0_RES.cb_event(ARM_I2C_EVENT_GENERAL_CALL);
}
else if (transfer->status & I2C_TRANSFER_STATUS_BUS_CLEAR)
{
I2C0_RES.cb_event(ARM_I2C_EVENT_BUS_CLEAR);
}
else
{
#if RTE_I2C0_DMA_ENABLE
if(I2C0_RES.status.direction == I2C_DIR_TRANSMITTER)
{
I2C_DMA_Stop(&I2C0_RES.dma_cfg->dma_tx);
}
else
{
I2C_DMA_Stop(&I2C0_RES.dma_cfg->dma_rx);
}
/* set busy flag to 0U */
i2c_stat->busy = 0U;
#endif
if (transfer->status & I2C_TRANSFER_STATUS_SLAVE_TRANSMIT)
{
I2C0_RES.cb_event(ARM_I2C_EVENT_SLAVE_TRANSMIT);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_SLAVE_RECEIVE)
{
I2C0_RES.cb_event(ARM_I2C_EVENT_SLAVE_RECEIVE);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_ADDRESS_NACK)
{
I2C0_RES.cb_event(ARM_I2C_EVENT_ADDRESS_NACK);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_ARBITRATION_LOST)
{
i2c_stat->arbitration_lost = 1U;
I2C0_RES.cb_event(ARM_I2C_EVENT_ARBITRATION_LOST);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_BUS_ERROR)
{
i2c_stat->bus_error = 1U;
I2C0_RES.cb_event(ARM_I2C_EVENT_BUS_ERROR);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_INCOMPLETE)
{
I2C0_RES.cb_event(ARM_I2C_EVENT_TRANSFER_INCOMPLETE);
i2c_stat->busy = 0U;
}
}
transfer->status = I2C_TRANSFER_STATUS_NONE;
}
#if RTE_I2C0_DMA_ENABLE
static void I2C0_DMACallback(uint32_t event, int8_t peri_num)
{
I2C_DMACallback(event, peri_num, &I2C0_RES);
}
#endif
/* I2C0 Driver Control Block */
extern ARM_DRIVER_I2C Driver_I2C0;
ARM_DRIVER_I2C Driver_I2C0 = {
ARM_I2C_GetVersion,
ARM_I2C_GetCapabilities,
I2C0_Initialize,
I2C0_Uninitialize,
I2C0_PowerControl,
I2C0_MasterTransmit,
I2C0_MasterReceive,
I2C0_SlaveTransmit,
I2C0_SlaveReceive,
I2C0_GetDataCount,
I2C0_Control,
I2C0_GetStatus
};
#endif /* RTE_I2C0 */
/* I2C1 Driver Instance */
#if (RTE_I2C1)
#if RTE_I2C1_DMA_ENABLE
static void I2C1_DMACallback(uint32_t event, int8_t peri_num);
static I2C_DMA_HW_CONFIG I2C1_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(I2C1_DMA),
.dma_periph_req = I2C1_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = I2C1_DMA,
.group = I2C1_DMA_GROUP,
.channel = I2C1_DMA_RX_PERIPH_REQ,
.enable_handshake = I2C1_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(I2C1_DMA),
.dma_periph_req = I2C1_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = I2C1_DMA,
.group = I2C1_DMA_GROUP,
.channel = I2C1_DMA_TX_PERIPH_REQ,
.enable_handshake = I2C1_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
/* I2C1 Driver Resources */
static I2C_RESOURCES I2C1_RES =
{
.regs = (I2C_Type *)I2C1_BASE,
.irq_num = (IRQn_Type)I2C1_IRQ_IRQn,
.irq_priority = (uint32_t)RTE_I2C1_IRQ_PRIORITY,
#if RTE_I2C1_DMA_ENABLE
.dma_enable = RTE_I2C1_DMA_ENABLE,
.dma_irq_priority = RTE_I2C1_DMA_IRQ_PRI,
.dma_cb = I2C1_DMACallback,
.dma_cfg = &I2C1_DMA_HW_CONFIG,
#endif
.tx_fifo_threshold = RTE_I2C1_TX_FIFO_THRESHOLD,
.rx_fifo_threshold = RTE_I2C1_RX_FIFO_THRESHOLD
};
static int32_t I2C1_Initialize(ARM_I2C_SignalEvent_t cb_event)
{
return ARM_I2C_Initialize(cb_event, &I2C1_RES);
}
static int32_t I2C1_Uninitialize(void)
{
return ARM_I2C_Uninitialize(&I2C1_RES);
}
static int32_t I2C1_PowerControl(ARM_POWER_STATE state)
{
return ARM_I2C_PowerControl(state, &I2C1_RES);
}
static int32_t I2C1_MasterTransmit(uint32_t addr, const uint8_t *data,
uint32_t num, bool xfer_pending)
{
return ARM_I2C_MasterTransmit(&I2C1_RES, addr, data, num, xfer_pending);
}
static int32_t I2C1_MasterReceive(uint32_t addr, uint8_t *data,
uint32_t num, bool xfer_pending)
{
return (ARM_I2C_MasterReceive(&I2C1_RES, addr, data, num, xfer_pending));
}
static int32_t I2C1_SlaveTransmit(const uint8_t *data, uint32_t num)
{
return (ARM_I2C_SlaveTransmit(&I2C1_RES, data, num));
}
static int32_t I2C1_SlaveReceive(uint8_t *data, uint32_t num)
{
return (ARM_I2C_SlaveReceive(&I2C1_RES, data, num));
}
static int32_t I2C1_GetDataCount(void)
{
return (ARM_I2C_GetDataCount(&I2C1_RES));
}
static int32_t I2C1_Control(uint32_t control, uint32_t arg)
{
return (ARM_I2C_Control(&I2C1_RES, control, arg));
}
static ARM_I2C_STATUS I2C1_GetStatus(void)
{
return (ARM_I2C_GetStatus(&I2C1_RES));
}
void I2C1_IRQHandler(void)
{
i2c_transfer_info_t *transfer = &(I2C1_RES.transfer);
ARM_I2C_STATUS *i2c_stat = &(I2C1_RES.status);
/* Check for master mode */
if (I2C1_RES.mode == I2C_MASTER_MODE)
{
if (transfer->curr_stat == I2C_TRANSFER_MST_TX)
{
/* Master transmit*/
i2c_master_tx_isr(I2C1_RES.regs, transfer);
}
if(transfer->curr_stat == I2C_TRANSFER_MST_RX)
{
/* Master receive */
i2c_master_rx_isr(I2C1_RES.regs, transfer);
}
}
else /* Slave mode */
{
if(transfer->curr_stat == I2C_TRANSFER_SLV_TX)
{
/* slave transmit*/
i2c_slave_tx_isr(I2C1_RES.regs, transfer);
}
if(transfer->curr_stat == I2C_TRANSFER_SLV_RX)
{
/* slave receive */
i2c_slave_rx_isr(I2C1_RES.regs, transfer);
}
}/* Slave mode */
if (transfer->status & I2C_TRANSFER_STATUS_DONE)
{
/* set busy flag to 0U */
i2c_stat->busy = 0U;
I2C1_RES.cb_event(ARM_I2C_EVENT_TRANSFER_DONE);
}
else if (transfer->status & I2C_TRANSFER_STATUS_GENERAL_CALL)
{
I2C1_RES.cb_event(ARM_I2C_EVENT_GENERAL_CALL);
}
else if (transfer->status & I2C_TRANSFER_STATUS_BUS_CLEAR)
{
I2C1_RES.cb_event(ARM_I2C_EVENT_BUS_CLEAR);
}
else
{
#if RTE_I2C1_DMA_ENABLE
if(I2C1_RES.status.direction == I2C_DIR_TRANSMITTER)
{
I2C_DMA_Stop(&I2C1_RES.dma_cfg->dma_tx);
}
else
{
I2C_DMA_Stop(&I2C1_RES.dma_cfg->dma_rx);
}
/* set busy flag to 0U */
i2c_stat->busy = 0U;
#endif
if (transfer->status & I2C_TRANSFER_STATUS_SLAVE_TRANSMIT)
{
I2C1_RES.cb_event(ARM_I2C_EVENT_SLAVE_TRANSMIT);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_SLAVE_RECEIVE)
{
I2C1_RES.cb_event(ARM_I2C_EVENT_SLAVE_RECEIVE);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_ADDRESS_NACK)
{
I2C1_RES.cb_event(ARM_I2C_EVENT_ADDRESS_NACK);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_ARBITRATION_LOST)
{
i2c_stat->arbitration_lost = 1U;
I2C1_RES.cb_event(ARM_I2C_EVENT_ARBITRATION_LOST);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_BUS_ERROR)
{
i2c_stat->bus_error = 1U;
I2C1_RES.cb_event(ARM_I2C_EVENT_BUS_ERROR);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_INCOMPLETE)
{
I2C1_RES.cb_event(ARM_I2C_EVENT_TRANSFER_INCOMPLETE);
i2c_stat->busy = 0U;
}
}
transfer->status = I2C_TRANSFER_STATUS_NONE;
}
#if RTE_I2C1_DMA_ENABLE
static void I2C1_DMACallback(uint32_t event, int8_t peri_num)
{
I2C_DMACallback(event, peri_num, &I2C1_RES);
}
#endif
/* I2C1 Driver Control Block */
extern ARM_DRIVER_I2C Driver_I2C1;
ARM_DRIVER_I2C Driver_I2C1 = {
ARM_I2C_GetVersion,
ARM_I2C_GetCapabilities,
I2C1_Initialize,
I2C1_Uninitialize,
I2C1_PowerControl,
I2C1_MasterTransmit,
I2C1_MasterReceive,
I2C1_SlaveTransmit,
I2C1_SlaveReceive,
I2C1_GetDataCount,
I2C1_Control,
I2C1_GetStatus
};
#endif /* RTE_I2C1 */
/* I2C2 Driver Instance */
#if (RTE_I2C2)
#if RTE_I2C2_DMA_ENABLE
static void I2C2_DMACallback(uint32_t event, int8_t peri_num);
static I2C_DMA_HW_CONFIG I2C2_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(I2C2_DMA),
.dma_periph_req = I2C2_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = I2C2_DMA,
.group = I2C2_DMA_GROUP,
.channel = I2C2_DMA_RX_PERIPH_REQ,
.enable_handshake = I2C2_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(I2C2_DMA),
.dma_periph_req = I2C2_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = I2C2_DMA,
.group = I2C2_DMA_GROUP,
.channel = I2C2_DMA_TX_PERIPH_REQ,
.enable_handshake = I2C2_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
/* I2C2 Driver Resources */
static I2C_RESOURCES I2C2_RES =
{
.regs = (I2C_Type *)I2C2_BASE,
.irq_num = (IRQn_Type)I2C2_IRQ_IRQn,
.irq_priority = (uint32_t)RTE_I2C2_IRQ_PRIORITY,
#if RTE_I2C2_DMA_ENABLE
.dma_enable = RTE_I2C2_DMA_ENABLE,
.dma_irq_priority = RTE_I2C2_DMA_IRQ_PRI,
.dma_cb = I2C2_DMACallback,
.dma_cfg = &I2C2_DMA_HW_CONFIG,
#endif
.tx_fifo_threshold = RTE_I2C2_TX_FIFO_THRESHOLD,
.rx_fifo_threshold = RTE_I2C2_RX_FIFO_THRESHOLD
};
static int32_t I2C2_Initialize(ARM_I2C_SignalEvent_t cb_event)
{
return ARM_I2C_Initialize(cb_event, &I2C2_RES);
}
static int32_t I2C2_Uninitialize(void)
{
return ARM_I2C_Uninitialize(&I2C2_RES);
}
static int32_t I2C2_PowerControl(ARM_POWER_STATE state)
{
return ARM_I2C_PowerControl(state, &I2C2_RES);
}
static int32_t I2C2_MasterTransmit(uint32_t addr, const uint8_t *data,
uint32_t num, bool xfer_pending)
{
return ARM_I2C_MasterTransmit(&I2C2_RES, addr, data, num, xfer_pending);
}
static int32_t I2C2_MasterReceive(uint32_t addr, uint8_t *data,
uint32_t num, bool xfer_pending)
{
return (ARM_I2C_MasterReceive(&I2C2_RES, addr, data, num, xfer_pending));
}
static int32_t I2C2_SlaveTransmit(const uint8_t *data, uint32_t num)
{
return (ARM_I2C_SlaveTransmit(&I2C2_RES, data, num));
}
static int32_t I2C2_SlaveReceive(uint8_t *data, uint32_t num)
{
return (ARM_I2C_SlaveReceive(&I2C2_RES, data, num));
}
static int32_t I2C2_GetDataCount(void)
{
return (ARM_I2C_GetDataCount(&I2C2_RES));
}
static int32_t I2C2_Control(uint32_t control, uint32_t arg)
{
return (ARM_I2C_Control(&I2C2_RES, control, arg));
}
static ARM_I2C_STATUS I2C2_GetStatus(void)
{
return (ARM_I2C_GetStatus(&I2C2_RES));
}
void I2C2_IRQHandler(void)
{
i2c_transfer_info_t *transfer = &(I2C2_RES.transfer);
ARM_I2C_STATUS *i2c_stat = &(I2C2_RES.status);
/* Check for master mode */
if (I2C2_RES.mode == I2C_MASTER_MODE)
{
if (transfer->curr_stat == I2C_TRANSFER_MST_TX)
{
/* Master transmit*/
i2c_master_tx_isr(I2C2_RES.regs, transfer);
}
if(transfer->curr_stat == I2C_TRANSFER_MST_RX)
{
/* Master receive */
i2c_master_rx_isr(I2C2_RES.regs, transfer);
}
}
else /* Slave mode */
{
if(transfer->curr_stat == I2C_TRANSFER_SLV_TX)
{
/* slave transmit*/
i2c_slave_tx_isr(I2C2_RES.regs, transfer);
}
if(transfer->curr_stat == I2C_TRANSFER_SLV_RX)
{
/* slave receive */
i2c_slave_rx_isr(I2C2_RES.regs, transfer);
}
}/* Slave mode */
if (transfer->status & I2C_TRANSFER_STATUS_DONE)
{
/* set busy flag to 0U */
i2c_stat->busy = 0U;
I2C2_RES.cb_event(ARM_I2C_EVENT_TRANSFER_DONE);
}
else if (transfer->status & I2C_TRANSFER_STATUS_GENERAL_CALL)
{
I2C2_RES.cb_event(ARM_I2C_EVENT_GENERAL_CALL);
}
else if (transfer->status & I2C_TRANSFER_STATUS_BUS_CLEAR)
{
I2C2_RES.cb_event(ARM_I2C_EVENT_BUS_CLEAR);
}
else
{
#if RTE_I2C2_DMA_ENABLE
if(I2C2_RES.status.direction == I2C_DIR_TRANSMITTER)
{
I2C_DMA_Stop(&I2C2_RES.dma_cfg->dma_tx);
}
else
{
I2C_DMA_Stop(&I2C2_RES.dma_cfg->dma_rx);
}
/* set busy flag to 0U */
i2c_stat->busy = 0U;
#endif
if (transfer->status & I2C_TRANSFER_STATUS_SLAVE_TRANSMIT)
{
I2C2_RES.cb_event(ARM_I2C_EVENT_SLAVE_TRANSMIT);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_SLAVE_RECEIVE)
{
I2C2_RES.cb_event(ARM_I2C_EVENT_SLAVE_RECEIVE);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_ADDRESS_NACK)
{
I2C2_RES.cb_event(ARM_I2C_EVENT_ADDRESS_NACK);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_ARBITRATION_LOST)
{
i2c_stat->arbitration_lost = 1U;
I2C2_RES.cb_event(ARM_I2C_EVENT_ARBITRATION_LOST);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_BUS_ERROR)
{
i2c_stat->bus_error = 1U;
I2C2_RES.cb_event(ARM_I2C_EVENT_BUS_ERROR);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_INCOMPLETE)
{
I2C2_RES.cb_event(ARM_I2C_EVENT_TRANSFER_INCOMPLETE);
i2c_stat->busy = 0U;
}
}
transfer->status = I2C_TRANSFER_STATUS_NONE;
}
#if RTE_I2C2_DMA_ENABLE
static void I2C2_DMACallback(uint32_t event, int8_t peri_num)
{
I2C_DMACallback(event, peri_num, &I2C2_RES);
}
#endif
/* I2C2 Driver Control Block */
extern ARM_DRIVER_I2C Driver_I2C2;
ARM_DRIVER_I2C Driver_I2C2 = {
ARM_I2C_GetVersion,
ARM_I2C_GetCapabilities,
I2C2_Initialize,
I2C2_Uninitialize,
I2C2_PowerControl,
I2C2_MasterTransmit,
I2C2_MasterReceive,
I2C2_SlaveTransmit,
I2C2_SlaveReceive,
I2C2_GetDataCount,
I2C2_Control,
I2C2_GetStatus
};
#endif /* RTE_I2C2 */
/* I2C3 Driver Instance */
#if (RTE_I2C3)
#if RTE_I2C3_DMA_ENABLE
static void I2C3_DMACallback(uint32_t event, int8_t peri_num);
static I2C_DMA_HW_CONFIG I2C3_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(I2C3_DMA),
.dma_periph_req = I2C3_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = I2C3_DMA,
.group = I2C3_DMA_GROUP,
.channel = I2C3_DMA_RX_PERIPH_REQ,
.enable_handshake = I2C3_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(I2C3_DMA),
.dma_periph_req = I2C3_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = I2C3_DMA,
.group = I2C3_DMA_GROUP,
.channel = I2C3_DMA_TX_PERIPH_REQ,
.enable_handshake = I2C3_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
/* I2C3 Driver Resources */
static I2C_RESOURCES I2C3_RES =
{
.regs = (I2C_Type *)I2C3_BASE,
.irq_num = (IRQn_Type)I2C3_IRQ_IRQn,
.irq_priority = (uint32_t)RTE_I2C3_IRQ_PRIORITY,
#if RTE_I2C3_DMA_ENABLE
.dma_enable = RTE_I2C3_DMA_ENABLE,
.dma_irq_priority = RTE_I2C3_DMA_IRQ_PRI,
.dma_cb = I2C3_DMACallback,
.dma_cfg = &I2C3_DMA_HW_CONFIG,
#endif
.tx_fifo_threshold = RTE_I2C3_TX_FIFO_THRESHOLD,
.rx_fifo_threshold = RTE_I2C3_RX_FIFO_THRESHOLD
};
static int32_t I2C3_Initialize(ARM_I2C_SignalEvent_t cb_event)
{
return ARM_I2C_Initialize(cb_event, &I2C3_RES);
}
static int32_t I2C3_Uninitialize(void)
{
return ARM_I2C_Uninitialize(&I2C3_RES);
}
static int32_t I2C3_PowerControl(ARM_POWER_STATE state)
{
return ARM_I2C_PowerControl(state, &I2C3_RES);
}
static int32_t I2C3_MasterTransmit(uint32_t addr, const uint8_t *data,
uint32_t num, bool xfer_pending)
{
return ARM_I2C_MasterTransmit(&I2C3_RES, addr, data, num, xfer_pending);
}
static int32_t I2C3_MasterReceive(uint32_t addr, uint8_t *data,
uint32_t num, bool xfer_pending)
{
return (ARM_I2C_MasterReceive(&I2C3_RES, addr, data, num, xfer_pending));
}
static int32_t I2C3_SlaveTransmit(const uint8_t *data, uint32_t num)
{
return (ARM_I2C_SlaveTransmit(&I2C3_RES, data, num));
}
static int32_t I2C3_SlaveReceive(uint8_t *data, uint32_t num)
{
return (ARM_I2C_SlaveReceive(&I2C3_RES, data, num));
}
static int32_t I2C3_GetDataCount(void)
{
return (ARM_I2C_GetDataCount(&I2C3_RES));
}
static int32_t I2C3_Control(uint32_t control, uint32_t arg)
{
return (ARM_I2C_Control(&I2C3_RES, control, arg));
}
static ARM_I2C_STATUS I2C3_GetStatus(void)
{
return (ARM_I2C_GetStatus(&I2C3_RES));
}
void I2C3_IRQHandler(void)
{
i2c_transfer_info_t *transfer = &(I2C3_RES.transfer);
ARM_I2C_STATUS *i2c_stat = &(I2C3_RES.status);
/* Check for master mode */
if (I2C3_RES.mode == I2C_MASTER_MODE)
{
if (transfer->curr_stat == I2C_TRANSFER_MST_TX)
{
/* Master transmit*/
i2c_master_tx_isr(I2C3_RES.regs, transfer);
}
if(transfer->curr_stat == I2C_TRANSFER_MST_RX)
{
/* Master receive */
i2c_master_rx_isr(I2C3_RES.regs, transfer);
}
}
else /* Slave mode */
{
if(transfer->curr_stat == I2C_TRANSFER_SLV_TX)
{
/* slave transmit*/
i2c_slave_tx_isr(I2C3_RES.regs, transfer);
}
if(transfer->curr_stat == I2C_TRANSFER_SLV_RX)
{
/* slave receive */
i2c_slave_rx_isr(I2C3_RES.regs, transfer);
}
}/* Slave mode */
if (transfer->status & I2C_TRANSFER_STATUS_DONE)
{
/* set busy flag to 0U */
i2c_stat->busy = 0U;
I2C3_RES.cb_event(ARM_I2C_EVENT_TRANSFER_DONE);
}
else if (transfer->status & I2C_TRANSFER_STATUS_GENERAL_CALL)
{
I2C3_RES.cb_event(ARM_I2C_EVENT_GENERAL_CALL);
}
else if (transfer->status & I2C_TRANSFER_STATUS_BUS_CLEAR)
{
I2C3_RES.cb_event(ARM_I2C_EVENT_BUS_CLEAR);
}
else
{
#if RTE_I2C3_DMA_ENABLE
if(I2C3_RES.status.direction == I2C_DIR_TRANSMITTER)
{
I2C_DMA_Stop(&I2C3_RES.dma_cfg->dma_tx);
}
else
{
I2C_DMA_Stop(&I2C3_RES.dma_cfg->dma_rx);
}
/* set busy flag to 0U */
i2c_stat->busy = 0U;
#endif
if (transfer->status & I2C_TRANSFER_STATUS_SLAVE_TRANSMIT)
{
I2C3_RES.cb_event(ARM_I2C_EVENT_SLAVE_TRANSMIT);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_SLAVE_RECEIVE)
{
I2C3_RES.cb_event(ARM_I2C_EVENT_SLAVE_RECEIVE);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_ADDRESS_NACK)
{
I2C3_RES.cb_event(ARM_I2C_EVENT_ADDRESS_NACK);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_ARBITRATION_LOST)
{
i2c_stat->arbitration_lost = 1U;
I2C3_RES.cb_event(ARM_I2C_EVENT_ARBITRATION_LOST);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_BUS_ERROR)
{
i2c_stat->bus_error = 1U;
I2C3_RES.cb_event(ARM_I2C_EVENT_BUS_ERROR);
i2c_stat->busy = 0U;
}
else if (transfer->status & I2C_TRANSFER_STATUS_INCOMPLETE)
{
I2C3_RES.cb_event(ARM_I2C_EVENT_TRANSFER_INCOMPLETE);
i2c_stat->busy = 0U;
}
}
transfer->status = I2C_TRANSFER_STATUS_NONE;
}
#if RTE_I2C3_DMA_ENABLE
static void I2C3_DMACallback(uint32_t event, int8_t peri_num)
{
I2C_DMACallback(event, peri_num, &I2C3_RES);
}
#endif
/* I2C3 Driver Control Block */
extern ARM_DRIVER_I2C Driver_I2C3;
ARM_DRIVER_I2C Driver_I2C3 = {
ARM_I2C_GetVersion,
ARM_I2C_GetCapabilities,
I2C3_Initialize,
I2C3_Uninitialize,
I2C3_PowerControl,
I2C3_MasterTransmit,
I2C3_MasterReceive,
I2C3_SlaveTransmit,
I2C3_SlaveReceive,
I2C3_GetDataCount,
I2C3_Control,
I2C3_GetStatus
};
#endif /* RTE_I2C3 */
/************************ (C) COPYRIGHT ALIF SEMICONDUCTOR *****END OF FILE****/