+++ /dev/null
-/*******************************************************************************\r
- * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.\r
- * \r
- * CoreI2C software driver implementation.\r
- * \r
- * SVN $Revision: 7984 $\r
- * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $\r
- */\r
-#include <stdint.h>\r
-#include <stdlib.h>\r
-#include <stddef.h>\r
-#include <unistd.h>\r
-#include <errno.h>\r
-#include <sys/stat.h>\r
-#include <sys/times.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include "cpu_types.h"\r
-#include "core_smbus_regs.h"\r
-#include "core_i2c.h"\r
-#include "hal.h"\r
-#include "hal_assert.h"\r
-\r
-\r
-#include <string.h>\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C transaction direction.\r
- */\r
-#define WRITE_DIR 0u\r
-#define READ_DIR 1u\r
-\r
-/* -- TRANSACTIONS TYPES -- */\r
-#define NO_TRANSACTION 0u\r
-#define MASTER_WRITE_TRANSACTION 1u\r
-#define MASTER_READ_TRANSACTION 2u\r
-#define MASTER_RANDOM_READ_TRANSACTION 3u\r
-#define WRITE_SLAVE_TRANSACTION 4u\r
-#define READ_SLAVE_TRANSACTION 5u\r
-\r
-/* -- SMBUS H/W STATES -- */\r
-/* -- MASTER STATES -- */\r
-#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */\r
-#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */\r
-#define ST_START 0x08u /* start condition sent */\r
-#define ST_RESTART 0x10u /* repeated start */\r
-#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */\r
-#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */\r
-#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */\r
-#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */\r
-#define ST_LOST_ARB 0x38u /* Master lost arbitration */\r
-#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */\r
-#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */\r
-#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */\r
-#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */\r
-#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */\r
-#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */\r
-\r
-/* -- SLAVE STATES -- */\r
-#define ST_SLAVE_SLAW 0x60u /* SLA+W received */\r
-#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */\r
-#define ST_SLV_LA 0x68u /* Slave lost arbitration */\r
-#define ST_GCA 0x70u /* GCA received */\r
-#define ST_GCA_LA 0x78u /* GCA lost arbitration */\r
-#define ST_RDATA 0x80u /* Data received */\r
-#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */\r
-#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */\r
-#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */\r
-#define ST_RSTOP 0xA0u /* Stop received */\r
-#define ST_SLARW_LA 0xB0u /* Arbitration lost */\r
-#define ST_RACK 0xB8u /* Byte sent, ACK received */\r
-#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */\r
-#define ST_FINAL 0xC8u /* Final byte sent, ACK received */\r
-#define ST_SLV_RST 0xD8u /* Slave reset state */\r
-\r
-\r
-/* I2C Channel base offset */\r
-#define CHANNEL_BASE_SHIFT 5u\r
-#define CHANNEL_MASK 0x1E0u\r
-\r
-/*\r
- * Maximum address offset length in slave write-read transactions.\r
- * A maximum of two bytes will be interpreted as address offset within the slave\r
- * tx buffer.\r
- */\r
-#define MAX_OFFSET_LENGTH 2u\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C interrupts control functions implemented "i2c_interrupt.c".\r
- * the implementation of these functions depend on the underlying hardware\r
- * design and how the CoreI2C interrupt line is connected to the system's\r
- * interrupt controller.\r
- */\r
-void I2C_enable_irq( i2c_instance_t * this_i2c );\r
-void I2C_disable_irq( i2c_instance_t * this_i2c );\r
-static void enable_slave_if_required(i2c_instance_t * this_i2c);\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_init()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_init\r
-(\r
- i2c_instance_t * this_i2c,\r
- addr_t base_address,\r
- uint8_t ser_address,\r
- i2c_clock_divider_t ser_clock_speed\r
-)\r
-{\r
- psr_t saved_psr;\r
- uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;\r
- \r
- /*\r
- * We need to disable ints while doing this as there is no guarantee we\r
- * have not been called already and the ISR is active.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
- \r
- /*\r
- * Initialize all items of the this_i2c data structure to zero. This\r
- * initializes all state variables to their init value. It relies on\r
- * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all\r
- * have an actual value of zero.\r
- */\r
- memset(this_i2c, 0, sizeof(i2c_instance_t));\r
- \r
- /*\r
- * Set base address of I2C hardware used by this instance.\r
- */\r
- this_i2c->base_address = base_address;\r
-\r
- /*\r
- * Update Serial address of the device\r
- */\r
- this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);\r
- \r
- /*\r
- * Configure hardware.\r
- */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );\r
- HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );\r
- HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );\r
-\r
- HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);\r
- HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);\r
- \r
- /*\r
- * Finally safe to enable interrupts.\r
- */\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-/*------------------------------------------------------------------------------\r
- * I2C_channel_init()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_channel_init\r
-(\r
- i2c_instance_t * this_i2c_channel,\r
- i2c_instance_t * this_i2c,\r
- i2c_channel_number_t channel_number,\r
- i2c_clock_divider_t ser_clock_speed\r
-)\r
-{\r
- psr_t saved_psr;\r
- uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;\r
- \r
- HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);\r
- HAL_ASSERT(I2C_CHANNEL_0 != channel_number);\r
-\r
- /* \r
- * Cannot allow channel 0 in this function as we will trash the hardware\r
- * base address and slave address.\r
- */\r
- if ((channel_number < I2C_MAX_CHANNELS) &&\r
- (I2C_CHANNEL_0 != channel_number))\r
- {\r
- /*\r
- * We need to disable ints while doing this as the hardware should already\r
- * be active at this stage.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
- /*\r
- * Initialize channel data.\r
- */\r
- memset(this_i2c_channel, 0, sizeof(i2c_instance_t));\r
- \r
- this_i2c_channel->base_address =\r
- ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK)) \r
- | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);\r
-\r
- this_i2c_channel->ser_address = this_i2c->ser_address;\r
-\r
- HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */\r
- HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */\r
- HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );\r
- HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );\r
- HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );\r
- /*\r
- * Finally safe to enable interrupts.\r
- */\r
-\r
- HAL_restore_interrupts( saved_psr );\r
- }\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_write()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_write\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint8_t serial_addr,\r
- const uint8_t * write_buffer,\r
- uint16_t write_size,\r
- uint8_t options\r
-)\r
-{\r
- psr_t saved_psr;\r
- volatile uint8_t stat_ctrl;\r
-\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- /* Update the transaction only when there is no transaction going on I2C */\r
- if( this_i2c->transaction == NO_TRANSACTION)\r
- {\r
- this_i2c->transaction = MASTER_WRITE_TRANSACTION;\r
- }\r
-\r
- /* Update the Pending transaction information so that transaction can restarted */\r
- this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;\r
-\r
- /* Update target address */\r
- this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;\r
- this_i2c->dir = WRITE_DIR;\r
- this_i2c->master_tx_buffer = write_buffer;\r
- this_i2c->master_tx_size = write_size;\r
- this_i2c->master_tx_idx = 0u;\r
-\r
- /* Set I2C status in progress */\r
- this_i2c->master_status = I2C_IN_PROGRESS;\r
- this_i2c->options = options;\r
-\r
- if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
- {\r
- this_i2c->is_transaction_pending = 1u;\r
- }\r
- else\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
- }\r
-\r
- /*\r
- * Clear interrupts if required (depends on repeated starts).\r
- * Since the Bus is on hold, only then prior status needs to\r
- * be cleared.\r
- */\r
- if ( I2C_HOLD_BUS == this_i2c->bus_status )\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);\r
- }\r
-\r
- stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
- stat_ctrl = stat_ctrl; /* Avoids lint warning. */\r
-\r
- /* Enable the interrupt. ( Re-enable) */\r
- I2C_enable_irq( this_i2c );\r
-\r
-\r
- HAL_restore_interrupts(saved_psr);\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_read()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_read\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint8_t serial_addr,\r
- uint8_t * read_buffer,\r
- uint16_t read_size,\r
- uint8_t options\r
-)\r
-{\r
- psr_t saved_psr;\r
- volatile uint8_t stat_ctrl;\r
-\r
-\r
- saved_psr=HAL_disable_interrupts();\r
- \r
- /* Update the transaction only when there is no transaction going on I2C */\r
- if( this_i2c->transaction == NO_TRANSACTION)\r
- {\r
- this_i2c->transaction = MASTER_READ_TRANSACTION;\r
- }\r
-\r
- /* Update the Pending transaction information so that transaction can restarted */\r
- this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;\r
-\r
- /* Update target address */\r
- this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;\r
-\r
- this_i2c->dir = READ_DIR;\r
-\r
- this_i2c->master_rx_buffer = read_buffer;\r
- this_i2c->master_rx_size = read_size;\r
- this_i2c->master_rx_idx = 0u;\r
-\r
- /* Set I2C status in progress */\r
- this_i2c->master_status = I2C_IN_PROGRESS;\r
-\r
- this_i2c->options = options;\r
- \r
- if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
- {\r
- this_i2c->is_transaction_pending = 1u;\r
- }\r
- else\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
- }\r
-\r
- /*\r
- * Clear interrupts if required (depends on repeated starts).\r
- * Since the Bus is on hold, only then prior status needs to\r
- * be cleared.\r
- */\r
- if ( I2C_HOLD_BUS == this_i2c->bus_status )\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);\r
- }\r
-\r
- stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
- stat_ctrl = stat_ctrl; /* Avoids lint warning. */\r
-\r
- /* Enable the interrupt. ( Re-enable) */\r
- I2C_enable_irq( this_i2c );\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_write_read()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_write_read\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint8_t serial_addr,\r
- const uint8_t * addr_offset,\r
- uint16_t offset_size,\r
- uint8_t * read_buffer,\r
- uint16_t read_size,\r
- uint8_t options\r
-)\r
-{\r
- HAL_ASSERT(offset_size > 0u);\r
- HAL_ASSERT(addr_offset != (uint8_t *)0);\r
- HAL_ASSERT(read_size > 0u);\r
- HAL_ASSERT(read_buffer != (uint8_t *)0);\r
- \r
- this_i2c->master_status = I2C_FAILED;\r
- \r
- if((read_size > 0u) && (offset_size > 0u))\r
- {\r
- psr_t saved_psr;\r
- volatile uint8_t stat_ctrl;\r
-\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- /* Update the transaction only when there is no transaction going on I2C */\r
- if( this_i2c->transaction == NO_TRANSACTION)\r
- {\r
- this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;\r
- }\r
-\r
- /* Update the Pending transaction information so that transaction can restarted */\r
- this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;\r
-\r
- /* Update target address */\r
- this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;\r
-\r
- this_i2c->dir = WRITE_DIR;\r
-\r
- this_i2c->master_tx_buffer = addr_offset;\r
- this_i2c->master_tx_size = offset_size;\r
- this_i2c->master_tx_idx = 0u;\r
-\r
- this_i2c->master_rx_buffer = read_buffer;\r
- this_i2c->master_rx_size = read_size;\r
- this_i2c->master_rx_idx = 0u;\r
- \r
- /* Set I2C status in progress */\r
- this_i2c->master_status = I2C_IN_PROGRESS;\r
- this_i2c->options = options;\r
- \r
- if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
- {\r
- this_i2c->is_transaction_pending = 1u;\r
- }\r
- else\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
- }\r
-\r
- /*\r
- * Clear interrupts if required (depends on repeated starts).\r
- * Since the Bus is on hold, only then prior status needs to\r
- * be cleared.\r
- */\r
- if ( I2C_HOLD_BUS == this_i2c->bus_status )\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);\r
- }\r
-\r
- stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
- stat_ctrl = stat_ctrl; /* Avoids lint warning. */\r
- \r
- /* Enable the interrupt. ( Re-enable) */\r
- I2C_enable_irq( this_i2c );\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
- }\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_get_status()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-i2c_status_t I2C_get_status\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- i2c_status_t i2c_status ;\r
-\r
- i2c_status = this_i2c->master_status ;\r
-\r
- return i2c_status;\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_wait_complete()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-i2c_status_t I2C_wait_complete\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint32_t timeout_ms\r
-)\r
-{\r
- i2c_status_t i2c_status;\r
- psr_t saved_psr;\r
- /*\r
- * Because we have no idea of what CPU we are supposed to be running on\r
- * we need to guard this write to the timeout value to avoid ISR/user code\r
- * interaction issues. Checking the status below should be fine as only a\r
- * single byte should change in that.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
- this_i2c->master_timeout_ms = timeout_ms;\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-\r
- /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/\r
- do {\r
- i2c_status = this_i2c->master_status;\r
- } while(I2C_IN_PROGRESS == i2c_status);\r
- return i2c_status;\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_system_tick()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_system_tick\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint32_t ms_since_last_tick\r
-)\r
-{\r
- if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)\r
- {\r
- if(this_i2c->master_timeout_ms > ms_since_last_tick)\r
- {\r
- this_i2c->master_timeout_ms -= ms_since_last_tick;\r
- }\r
- else\r
- {\r
- psr_t saved_psr;\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * shared data without the I2C ISR interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- /*\r
- * Mark current transaction as having timed out.\r
- */\r
- this_i2c->master_status = I2C_TIMED_OUT;\r
- this_i2c->transaction = NO_TRANSACTION;\r
- this_i2c->is_transaction_pending = 0;\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
- \r
- /*\r
- * Make sure we do not incorrectly signal a timeout for subsequent\r
- * transactions.\r
- */\r
- this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;\r
- }\r
- }\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_set_slave_tx_buffer()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_set_slave_tx_buffer\r
-(\r
- i2c_instance_t * this_i2c,\r
- const uint8_t * tx_buffer,\r
- uint16_t tx_size\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * shared data without the I2C ISR interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
- \r
- this_i2c->slave_tx_buffer = tx_buffer;\r
- this_i2c->slave_tx_size = tx_size;\r
- this_i2c->slave_tx_idx = 0u;\r
- \r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_set_slave_rx_buffer()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_set_slave_rx_buffer\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint8_t * rx_buffer,\r
- uint16_t rx_size\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * shared data without the I2C ISR interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- this_i2c->slave_rx_buffer = rx_buffer;\r
- this_i2c->slave_rx_size = rx_size;\r
- this_i2c->slave_rx_idx = 0u;\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_set_slave_mem_offset_length()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_set_slave_mem_offset_length\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint8_t offset_length\r
-)\r
-{\r
- HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);\r
- \r
- /*\r
- * Single byte update, should be interrupt safe\r
- */\r
- if(offset_length > MAX_OFFSET_LENGTH)\r
- {\r
- this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;\r
- }\r
- else\r
- {\r
- this_i2c->slave_mem_offset_length = offset_length;\r
- }\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_register_write_handler()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_register_write_handler\r
-(\r
- i2c_instance_t * this_i2c,\r
- i2c_slave_wr_handler_t handler\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * shared data without the I2C ISR interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- this_i2c->slave_write_handler = handler;\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_enable_slave()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_enable_slave\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * hardware register and slave mode flag without the I2C ISR interrupting\r
- * us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- /* Set the Assert Acknowledge bit. */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);\r
-\r
- /* Enable slave mode */\r
- this_i2c->is_slave_enabled = 1u;\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-\r
- /* Enable I2C IRQ*/\r
- I2C_enable_irq( this_i2c );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_disable_slave()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_disable_slave\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * hardware register without the I2C ISR interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
- \r
- /* Reset the assert acknowledge bit. */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);\r
-\r
- /* Disable slave mode with IRQ blocked to make whole change atomic */\r
- this_i2c->is_slave_enabled = 0u;\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * \r
- */\r
-static void enable_slave_if_required\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- /*\r
- * This function is only called from within the ISR and so does not need\r
- * guarding on the register access.\r
- */\r
- if( 0 != this_i2c->is_slave_enabled )\r
- {\r
- HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );\r
- }\r
-}\r
-/*------------------------------------------------------------------------------\r
- * I2C_set_slave_second_addr()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_set_slave_second_addr\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint8_t second_slave_addr\r
-)\r
-{\r
- uint8_t second_slave_address;\r
- \r
- /*\r
- This function does not support CoreI2C hardware configured with a fixed \r
- second slave address. The current implementation of the ADDR1[0] register\r
- bit makes it difficult for the driver to support both programmable and\r
- fixed second slave address, so we choose to support programmable only.\r
- With the programmable configuration, ADDR1[0] and ADDR0[0] both control\r
- enable/disable of GCA recognition, as an effective OR of the 2 bit fields.\r
- Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.\r
- */\r
- second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));\r
-\r
- /*\r
- * Single byte register write, should be interrupt safe\r
- */\r
- HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_disable_slave_second_addr()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_disable_slave_second_addr\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- /*\r
- We are disabling the second slave address by setting the value of the 2nd\r
- slave address to the primary slave address. The reason for using this method\r
- of disabling 2nd slave address is that ADDRESS1[0] has different meaning \r
- depending on hardware configuration. Its use would likely interfere with\r
- the intended GCA setting.\r
- */\r
- /*\r
- * Single byte register write, should be interrupt safe\r
- */\r
- HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * i2C_set_gca()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-\r
-void I2C_set_gca\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- /* \r
- * This read modify write access should be interrupt safe as the address\r
- * register is not written to in the ISR.\r
- */\r
- /* accept GC addressing. */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_clear_gca()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_clear_gca\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- /* \r
- * This read modify write access should be interrupt safe as the address\r
- * register is not written to in the ISR.\r
- */\r
- /* Clear GC addressing. */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_isr()\r
- * See "core_i2c.h" for details of how to use this function.\r
- */\r
-void I2C_isr\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- volatile uint8_t status;\r
- uint8_t data;\r
- uint8_t hold_bus;\r
- uint8_t clear_irq = 1u;\r
-\r
- status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
- \r
- switch( status )\r
- {\r
- /************** MASTER TRANSMITTER / RECEIVER *******************/\r
- \r
- case ST_START: /* start has been xmt'd */\r
- case ST_RESTART: /* repeated start has been xmt'd */\r
- //write_hex(STDOUT_FILENO, status);\r
- HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);\r
- HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */\r
- HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */\r
- if(this_i2c->dir == WRITE_DIR)\r
- {\r
- this_i2c->master_tx_idx = 0u;\r
- }\r
- else\r
- {\r
- this_i2c->master_rx_idx = 0u;\r
- }\r
-\r
- /*\r
- * Clear the pending transaction. This condition will be true if the slave \r
- * has acquired the bus to carry out pending master transaction which \r
- * it had received during its slave transmission or reception mode. \r
- */\r
- if(this_i2c->is_transaction_pending)\r
- {\r
- this_i2c->is_transaction_pending = 0u;\r
- }\r
-\r
- /*\r
- * Make sure to update proper transaction after master START\r
- * or RESTART\r
- */\r
- if(this_i2c->transaction != this_i2c->pending_transaction)\r
- {\r
- this_i2c->transaction = this_i2c->pending_transaction;\r
- }\r
- break;\r
- \r
- case ST_LOST_ARB:\r
- /* Set start bit. Let's keep trying! Don't give up! */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
- break;\r
-\r
- case ST_STOP_TRANSMIT:\r
- /* Stop has been transmitted. Do nothing */\r
- break;\r
-\r
- /******************* MASTER TRANSMITTER *************************/\r
- case ST_SLAW_NACK:\r
- //write_hex(STDOUT_FILENO, status);\r
- /* SLA+W has been transmitted; not ACK has been received - let's stop. */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);\r
- this_i2c->master_status = I2C_FAILED;\r
- this_i2c->transaction = NO_TRANSACTION;\r
- enable_slave_if_required(this_i2c);\r
- break;\r
- \r
- case ST_SLAW_ACK:\r
- case ST_TX_DATA_ACK:\r
- //write_hex(STDOUT_FILENO, status);\r
- /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */\r
- if (this_i2c->master_tx_idx < this_i2c->master_tx_size)\r
- { \r
- HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);\r
- }\r
- else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )\r
- {\r
- /* We are finished sending the address offset part of a random read transaction.\r
- * It is is time to send a restart in order to change direction. */\r
- this_i2c->dir = READ_DIR;\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
- }\r
- else /* done sending. let's stop */\r
- {\r
- /*\r
- * Set the transaction back to NO_TRANSACTION to allow user to do further\r
- * transaction\r
- */\r
- this_i2c->transaction = NO_TRANSACTION;\r
- hold_bus = this_i2c->options & I2C_HOLD_BUS;\r
-\r
- /* Store the information of current I2C bus status in the bus_status*/\r
- this_i2c->bus_status = hold_bus;\r
- if ( hold_bus == 0u )\r
- { \r
- HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */\r
- enable_slave_if_required(this_i2c);\r
- }\r
- else\r
- {\r
- I2C_disable_irq( this_i2c );\r
- clear_irq = 0u;\r
- }\r
- this_i2c->master_status = I2C_SUCCESS;\r
- }\r
- break;\r
-\r
- case ST_TX_DATA_NACK:\r
- //write_hex(STDOUT_FILENO, status);\r
- /* data byte SENT, ACK to be received\r
- * In fact, this means we've received a NACK (This may not be \r
- * obvious, but if we've rec'd an ACK then we would be in state \r
- * 0x28!) hence, let's send a stop bit\r
- */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */\r
- this_i2c->master_status = I2C_FAILED;\r
-\r
- /*\r
- * Set the transaction back to NO_TRANSACTION to allow user to do further\r
- * transaction\r
- */\r
- this_i2c->transaction = NO_TRANSACTION;\r
- enable_slave_if_required(this_i2c);\r
- break;\r
- \r
- /********************* MASTER (or slave?) RECEIVER *************************/\r
- \r
- /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */\r
- case ST_SLAR_ACK: /* SLA+R tx'ed. */\r
-// //write_hex(STDOUT_FILENO, status);\r
- /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless\r
- * the next byte is the last byte of the read transaction.\r
- */\r
- if(this_i2c->master_rx_size > 1u)\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);\r
- }\r
- else if(1u == this_i2c->master_rx_size)\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);\r
- }\r
- else /* this_i2c->master_rx_size == 0u */\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);\r
- this_i2c->master_status = I2C_SUCCESS;\r
- this_i2c->transaction = NO_TRANSACTION;\r
- }\r
- break;\r
- \r
- case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */\r
-// //write_hex(STDOUT_FILENO, status);\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);\r
- this_i2c->master_status = I2C_FAILED;\r
-\r
- /*\r
- * Set the transaction back to NO_TRANSACTION to allow user to do further\r
- * transaction\r
- */\r
- this_i2c->transaction = NO_TRANSACTION;\r
- enable_slave_if_required(this_i2c);\r
- break;\r
- \r
- case ST_RX_DATA_ACK: /* Data byte received, ACK returned */\r
-// //write_hex(STDOUT_FILENO, status);\r
- /* First, get the data */\r
- this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);\r
- if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))\r
- {\r
- /* If we're at the second last byte, let's set AA to 0 so\r
- * we return a NACK at the last byte. */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);\r
- }\r
- break;\r
- \r
- case ST_RX_DATA_NACK: /* Data byte received, NACK returned */\r
-// //write_hex(STDOUT_FILENO, status);\r
- /* Get the data, then send a stop condition */\r
- this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);\r
- \r
- hold_bus = this_i2c->options & I2C_HOLD_BUS; \r
-\r
- /* Store the information of current I2C bus status in the bus_status*/\r
- this_i2c->bus_status = hold_bus;\r
- if ( hold_bus == 0u )\r
- { \r
- HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */\r
-\r
- /* Bus is released, now we can start listening to bus, if it is slave */\r
- enable_slave_if_required(this_i2c);\r
- }\r
- else\r
- {\r
- I2C_disable_irq( this_i2c );\r
- clear_irq = 0u;\r
- }\r
- /*\r
- * Set the transaction back to NO_TRANSACTION to allow user to do further\r
- * transaction\r
- */\r
- this_i2c->transaction = NO_TRANSACTION;\r
- this_i2c->master_status = I2C_SUCCESS;\r
- break;\r
- \r
- /******************** SLAVE RECEIVER **************************/\r
- case ST_GCA_NACK: /* NACK after, GCA addressing */\r
- case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */\r
- //write_hex(STDOUT_FILENO, status);\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);\r
-\r
- this_i2c->transaction = NO_TRANSACTION;\r
- this_i2c->slave_status = I2C_SUCCESS;\r
- \r
- /* Check if transaction was pending. If yes, set the START bit */\r
- if(this_i2c->is_transaction_pending)\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
- }\r
- break;\r
- \r
- case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */\r
- case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */\r
- //write_hex(STDOUT_FILENO, status);\r
- /*\r
- * We lost arbitration and either the GCE or our address was the\r
- * one received so pend the master operation we were starting.\r
- */\r
- this_i2c->is_transaction_pending = 1u;\r
- /* Fall through to normal ST processing as we are now in slave mode */\r
-\r
- case ST_GCA: /* General call address received, ACK returned */\r
- case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */\r
- //write_hex(STDOUT_FILENO, status);\r
- this_i2c->transaction = WRITE_SLAVE_TRANSACTION;\r
- this_i2c->slave_rx_idx = 0u;\r
- this_i2c->random_read_addr = 0u;\r
- /*\r
- * If Start Bit is set clear it, but store that information since it is because of\r
- * pending transaction\r
- */\r
- if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);\r
- this_i2c->is_transaction_pending = 1u;\r
- }\r
- this_i2c->slave_status = I2C_IN_PROGRESS;\r
-#ifdef INCLUDE_SLA_IN_RX_PAYLOAD\r
- /* Fall through to put address as first byte in payload buffer */\r
-#else\r
- /* Only break from this case if the slave address must NOT be included at the\r
- * beginning of the received write data. */\r
- break;\r
-#endif \r
- case ST_GCA_ACK: /* DATA received; ACK sent after GCA */\r
- case ST_RDATA: /* DATA received; must clear DATA register */\r
- //write_hex(STDOUT_FILENO, status);\r
- if((this_i2c->slave_rx_buffer != (uint8_t *)0)\r
- && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))\r
- {\r
- data = HAL_get_8bit_reg(this_i2c->base_address, DATA);\r
- this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;\r
- \r
-#ifdef INCLUDE_SLA_IN_RX_PAYLOAD\r
- if((ST_RDATA == status) || (ST_GCA_ACK == status))\r
- {\r
- /* Ignore the slave address byte in the random read address\r
- computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD\r
- is defined. */\r
-#endif\r
- this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;\r
-#ifdef INCLUDE_SLA_IN_RX_PAYLOAD\r
- }\r
-#endif\r
- }\r
- \r
- if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)\r
- {\r
- /* Rx buffer is full. NACK next received byte. */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u); \r
- }\r
- break;\r
- \r
- case ST_RSTOP:\r
- //write_hex(STDOUT_FILENO, status);\r
- /* STOP or repeated START occurred. */\r
- /* We cannot be sure if the transaction has actually completed as\r
- * this hardware state reports that either a STOP or repeated START\r
- * condition has occurred. We assume that this is a repeated START\r
- * if the transaction was a write from the master to this point.*/\r
- if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )\r
- {\r
- if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )\r
- {\r
- this_i2c->slave_tx_idx = this_i2c->random_read_addr;\r
- }\r
- /* Call the slave's write transaction handler if it exists. */\r
- if ( this_i2c->slave_write_handler != 0u )\r
- {\r
- i2c_slave_handler_ret_t h_ret;\r
- h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );\r
- if ( I2C_REENABLE_SLAVE_RX == h_ret )\r
- {\r
- /* There is a small risk that the write handler could\r
- * call I2C_disable_slave() but return\r
- * I2C_REENABLE_SLAVE_RX in error so we only enable\r
- * ACKs if still in slave mode. */\r
- enable_slave_if_required(this_i2c);\r
- }\r
- else\r
- {\r
- HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );\r
- /* Clear slave mode flag as well otherwise in mixed\r
- * master/slave applications, the AA bit will get set by\r
- * subsequent master operations. */\r
- this_i2c->is_slave_enabled = 0u;\r
- }\r
- }\r
- else\r
- {\r
- /* Re-enable address acknowledge in case we were ready to nack the next received byte. */\r
- HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );\r
- }\r
- }\r
- else /* A stop or repeated start outside a write/read operation */\r
- {\r
- /*\r
- * Reset slave_tx_idx so that a subsequent read will result in the slave's\r
- * transmit buffer being sent from the first byte.\r
- */\r
- this_i2c->slave_tx_idx = 0u;\r
- /*\r
- * See if we need to re-enable acknowledgement as some error conditions, such\r
- * as a master prematurely ending a transfer, can see us get here with AA set\r
- * to 0 which will disable slave operation if we are not careful.\r
- */\r
- enable_slave_if_required(this_i2c);\r
- }\r
-\r
- /* Mark any previous master write transaction as complete. */\r
- this_i2c->slave_status = I2C_SUCCESS;\r
- \r
- /* Check if transaction was pending. If yes, set the START bit */\r
- if(this_i2c->is_transaction_pending)\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
- }\r
-\r
- /*\r
- * Set the transaction back to NO_TRANSACTION to allow user to do further\r
- * transaction\r
- */\r
- this_i2c->transaction = NO_TRANSACTION;\r
-\r
- break;\r
- \r
- case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */\r
- //write_hex(STDOUT_FILENO, status);\r
- /*\r
- * Set the transaction back to NO_TRANSACTION to allow user to do further\r
- * transaction.\r
- */\r
- this_i2c->transaction = NO_TRANSACTION;\r
- /*\r
- * Reset slave_tx_idx so that a subsequent read will result in the slave's\r
- * transmit buffer being sent from the first byte.\r
- */\r
- this_i2c->slave_tx_idx = 0u;\r
- /*\r
- * Clear status to I2C_FAILED only if there was an operation in progress.\r
- */\r
- if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
- {\r
- this_i2c->slave_status = I2C_FAILED;\r
- }\r
-\r
- enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */\r
-\r
- break;\r
- \r
- /****************** SLAVE TRANSMITTER **************************/\r
- case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */\r
- case ST_SLARW_LA: /* Arbitration lost, and: */\r
- case ST_RACK: /* Data tx'ed, ACK received */\r
- //write_hex(STDOUT_FILENO, status);\r
- if ( status == ST_SLAVE_SLAR_ACK )\r
- {\r
- this_i2c->transaction = READ_SLAVE_TRANSACTION;\r
- this_i2c->random_read_addr = 0u;\r
- this_i2c->slave_status = I2C_IN_PROGRESS;\r
- /* If Start Bit is set clear it, but store that information since it is because of\r
- * pending transaction\r
- */\r
- if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);\r
- this_i2c->is_transaction_pending = 1u;\r
- }\r
- }\r
- if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)\r
- {\r
- /* Ensure 0xFF is returned to the master when the slave specifies\r
- * an empty transmit buffer. */\r
- HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);\r
- }\r
- else\r
- {\r
- /* Load the data the data byte to be sent to the master. */\r
- HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);\r
- }\r
- /* Determine if this is the last data byte to send to the master. */\r
- if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u); \r
- /* Next read transaction will result in slave's transmit buffer\r
- * being sent from the first byte. */\r
- this_i2c->slave_tx_idx = 0u;\r
- }\r
- break;\r
- \r
- case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */\r
- case ST_FINAL: /* Last Data byte tx'ed, ACK received */\r
- //write_hex(STDOUT_FILENO, status);\r
- /* We assume that the transaction will be stopped by the master.\r
- * Reset slave_tx_idx so that a subsequent read will result in the slave's\r
- * transmit buffer being sent from the first byte. */\r
- this_i2c->slave_tx_idx = 0u;\r
- HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u); \r
-\r
- /* Mark previous state as complete */\r
- this_i2c->slave_status = I2C_SUCCESS;\r
- /* Check if transaction was pending. If yes, set the START bit */\r
- if(this_i2c->is_transaction_pending)\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
- }\r
- /*\r
- * Set the transaction back to NO_TRANSACTION to allow user to do further\r
- * transaction\r
- */\r
- this_i2c->transaction = NO_TRANSACTION;\r
-\r
- break;\r
-\r
- /* Master Reset has been activated Wait 35 ms for interrupt to be set,\r
- * clear interrupt and proceed to 0xF8 state. */\r
- case ST_RESET_ACTIVATED:\r
- case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */\r
- default:\r
- //write_hex(STDOUT_FILENO, status);\r
- /* Some undefined state has encountered. Clear Start bit to make\r
- * sure, next good transaction happen */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);\r
- /*\r
- * Set the transaction back to NO_TRANSACTION to allow user to do further\r
- * transaction.\r
- */\r
- this_i2c->transaction = NO_TRANSACTION;\r
- /*\r
- * Reset slave_tx_idx so that a subsequent read will result in the slave's\r
- * transmit buffer being sent from the first byte.\r
- */\r
- this_i2c->slave_tx_idx = 0u;\r
- /*\r
- * Clear statuses to I2C_FAILED only if there was an operation in progress.\r
- */\r
- if(I2C_IN_PROGRESS == this_i2c->master_status)\r
- {\r
- this_i2c->master_status = I2C_FAILED;\r
- }\r
-\r
- if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
- {\r
- this_i2c->slave_status = I2C_FAILED;\r
- }\r
-\r
- break;\r
- }\r
- \r
- if ( clear_irq )\r
- {\r
- /* clear interrupt. */\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);\r
- }\r
- \r
- /* Read the status register to ensure the last I2C registers write took place\r
- * in a system built around a bus making use of posted writes. */\r
-// status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_smbus_init()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
- \r
-/*\r
- * SMBSUS_NO = 1\r
- * SMBALERT_NO = 1\r
- * SMBus enable = 1\r
- */\r
-#define INIT_AND_ENABLE_SMBUS 0x54u\r
-void I2C_smbus_init\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- /*\r
- * Single byte register write, should be interrupt safe\r
- */\r
- /* Enable SMBUS */\r
- HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_enable_smbus_irq()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_enable_smbus_irq\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint8_t irq_type\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * hardware register without the SMBUS IRQs interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- if ( irq_type & I2C_SMBALERT_IRQ)\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);\r
- }\r
- if ( irq_type & I2C_SMBSUS_IRQ)\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);\r
- }\r
- \r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_disable_smbus_irq()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_disable_smbus_irq\r
-(\r
- i2c_instance_t * this_i2c,\r
- uint8_t irq_type\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * hardware register without the SMBUS IRQs interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- if ( irq_type & I2C_SMBALERT_IRQ)\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);\r
- }\r
- if (irq_type & I2C_SMBSUS_IRQ )\r
- {\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);\r
- }\r
- \r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_suspend_smbus_slave()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_suspend_smbus_slave\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * hardware register without the SMBUS IRQs interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_resume_smbus_slave()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_resume_smbus_slave\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * hardware register without the SMBUS IRQs interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_reset_smbus()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_reset_smbus\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * hardware register without the SMBUS IRQs interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);\r
- \r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_set_smbus_alert()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_set_smbus_alert\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * hardware register without the SMBUS IRQs interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_clear_smbus_alert()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_clear_smbus_alert\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- psr_t saved_psr;\r
-\r
- /*\r
- * We need to disable interrupts here to ensure we can update the\r
- * hardware register without the SMBUS IRQs interrupting us.\r
- */\r
-\r
- saved_psr=HAL_disable_interrupts();\r
-\r
- HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);\r
-\r
-\r
- HAL_restore_interrupts( saved_psr );\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_get_irq_status()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-uint8_t I2C_get_irq_status\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- uint8_t status ;\r
- uint8_t irq_type = I2C_NO_IRQ ;\r
-\r
- status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);\r
-\r
- if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )\r
- {\r
- irq_type |= I2C_SMBALERT_IRQ ;\r
- }\r
-\r
- if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )\r
- {\r
- irq_type |= I2C_SMBSUS_IRQ ;\r
- }\r
-\r
- status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);\r
-\r
- if( status & (uint8_t)SI_MASK )\r
- {\r
- irq_type |= I2C_INTR_IRQ ;\r
- }\r
- return(irq_type);\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_set_slave_addr2()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void I2C_set_user_data\r
-(\r
- i2c_instance_t * this_i2c,\r
- void * p_user_data\r
-)\r
-{\r
- this_i2c->p_user_data = p_user_data ;\r
-}\r
-\r
-/*------------------------------------------------------------------------------\r
- * I2C_get_user_data()\r
- * See "i2c.h" for details of how to use this function.\r
- */\r
-void * I2C_get_user_data\r
-(\r
- i2c_instance_t * this_i2c\r
-)\r
-{\r
- return( this_i2c->p_user_data);\r
-}\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r