+/*******************************************************************************\r
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * CoreI2C software driver Application Programming Interface.\r
+ * This file contains defines and function declarations allowing to interface\r
+ * with the CoreI2C software driver.\r
+ * \r
+ * SVN $Revision: 7984 $\r
+ * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $\r
+ */\r
+/*=========================================================================*//**\r
+ @mainpage CoreI2C Bare Metal Driver.\r
+ The CoreI2C bare metal software driver supports I2C master and slave\r
+ operations.\r
+\r
+ @section intro_sec Introduction\r
+ The CoreI2C driver provides a set of functions for controlling the Microsemi\r
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per\r
+ CoreI2C instance, with common slave address settings shared between channels\r
+ on a device.\r
+ \r
+ Optional features of the CoreI2C allow it operate with I2C based protocols\r
+ such as System Management Bus (SMBus), Power Management Bus (PMBus) and\r
+ Intelligent Platform Management Interface (IPMI). This driver provides support\r
+ for these features when enabled in the CoreI2C IP.\r
+ \r
+ The major features provided by CoreI2C driver are:\r
+ - Support for configuring the I2C channels of each CoreI2C peripheral.\r
+ - I2C master operations.\r
+ - I2C slave operations.\r
+ - SMBus related operations.\r
+\r
+ This driver can be used as part of a bare metal system where no operating \r
+ system is available. The driver can be adapted for use as part of an \r
+ operating system, but the implementation of the adaptation layer between the \r
+ driver and the operating system's driver model is outside the scope of this \r
+ driver.\r
+ \r
+ @section hw_dependencies Hardware Flow Dependencies\r
+ Your application software should configure the CoreI2C driver through\r
+ calls to the I2C_init() function for each CoreI2C instance in the\r
+ hardware design. The configuration parameters include the CoreI2C hardware\r
+ instance base address and other runtime parameters, such as the I2C serial\r
+ clock frequency and I2C device address.\r
+ \r
+ Once channel 0 of a CoreI2C peripheral has been initialized via I2C_init(),\r
+ any additional channels present should be configured by calling\r
+ I2C_channel_init() for each of the remaining channels.\r
+ \r
+ No CoreI2C hardware configuration parameters are used by the driver, apart\r
+ from the CoreI2C hardware instance base address. Hence, no additional\r
+ configuration files are required to use the driver. \r
+ \r
+ Interrupt Control\r
+ The CoreI2C driver has to enable and disable the generation of interrupts by\r
+ CoreI2C at various times when it is operating. This enabling and disabling of\r
+ interrupts must be done through the system\92s interrupt controller. For that\r
+ reason, the method of controlling the CoreI2C interrupt is system specific\r
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()\r
+ functions. These functions are found in the file i2c_interrupt.c. Their\r
+ default implementation fires an assertion to attract attention to the fact\r
+ that these functions must be modified.\r
+ \r
+ The implementation of the I2C_enable_irq() function should permit interrupts\r
+ generated by a CoreI2C instance to interrupt the processor. The implementation\r
+ of the I2C_disable_irq() function should prevent interrupts generated by a\r
+ CoreI2C instance from interrupting the processor. Please refer to the provided\r
+ example projects for a working implementation of these functions.\r
+ \r
+ The function I2C_register_write_handler() is used to register a write handler\r
+ function with the CoreI2C driver that it calls on completion of an I2C write\r
+ transaction by the CoreI2C slave. It is your responsibility to create and\r
+ register the implementation of this handler function that processes or\r
+ trigger the processing of the received data.\r
+ \r
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are\r
+ enabled and disabled through I2C_enable_smbus_irq() and \r
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create\r
+ interrupt handler functions in your application to get the desired response\r
+ for the SMBus interrupts.\r
+\r
+ Note: You must include the path to any application header files that are\r
+ included in the i2c_interrupt.c file, as an include path in your\r
+ project\92s compiler settings. The details of how to do this will depend\r
+ on your development software.\r
+\r
+ SMBus Logic options\r
+ SMBus related APIs will not have any effect if in CoreI2C hardware\r
+ configuration "Generate SMBus Logic" is not enabled. The APIs which will not\r
+ give desired results in case SMBus Logic is disabled are:\r
+ \r
+ I2C_smbus_init()\r
+ I2C_reset_smbus()\r
+ I2C_enable_smbus_irq()\r
+ I2C_disable_smbus_irq()\r
+ I2C_suspend_smbus_slave()\r
+ I2C_resume_smbus_slave()\r
+ I2C_set_smsbus_alert()\r
+ I2C_clear_smsbus_alert()\r
+ I2C_get_irq_status() \r
+\r
+ Fixed Baud Rate Values\r
+ The serial clock frequency parameter passed to the I2C_init() and \r
+ I2C_channel_init() functions may not have any effect if fixed values were\r
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed\r
+ values are selected for these baud rates, the driver cannot overwrite\r
+ the fixed values.\r
+\r
+ Fixed Slave Address Options Values\r
+ The primary slave address parameter passed to the I2C_init() function, and\r
+ secondary address value passed to the I2C_set_slave_second_addr() function,\r
+ may not have the desired effect if fixed values were selected for the slave 0\r
+ address and slave 1 address respectively. Proper operation of this version of\r
+ the driver requires the slave addresses to be programmable.\r
+\r
+ @section theory_op Theory of Operation\r
+ The CoreI2C software driver is designed to allow the control of multiple\r
+ instances of CoreI2C with one or more I2C channels. Each channel in an\r
+ instance of CoreI2C in the hardware design is associated with a single \r
+ instance of the i2c_instance_t structure in the software. You must allocate\r
+ memory for one unique i2c_instance_t structure instance for each channel of\r
+ each CoreI2C hardware instance. The contents of these data structures are\r
+ initialised during calls to I2C_init() and if necessary I2C_channel_init().\r
+ A pointer to the structure is passed to subsequent driver functions in order\r
+ to identify the CoreI2C hardware instance and channel you wish to perform the\r
+ requested operation.\r
+\r
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t\r
+ structures. These structures are only intended to be modified by the driver\r
+ functions.\r
+\r
+ The CoreI2C driver functions are grouped into the following categories:\r
+ - Initialization and configuration functions\r
+ - Interrupt control\r
+ - I2C slave addressing functions\r
+ - I2C master operations functions to handle write, read and write-read \r
+ transactions\r
+ - I2C slave operations functions to handle write, read and write-read \r
+ transactions\r
+ - Mixed master-slave operations \r
+ - SMBus interface configuration and control.\r
+ \r
+ Initialization and Configuration\r
+ The CoreI2C device is first initialized through a call to the I2C_init()\r
+ function. Since each CoreI2C peripheral supports up to 16 channels, an\r
+ additional function, I2C_channel_init(), is required to initialize the\r
+ remaining channels with their own data structures.\r
+\r
+ I2C_init() initializes channel 0 of a CoreI2C and the i2c_instance_t for\r
+ channel 0 acts as the basis for further channel initialization as the\r
+ hardware base address and I2C serial address are same across all the\r
+ channels. I2C_init() must be called before any other I2C driver function\r
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address\r
+ assigned to the I2C and the serial clock divider to be used to generate its\r
+ I2C clock as configuration parameters. \r
+ \r
+ I2C_channel_init() takes as input parameters a pointer to the CoreI2C \r
+ i2c_instance_t which has been initialized via I2C_init() and a pointer to a\r
+ separate i2c_instance_t which represents this new channel. Another input\r
+ parameter which is required by this function is serial clock divider which\r
+ generates its I2C clock. \r
+ \r
+ Interrupt Control\r
+ The CoreI2C driver is interrupt driven and it uses each channels INT\r
+ interrupt to drive the state machine which is at the heart of the driver.\r
+ The application is responsible for providing the link between the interrupt\r
+ generating hardware and the CoreI2C interrupt handler and must ensure that\r
+ the I2C_isr() function is called with the correct i2c_instance_t structure\r
+ pointer for the CoreI2C channel initiating the interrupt.\r
+ \r
+ The driver enables and disables the generation of INT interrupts by CoreI2C\r
+ at various times when it is operating through the user supplied\r
+ I2C_enable_irq() and I2C_disable_irq() functions. \r
+ \r
+ The function I2C_register_write_handler() is used to register a write\r
+ handler function with the CoreI2C driver which is called on completion\r
+ of an I2C write transaction by the CoreI2C slave. It is the user\r
+ applications responsibility to create and register the implementation of\r
+ this handler function that processes or triggers the processing of the\r
+ received data. \r
+ \r
+ The other two interrupt sources in the CoreI2C, are related to SMBus\r
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and\r
+ I2C_disable_smbus_irq() respectively. Due to the application specific\r
+ nature of the response to SMBus interrupts, you must design interrupt\r
+ handler functions in the application to get the desired behaviour for\r
+ SMBus related interrupts.\r
+ \r
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an\r
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.\r
+ \r
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an\r
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.\r
+\r
+ I2C slave addressing functions\r
+ A CoreI2C peripheral can respond to three slave addresses:\r
+ - Slave address 0 - This is the primary slave address which is used for\r
+ accessing a CoreI2C channel when it acts as a slave in\r
+ I2C transactions. You must configure the primary slave\r
+ address via I2C_init().\r
+ \r
+ - Slave address 1 - This is the secondary slave address which might be\r
+ required in certain application specific scenarios.\r
+ The secondary slave address can be configured via\r
+ I2C_set_slave_second_addr() and disabled via \r
+ I2C_disable_slave_second_addr().\r
+ \r
+ - General call address - A CoreI2C slave can be configured to respond to\r
+ a broadcast command by a master transmitting the\r
+ general call address of 0x00. Use the I2C_set_gca()\r
+ function to enable the slave to respond to the general\r
+ call address. If the CoreI2C slave is not required to\r
+ respond to the general call address, disable this\r
+ address by calling I2C_clear_gca().\r
+\r
+ Note: All channels on a CoreI2C instance share the same slave address logic.\r
+ This means that they cannot have separate slave addresses and rely on\r
+ the separate physical I2C bus connections to distinguish them.\r
+ \r
+ Transaction Types\r
+ The I2C driver is designed to handle three types of I2C transaction:\r
+ Write transactions\r
+ Read transactions\r
+ Write-read transactions\r
+ \r
+ Write transaction\r
+ The master I2C device initiates a write transaction by sending a START bit\r
+ as soon as the bus becomes free. The START bit is followed by the 7-bit\r
+ serial address of the target slave device followed by the read/write bit\r
+ indicating the direction of the transaction. The slave acknowledges the\r
+ receipt of it's address with an acknowledge bit. The master sends data one\r
+ byte at a time to the slave, which must acknowledge receipt of each byte\r
+ for the next byte to be sent. The master sends a STOP bit to complete the\r
+ transaction. The slave can abort the transaction by replying with a \r
+ non-acknowledge bit instead of an acknowledge.\r
+ \r
+ The application programmer can choose not to send a STOP bit at the end of\r
+ the transaction causing the next transaction to begin with a repeated \r
+ START bit.\r
+ \r
+ Read transaction\r
+ The master I2C device initiates a read transaction by sending a START bit\r
+ as soon as the bus becomes free. The START bit is followed by the 7-bit\r
+ serial address of the target slave device followed by the read/write bit\r
+ indicating the direction of the transaction. The slave acknowledges\r
+ receipt of it's slave address with an acknowledge bit. The slave sends\r
+ data one byte at a time to the master, which must acknowledge receipt of\r
+ each byte for the next byte to be sent. The master sends a non-acknowledge\r
+ bit following the last byte it wishes to read followed by a STOP bit.\r
+ \r
+ The application programmer can choose not to send a STOP bit at the end of\r
+ the transaction causing the next transaction to begin with a repeated \r
+ START bit.\r
+ \r
+ Write-read transaction\r
+ The write-read transaction is a combination of a write transaction\r
+ immediately followed by a read transaction. There is no STOP bit between\r
+ the write and read phases of a write-read transaction. A repeated START\r
+ bit is sent between the write and read phases.\r
+ \r
+ Whilst the write handler is being executed, the slave holds the clock line\r
+ low to stretch the clock until the response is ready.\r
+ \r
+ The write-read transaction is typically used to send a command or offset\r
+ in the write transaction specifying the logical data to be transferred\r
+ during the read phase.\r
+ \r
+ The application programmer can choose not to send a STOP bit at the end of\r
+ the transaction causing the next transaction to begin with a repeated\r
+ START bit.\r
+\r
+ Master Operations\r
+ The application can use the I2C_write(), I2C_read() and I2C_write_read()\r
+ functions to initiate an I2C bus transaction. The application can then wait\r
+ for the transaction to complete using the I2C_wait_complete() function\r
+ or poll the status of the I2C transaction using the I2C_get_status()\r
+ function until it returns a value different from I2C_IN_PROGRESS. The\r
+ I2C_system_tick() function can be used to set a time base for the\r
+ I2C_wait_complete() function\92s time out delay.\r
+\r
+ Slave Operations\r
+ The configuration of the I2C driver to operate as an I2C slave requires\r
+ the use of the following functions:\r
+ I2C_set_slave_tx_buffer()\r
+ I2C_set_slave_rx_buffer()\r
+ I2C_set_slave_mem_offset_length()\r
+ I2C_register_write_handler()\r
+ I2C_enable_slave()\r
+ \r
+ Use of all functions is not required if the slave I2C does not need to support\r
+ all types of I2C read transactions. The subsequent sections list the functions\r
+ that must be used to support each transaction type. \r
+ \r
+ Responding to read transactions\r
+ The following functions are used to configure the CoreI2C driver to\r
+ respond to I2C read transactions:\r
+ I2C_set_slave_tx_buffer()\r
+ I2C_enable_slave()\r
+ \r
+ The function I2C_set_slave_tx_buffer() specifies the data buffer that\r
+ will be transmitted when the I2C slave is the target of an I2C read\r
+ transaction. It is then up to the application to manage the content of\r
+ that buffer to control the data that will be transmitted to the I2C\r
+ master as a result of the read transaction.\r
+ \r
+ The function I2C_enable_slave() enables the I2C hardware instance\r
+ to respond to I2C transactions. It must be called after the I2C driver\r
+ has been configured to respond to the required transaction types.\r
+\r
+ Responding to write transactions\r
+ The following functions are used to configure the I2C driver to respond\r
+ to I2C write transactions:\r
+ I2C_set_slave_rx_buffer()\r
+ I2C_register_write_handler()\r
+ I2C_enable_slave()\r
+ \r
+ The function I2C_set_slave_rx_buffer() specifies the data buffer that\r
+ will be used to store the data received by the I2C slave when it is the\r
+ target an I2C write transaction.\r
+ \r
+ The function I2C_register_write_handler() specifies the handler function\r
+ that must be called on completion of the I2C write transaction. It is this\r
+ handler function that processes or triggers the processing of the received\r
+ data.\r
+ \r
+ The function I2C_enable_slave() enables the I2C hardware instance\r
+ to respond to I2C transactions. It must be called after the I2C driver\r
+ has been configured to respond to the required transaction types.\r
+\r
+ Responding to write-read transactions\r
+ The following functions are used to configure the CoreI2C driver to \r
+ respond to write-read transactions:\r
+ I2C_set_slave_mem_offset_length()\r
+ I2C_set_slave_tx_buffer()\r
+ I2C_set_slave_rx_buffer()\r
+ I2C_register_write_handler()\r
+ I2C_enable_slave()\r
+ \r
+ The function I2C_set_slave_mem_offset_length() specifies the number of\r
+ bytes expected by the I2C slave during the write phase of the write-read\r
+ transaction.\r
+ \r
+ The function I2C_set_slave_tx_buffer() specifies the data that will be\r
+ transmitted to the I2C master during the read phase of the write-read\r
+ transaction. The value received by the I2C slave during the write phase of\r
+ the transaction will be used as an index into the transmit buffer\r
+ specified by this function to decide which part of the transmit buffer\r
+ will be transmitted to the I2C master as part of the read phase of the\r
+ write-read transaction. \r
+ \r
+ The function I2C_set_slave_rx_buffer() specifies the data buffer that\r
+ will be used to store the data received by the I2C slave during the write\r
+ phase of the write-read transaction. This buffer must be at least large\r
+ enough to accommodate the number of bytes specified through the\r
+ I2C_set_slave_mem_offset_length() function.\r
+ \r
+ The function I2C_register_write_handler() can optionally be used to\r
+ specify a handler function that is called on completion of the write phase\r
+ of the I2C write-read transaction. If a handler function is registered, it\r
+ is responsible for processing the received data in the slave receive\r
+ buffer and populating the slave transmit buffer with the data that will be\r
+ transmitted to the I2C master as part of the read phase of the write-read\r
+ transaction.\r
+ \r
+ The function I2C_enable_slave() enables the CoreI2C hardware instance to \r
+ respond to I2C transactions. It must be called after the CoreI2C driver\r
+ has been configured to respond to the required transaction types.\r
+\r
+ Mixed Master-Slave Operations\r
+ The CoreI2C device supports mixed master and slave operations. If the \r
+ CoreI2C slave has a transaction in progress and your application attempts to\r
+ begin a master mode transaction, the CoreI2C driver queu3es the master mode\r
+ transaction until the bus is released and the CoreI2C can switch to master\r
+ mode and acquire the bus. The CoreI2C master then starts the previously\r
+ queued master transaction.\r
+ \r
+ SMBus Control\r
+ The CoreI2C driver enables the CoreI2C peripheral\92s SMBus functionality\r
+ using the I2C_smbus_init() function.\r
+ \r
+ The I2C_suspend_smbus_slave() function is used, with a master mode CoreI2C,\r
+ to force slave devices on the SMBus to enter their power-down/suspend mode.\r
+ The I2C_resume_smbus_slave() function is used to end the suspend operation\r
+ on the SMBus.\r
+ \r
+ The I2C_reset_smbus() function is used, with a master mode CoreI2C, to force\r
+ all devices on the SMBus to reset their SMBUs interface.\r
+ \r
+ The I2C_set_smsbus_alert() function is used, by a slave mode CoreI2C, to\r
+ force communication with the SMBus master. Once communications with the\r
+ master is initiated, the I2C_clear_smsbus_alert() function is used to clear\r
+ the alert condition.\r
+ \r
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to\r
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.\r
+\r
+ *//*=========================================================================*/\r
+\r
+#ifndef CORE_I2C_H_\r
+#define CORE_I2C_H_\r
+\r
+#include "cpu_types.h"\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif \r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to\r
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate\r
+ that a STOP bit must be generated at the end of the I2C transaction to release\r
+ the bus.\r
+ */\r
+#define I2C_RELEASE_BUS 0x00u\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_HOLD_BUS constant is used to specify the options parameter to\r
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate\r
+ that a STOP bit must not be generated at the end of the I2C transaction in\r
+ order to retain the bus ownership. This causes the next transaction to\r
+ begin with a repeated START bit and no STOP bit between the transactions.\r
+ */\r
+#define I2C_HOLD_BUS 0x01u\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The following constants specify the interrupt identifier number which will be\r
+ solely used by driver API. This has nothing to do with hardware interrupt line.\r
+ I2C_INT_IRQ is the primary interrupt signal which drives the state machine\r
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBUS_IRQ are used by\r
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used\r
+ by I2C_get_irq_status().\r
+ */\r
+#define I2C_NO_IRQ 0x00u\r
+#define I2C_SMBALERT_IRQ 0x01u\r
+#define I2C_SMBSUS_IRQ 0x02u\r
+#define I2C_INTR_IRQ 0x04u\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_NO_TIMEOUT constant is used as parameter to the I2C_wait_complete()\r
+ function to indicate that the wait for completion of the transaction should\r
+ not time out.\r
+ */\r
+#define I2C_NO_TIMEOUT 0u\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The i2c_channel_number_t type is used to specify the channel number of a\r
+ CoreI2C instance.\r
+ */\r
+typedef enum i2c_channel_number {\r
+ I2C_CHANNEL_0 = 0u,\r
+ I2C_CHANNEL_1,\r
+ I2C_CHANNEL_2,\r
+ I2C_CHANNEL_3,\r
+ I2C_CHANNEL_4,\r
+ I2C_CHANNEL_5,\r
+ I2C_CHANNEL_6,\r
+ I2C_CHANNEL_7,\r
+ I2C_CHANNEL_8,\r
+ I2C_CHANNEL_9,\r
+ I2C_CHANNEL_10,\r
+ I2C_CHANNEL_11,\r
+ I2C_CHANNEL_12,\r
+ I2C_CHANNEL_13,\r
+ I2C_CHANNEL_14,\r
+ I2C_CHANNEL_15,\r
+ I2C_MAX_CHANNELS = 16u\r
+} i2c_channel_number_t;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The i2c_clock_divider_t type is used to specify the divider to be applied\r
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.\r
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,\r
+ all other values select a clock frequency based on division of PCLK.\r
+ */\r
+typedef enum i2c_clock_divider {\r
+ I2C_PCLK_DIV_256 = 0u,\r
+ I2C_PCLK_DIV_224,\r
+ I2C_PCLK_DIV_192,\r
+ I2C_PCLK_DIV_160,\r
+ I2C_PCLK_DIV_960,\r
+ I2C_PCLK_DIV_120,\r
+ I2C_PCLK_DIV_60,\r
+ I2C_BCLK_DIV_8\r
+} i2c_clock_divider_t;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The i2c_status_t type is used to report the status of I2C transactions.\r
+ */\r
+typedef enum i2c_status\r
+{\r
+ I2C_SUCCESS = 0u,\r
+ I2C_IN_PROGRESS,\r
+ I2C_FAILED,\r
+ I2C_TIMED_OUT\r
+} i2c_status_t;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The i2c_slave_handler_ret_t type is used by slave write handler functions\r
+ to indicate whether or not the received data buffer should be released.\r
+ */\r
+typedef enum i2c_slave_handler_ret {\r
+ I2C_REENABLE_SLAVE_RX = 0u,\r
+ I2C_PAUSE_SLAVE_RX = 1u\r
+} i2c_slave_handler_ret_t;\r
+\r
+typedef struct i2c_instance i2c_instance_t ;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ Slave write handler functions prototype.\r
+ ------------------------------------------------------------------------------\r
+ This defines the function prototype that must be followed by I2C slave write\r
+ handler functions. These functions are registered with the CoreI2C driver\r
+ through the I2C_register_write_handler() function.\r
+\r
+ Declaring and Implementing Slave Write Handler Functions:\r
+ Slave write handler functions should follow the following prototype:\r
+ i2c_slave_handler_ret_t write_handler\r
+ ( \r
+ i2c_instance_t *instance, uint8_t * data, uint16_t size \r
+ );\r
+\r
+ The instance parameter is a pointer to the i2c_instance_t for which this\r
+ slave write handler has been declared.\r
+ \r
+ The data parameter is a pointer to a buffer (received data buffer) holding\r
+ the data written to the I2C slave.\r
+ \r
+ Defining the macro INCLUDE_SLA_IN_RX_PAYLOAD causes the driver to insert the\r
+ actual address used to access the slave as the first byte in the buffer.\r
+ This allows applications tailor their response based on the actual address\r
+ used to access the slave (primary address, secondary address or GCA).\r
+ \r
+ The size parameter is the number of bytes held in the received data buffer.\r
+ Handler functions must return one of the following values:\r
+ I2C_REENABLE_SLAVE_RX\r
+ I2C_PAUSE_SLAVE_RX.\r
+ \r
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases\r
+ the received data buffer and allows further I2C write transactions to the\r
+ I2C slave to take place.\r
+ \r
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds\r
+ to subsequent write requests with a non-acknowledge bit (NACK), until the\r
+ received data buffer content has been processed by some other part of the\r
+ software application.\r
+ \r
+ A call to I2C_enable_slave() is required at some point after returning\r
+ I2C_PAUSE_SLAVE_RX in order to release the received data buffer so it can\r
+ be used to store data received by subsequent I2C write transactions.\r
+ */\r
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );\r
+\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ i2c_instance_t\r
+ ------------------------------------------------------------------------------\r
+ This structure is used to identify the various CoreI2C hardware instances in\r
+ your system and the I2C channels within them. Your application software should\r
+ declare one instance of this structure for each channel of each instance of\r
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init() \r
+ initialize this structure depending on whether it is channel 0 or one of the\r
+ additional channels respectively. A pointer to an initialized instance of the\r
+ structure should be passed as the first parameter to the CoreI2C driver\r
+ functions, to identify which CoreI2C hardware instance and channel should\r
+ perform the requested operation.\r
+ \r
+ The contents of this data structure should not be modified or used outside of\r
+ the CoreI2C driver. Software using the CoreI2C driver should only need to \r
+ create one single instance of this data structure for each channel of each \r
+ CoreI2C hardware instance in the system then pass a pointer to these data\r
+ structures with each call to the CoreI2C driver in order to identify the\r
+ CoreI2C hardware instance it wishes to use.\r
+ */\r
+struct i2c_instance\r
+{\r
+ addr_t base_address;\r
+ uint_fast8_t ser_address;\r
+\r
+ /* Transmit related info:*/\r
+ uint_fast8_t target_addr;\r
+\r
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/\r
+ uint8_t transaction;\r
+ \r
+ uint_fast16_t random_read_addr;\r
+\r
+ uint8_t options;\r
+ \r
+ /* Master TX INFO: */\r
+ const uint8_t * master_tx_buffer;\r
+ uint_fast16_t master_tx_size;\r
+ uint_fast16_t master_tx_idx;\r
+ uint_fast8_t dir;\r
+ \r
+ /* Master RX INFO: */\r
+ uint8_t * master_rx_buffer;\r
+ uint_fast16_t master_rx_size;\r
+ uint_fast16_t master_rx_idx;\r
+\r
+ /* Master Status */\r
+ volatile i2c_status_t master_status;\r
+ uint32_t master_timeout_ms;\r
+\r
+ /* Slave TX INFO */\r
+ const uint8_t * slave_tx_buffer;\r
+ uint_fast16_t slave_tx_size;\r
+ uint_fast16_t slave_tx_idx;\r
+ \r
+ /* Slave RX INFO */\r
+ uint8_t * slave_rx_buffer;\r
+ uint_fast16_t slave_rx_size;\r
+ uint_fast16_t slave_rx_idx;\r
+ /* Slave Status */\r
+ volatile i2c_status_t slave_status;\r
+ \r
+ /* Slave data: */\r
+ uint_fast8_t slave_mem_offset_length;\r
+ i2c_slave_wr_handler_t slave_write_handler;\r
+ uint8_t is_slave_enabled;\r
+ \r
+ /* user specific data */\r
+ void *p_user_data ;\r
+\r
+ /* I2C bus status */\r
+ uint8_t bus_status;\r
+\r
+ /* Is transaction pending flag */\r
+ uint8_t is_transaction_pending;\r
+\r
+ /* I2C Pending transaction */\r
+ uint8_t pending_transaction;\r
+};\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C initialization routine.\r
+ ------------------------------------------------------------------------------\r
+ The I2C_init() function is used to configure channel 0 of a CoreI2C instance.\r
+ It sets the base hardware address which is used to locate the CoreI2C instance\r
+ in memory and also used internally by I2C_channel_init() to calculate the\r
+ register addresses for any additional channels. The slave serial address set\r
+ is shared by all channels on a CoreI2C instance. \r
+ \r
+ If only one channel is configured in a CoreI2C, the address of the \r
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the\r
+ CoreI2C driver functions. If more than one channel is configured in the\r
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes\r
+ the i2c_instance_t data structure for a specific channel.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ Pointer to the i2c_instance_t data structure which will hold all data\r
+ related to channel 0 of the CoreI2C instance being initialized. A pointer\r
+ to this structure will be used in all subsequent calls to CoreI2C driver\r
+ functions which are to operate on channel 0 of this CoreI2C instance.\r
+ \r
+ @param base_address:\r
+ Base address in the processor's memory map of the registers of the CoreI2C\r
+ instance being initialized.\r
+ \r
+ @param ser_address:\r
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the\r
+ CoreI2C being initialized. It is the principal I2C bus address to which the\r
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave\r
+ mode and the serial address is significant only in the case of I2C slave\r
+ mode. In master mode, CoreI2C does not require a serial address and the\r
+ value of this parameter is not important. If you do not intend to use the\r
+ CoreI2C device in slave mode, then any dummy slave address value can be\r
+ provided to this parameter. However, in systems where the CoreI2C may be\r
+ expected to switch from master mode to slave mode, it is advisable to\r
+ initialize the CoreI2C device with a valid serial slave address.\r
+ \r
+ You need to call the I2C_init() function whenever it is required to change \r
+ the primary slave address as there is no separate function to set the\r
+ primary slave address of the I2C device. The serial address being\r
+ initialized through this function is basically the primary slave address or\r
+ slave address0. I2C_set_slave_second_addr() can be used to set the\r
+ secondary slave address or slave address 1.\r
+ Note : ser_address parameter does not have any affect if fixed slave \r
+ address is enabled in CoreI2C hardware design. CoreI2C will \r
+ be always addressed with the hardware configured fixed slave\r
+ address.\r
+ Note : ser_address parameter will not have any affect if the CoreI2C\r
+ instance is only used in master mode.\r
+\r
+ @param ser_clock_speed:\r
+ This parameter sets the I2C serial clock frequency. It selects the divider\r
+ that will be used to generate the serial clock from the APB PCLK or from\r
+ the BCLK. It can be one of the following:\r
+ I2C_PCLK_DIV_256\r
+ I2C_PCLK_DIV_224\r
+ I2C_PCLK_DIV_192\r
+ I2C_PCLK_DIV_160\r
+ I2C_PCLK_DIV_960\r
+ I2C_PCLK_DIV_120\r
+ I2C_PCLK_DIV_60\r
+ I2C_BCLK_DIV_8\r
+ Note: serial_clock_speed value will have no affect if Fixed baud rate is \r
+ enabled in CoreI2C hardware instance configuration dialogue window. \r
+ The fixed baud rate divider value will override the value\r
+ passed as parameter in this function.\r
+ Note: serial_clock_speed value is not critical for devices that only operate\r
+ as slaves and can be set to any of the above values. \r
+\r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void system_init( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ }\r
+ @endcode\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
+/*-------------------------------------------------------------------------*//**\r
+ I2C channel initialization routine.\r
+ ------------------------------------------------------------------------------\r
+ The I2C_channel_init() function initializes and configures hardware and data\r
+ structures of one of the additional channels of a CoreI2C instance.\r
+ I2C_init() must be called before calling this function to set the CoreI2C\r
+ instance hardware base address and I2C serial address. I2C_channel_init() also\r
+ initializes I2C serial clock divider to set the serial clock baud rate. \r
+ The pointer to data structure i2c_instance_t used for a particular channel\r
+ will be used as an input parameter to subsequent CoreI2C driver functions\r
+ which operate on this channel.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c_channel\r
+ Pointer to the i2c_instance_t data structure holding all data related to the\r
+ CoreI2C channel being initialized. A pointer to the same data structure will\r
+ be used in subsequent calls to the CoreI2C driver functions in order to\r
+ identify the CoreI2C channel instance that should perform the operation \r
+ implemented by the called driver function.\r
+\r
+ @param this_i2c:\r
+ This is a pointer to an i2c_instance_t structure previously initialized by\r
+ I2C_init(). It holds information regarding the hardware base address and\r
+ I2C serial address for the CoreI2C containing the channel to be\r
+ initialized. This information is required by I2C_channel_init() to\r
+ initialize the i2c_instance_t structure pointed to by this_i2c_channel as\r
+ all channels in a CoreI2C instance share the same base address and serial\r
+ address. It is very important that the i2c_instance_t structure pointed to\r
+ by this_i2c has been previously initialized with a call to I2C_init().\r
+ \r
+ @param channel_number:\r
+ This parameter of type i2c_channel_number_t identifies the channel to be\r
+ initialized.\r
+\r
+ @param ser_clock_speed:\r
+ This parameter sets the I2C serial clock frequency. It selects the divider\r
+ that will be used to generate the serial clock from the APB PCLK or from\r
+ the BCLK. It can be one of the following:\r
+ I2C_PCLK_DIV_256\r
+ I2C_PCLK_DIV_224\r
+ I2C_PCLK_DIV_192\r
+ I2C_PCLK_DIV_160\r
+ I2C_PCLK_DIV_960\r
+ I2C_PCLK_DIV_120\r
+ I2C_PCLK_DIV_60\r
+ I2C_BCLK_DIV_8\r
+ \r
+ Note: serial_clock_speed value will have no affect if Fixed baud rate is \r
+ enabled in CoreI2C hardware instance configuration dialogue window. \r
+ The fixed baud rate divider value will supersede the value \r
+ passed as parameter in this function.\r
+\r
+ Note: ser_clock_speed value is not critical for devices that only operate\r
+ as slaves and can be set to any of the above values. \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_SER_ADDR 0x10u\r
+ #define DATA_LENGTH 16u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ i2c_instance_t g_i2c_channel_1_inst;\r
+\r
+ uint8_t tx_buffer[DATA_LENGTH];\r
+ uint8_t write_length = DATA_LENGTH;\r
+\r
+ void system_init( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ \r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Initialize CoreI2C channel 1 with different clock speed\r
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,\r
+ I2C_PCLK_DIV_224 );\r
+ \r
+ // Write data to Channel 1 of CoreI2C instance.\r
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,\r
+ write_length, I2C_RELEASE_BUS );\r
+ }\r
+ @endcode\r
+ \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
+/*------------------------------------------------------------------------------\r
+ CoreI2C interrupt service routine.\r
+ ------------------------------------------------------------------------------\r
+ The function I2C_isr is the CoreI2C interrupt service routine. User must\r
+ call this function from their application level CoreI2C interrupt handler\r
+ function. This function runs the I2C state machine based on previous and \r
+ current status.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @return none\r
+ \r
+ Example:\r
+ @code\r
+ \r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u\r
+ #define COREI2C_SER_ADDR 0x10u\r
+ #define I2C_IRQ_NB 2u\r
+ \r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void core_i2c_isr( void )\r
+ {\r
+ I2C_isr( &g_i2c_inst );\r
+ }\r
+ \r
+ void main( void )\r
+ {\r
+ CIC_init( COREINTERRUPT_BASE_ADDR );\r
+ NVIC_init();\r
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ NVIC_enable_interrupt( NVIC_IRQ_0 );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_isr\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*******************************************************************************\r
+ *******************************************************************************\r
+ * \r
+ * Master specific functions\r
+ * \r
+ * The following functions are only used within an I2C master's implementation.\r
+ */\r
+ \r
+/*-------------------------------------------------------------------------*//**\r
+ I2C master write function.\r
+ ------------------------------------------------------------------------------\r
+ This function initiates an I2C master write transaction. This function returns\r
+ immediately after initiating the transaction. The content of the write buffer\r
+ passed as parameter should not be modified until the write transaction\r
+ completes. It also means that the memory allocated for the write buffer should\r
+ not be freed or should not go out of scope before the write completes. You can\r
+ check for the write transaction completion using the I2C_status() function.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param serial_addr:\r
+ This parameter specifies the serial address of the target I2C device.\r
+ \r
+ @param write_buffer:\r
+ This parameter is a pointer to a buffer holding the data to be written to\r
+ the target I2C device.\r
+ Care must be taken not to release the memory used by this buffer before the\r
+ write transaction completes. For example, it is not appropriate to return\r
+ from a function allocating this buffer as an auto array variable before the\r
+ write transaction completes as this would result in the buffer's memory \r
+ being de-allocated from the stack when the function returns. This memory\r
+ could then be subsequently reused and modified causing unexpected data to \r
+ be written to the target I2C device.\r
+ \r
+ @param write_size:\r
+ Number of bytes held in the write_buffer to be written to the target I2C\r
+ device.\r
+ \r
+ @param options:\r
+ The options parameter is used to indicate if the I2C bus should be released\r
+ on completion of the write transaction. Using the I2C_RELEASE_BUS\r
+ constant for the options parameter causes a STOP bit to be generated at the\r
+ end of the write transaction causing the bus to be released for other I2C\r
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter\r
+ prevents a STOP bit from being generated at the end of the write\r
+ transaction, preventing other I2C devices from initiating a bus transaction.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_DUMMY_ADDR 0x10u\r
+ #define DATA_LENGTH 16u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t tx_buffer[DATA_LENGTH];\r
+ uint8_t write_length = DATA_LENGTH; \r
+\r
+ void main( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ i2c_status_t status;\r
+ \r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Write data to Channel 0 of CoreI2C instance.\r
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,\r
+ I2C_RELEASE_BUS );\r
+ \r
+ // Wait for completion and record the outcome\r
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );\r
+ }\r
+ @endcode\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
+/*-------------------------------------------------------------------------*//**\r
+ I2C master read.\r
+ ------------------------------------------------------------------------------\r
+ This function initiates an I2C master read transaction. This function returns\r
+ immediately after initiating the transaction.\r
+ The contents of the read buffer passed as parameter should not be modified\r
+ until the read transaction completes. It also means that the memory allocated\r
+ for the read buffer should not be freed or should not go out of scope before\r
+ the read completes. You can check for the read transaction completion using \r
+ the I2C_status() function.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param serial_addr:\r
+ This parameter specifies the serial address of the target I2C device.\r
+ \r
+ @param read_buffer\r
+ This is a pointer to a buffer where the data received from the target device\r
+ will be stored.\r
+ Care must be taken not to release the memory used by this buffer before the\r
+ read transaction completes. For example, it is not appropriate to return\r
+ from a function allocating this buffer as an auto array variable before the\r
+ read transaction completes as this would result in the buffer's memory being\r
+ de-allocated from the stack when the function returns. This memory could\r
+ then be subsequently reallocated resulting in the read transaction\r
+ corrupting the newly allocated memory. \r
+\r
+ @param read_size:\r
+ This parameter specifies the number of bytes to read from the target device.\r
+ This size must not exceed the size of the read_buffer buffer.\r
+ \r
+ @param options:\r
+ The options parameter is used to indicate if the I2C bus should be released\r
+ on completion of the read transaction. Using the I2C_RELEASE_BUS\r
+ constant for the options parameter causes a STOP bit to be generated at the\r
+ end of the read transaction causing the bus to be released for other I2C\r
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter\r
+ prevents a STOP bit from being generated at the end of the read transaction,\r
+ preventing other I2C devices from initiating a bus transaction.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_DUMMY_ADDR 0x10u\r
+ #define DATA_LENGTH 16u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t rx_buffer[DATA_LENGTH];\r
+ uint8_t read_length = DATA_LENGTH; \r
+\r
+ void main( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ i2c_status_t status;\r
+ \r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Read data from target slave Channel 0 of CoreI2C instance.\r
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,\r
+ I2C_RELEASE_BUS );\r
+ \r
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );\r
+ }\r
+ @endcode\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
+/*-------------------------------------------------------------------------*//**\r
+ I2C master write-read\r
+ ------------------------------------------------------------------------------\r
+ This function initiates an I2C write-read transaction where data is first\r
+ written to the target device before issuing a restart condition and changing\r
+ the direction of the I2C transaction in order to read from the target device.\r
+ \r
+ The same warnings about buffer allocation in I2C_write() and I2C_read() \r
+ apply to this function.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of\r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param serial_addr:\r
+ This parameter specifies the serial address of the target I2C device.\r
+ \r
+ @param addr_offset:\r
+ This parameter is a pointer to the buffer containing the data that will be\r
+ sent to the slave during the write phase of the write-read transaction. This\r
+ data is typically used to specify an address offset specifying to the I2C\r
+ slave device what data it must return during the read phase of the\r
+ write-read transaction.\r
+ \r
+ @param offset_size:\r
+ This parameter specifies the number of offset bytes to be written during the\r
+ write phase of the write-read transaction. This is typically the size of the\r
+ buffer pointed to by the addr_offset parameter.\r
+ \r
+ @param read_buffer:\r
+ This parameter is a pointer to the buffer where the data read from the I2C\r
+ slave will be stored.\r
+ \r
+ @param read_size:\r
+ This parameter specifies the number of bytes to read from the target I2C\r
+ slave device. This size must not exceed the size of the buffer pointed to by\r
+ the read_buffer parameter.\r
+ \r
+ @param options:\r
+ The options parameter is used to indicate if the I2C bus should be released\r
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS\r
+ constant for the options parameter causes a STOP bit to be generated at the\r
+ end of the write-read transaction causing the bus to be released for other\r
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter\r
+ prevents a STOP bit from being generated at the end of the write-read\r
+ transaction, preventing other I2C devices from initiating a bus transaction.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_DUMMY_ADDR 0x10u\r
+ #define TX_LENGTH 16u\r
+ #define RX_LENGTH 8u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ uint8_t rx_buffer[RX_LENGTH];\r
+ uint8_t read_length = RX_LENGTH; \r
+ uint8_t tx_buffer[TX_LENGTH];\r
+ uint8_t write_length = TX_LENGTH; \r
+ \r
+ void main( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ i2c_status_t status;\r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,\r
+ rx_buffer, read_length, I2C_RELEASE_BUS );\r
+ \r
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );\r
+ }\r
+ @endcode\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
+/*-------------------------------------------------------------------------*//**\r
+ I2C status\r
+ ------------------------------------------------------------------------------\r
+ This function indicates the current state of a CoreI2C channel.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ ------------------------------------------------------------------------------\r
+ @return\r
+ The return value indicates the current state of a CoreI2C channel or the\r
+ outcome of the previous transaction if no transaction is in progress. \r
+ Possible return values are:\r
+ I2C_SUCCESS\r
+ The last I2C transaction has completed successfully. \r
+ I2C_IN_PROGRESS\r
+ There is an I2C transaction in progress.\r
+ I2C_FAILED\r
+ The last I2C transaction failed.\r
+ I2C_TIMED_OUT\r
+ The request has failed to complete in the allotted time. \r
+ \r
+ Example:\r
+ @code\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )\r
+ {\r
+ // Do something useful while waiting for I2C operation to complete\r
+ our_i2c_busy_task();\r
+ }\r
+ \r
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )\r
+ {\r
+ // Something went wrong... \r
+ our_i2c_error_recovery( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+i2c_status_t I2C_get_status\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ Wait for I2C transaction completion.\r
+ ------------------------------------------------------------------------------\r
+ This function waits for the current I2C transaction to complete. The return\r
+ value indicates whether the last I2C transaction was successful or not.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of\r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ @param timeout_ms:\r
+ The timeout_ms parameter specified the delay within which the current I2C \r
+ transaction is expected to complete. The time out delay is given in \r
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current\r
+ transaction has not completed after the time out delay has expired. This\r
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()\r
+ must not time out.\r
+ ------------------------------------------------------------------------------\r
+ @return\r
+ The return value indicates the outcome of the last I2C transaction. It can\r
+ be one of the following: \r
+ I2C_SUCCESS\r
+ The last I2C transaction has completed successfully.\r
+ I2C_FAILED\r
+ The last I2C transaction failed.\r
+ I2C_TIMED_OUT\r
+ The last transaction failed to complete within the time out delay given\r
+ as second parameter.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_DUMMY_ADDR 0x10u\r
+ #define DATA_LENGTH 16u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t rx_buffer[DATA_LENGTH];\r
+ uint8_t read_length = DATA_LENGTH; \r
+\r
+ void main( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ i2c_status_t status;\r
+ \r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Read data from Channel 0 of CoreI2C instance.\r
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,\r
+ I2C_RELEASE_BUS );\r
+ \r
+ // Wait for completion and record the outcome\r
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );\r
+ }\r
+ @endcode\r
+ */\r
+i2c_status_t I2C_wait_complete\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint32_t timeout_ms\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ Time out delay expiration.\r
+ ------------------------------------------------------------------------------\r
+ This function is used to control the expiration of the time out delay\r
+ specified as a parameter to the I2C_wait_complete() function. It must be\r
+ called from the interrupt service routine of a periodic interrupt source such\r
+ as the Cortex-M3 SysTick timer interrupt. It takes the period of the interrupt\r
+ source as its ms_since_last_tick parameter and uses it as the time base for\r
+ the I2C_wait_complete() function\92s time out delay.\r
+ \r
+ Note: This function does not need to be called if the I2C_wait_complete()\r
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.\r
+ Note: If this function is not called then the I2C_wait_complete() function\r
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it\r
+ will not time out.\r
+ Note: If this function is being called from an interrupt handler (e.g SysTick)\r
+ it is important that the calling interrupt have a lower priority than\r
+ the CoreI2C interrupt(s) to ensure any updates to shared data are\r
+ protected.\r
+ \r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ @param ms_since_last_tick:\r
+ The ms_since_last_tick parameter specifies the number of milliseconds that\r
+ elapsed since the last call to I2C_system_tick(). This parameter would\r
+ typically be a constant specifying the interrupt rate of a timer used to\r
+ generate system ticks.\r
+ ------------------------------------------------------------------------------\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ The example below shows an example of how the I2C_system_tick() function\r
+ would be called in a Cortex-M3 based system. I2C_system_tick() is called for\r
+ each I2C channel from the Cortex-M3 SysTick timer interrupt service routine.\r
+ The SysTick is configured to generate an interrupt every 10 milliseconds in\r
+ the example below.\r
+ @code\r
+ #define SYSTICK_INTERVAL_MS 10\r
+ \r
+ void SysTick_Handler(void)\r
+ {\r
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);\r
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_system_tick\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint32_t ms_since_last_tick\r
+);\r
+\r
+/*******************************************************************************\r
+ *******************************************************************************\r
+ * \r
+ * Slave specific functions\r
+ * \r
+ * The following functions are only used within the implementation of an I2C\r
+ * slave device.\r
+ */\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave transmit buffer configuration.\r
+ ------------------------------------------------------------------------------\r
+ This function specifies the memory buffer holding the data that will be sent\r
+ to the I2C master when this CoreI2C channel is the target of an I2C read or\r
+ write-read transaction.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param tx_buffer:\r
+ This parameter is a pointer to the memory buffer holding the data to be\r
+ returned to the I2C master when this CoreI2C channel is the target of an\r
+ I2C read or write-read transaction.\r
+ \r
+ @param tx_size:\r
+ Size of the transmit buffer pointed to by the tx_buffer parameter.\r
+\r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SLAVE_TX_BUFFER_SIZE 10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,\r
+ 6, 7, 8, 9, 10 };\r
+\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, I2C serial\r
+ // address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Specify the transmit buffer containing the data that will be\r
+ // returned to the master during read and write-read transactions.\r
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer, \r
+ sizeof(g_slave_tx_buffer) );\r
+ }\r
+ @endcode\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
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave receive buffer configuration.\r
+ ------------------------------------------------------------------------------\r
+ This function specifies the memory buffer that will be used by the CoreI2C\r
+ channel to receive data when it is a slave. This buffer is the memory where\r
+ data will be stored when the CoreI2C channel is the target of an I2C master\r
+ write transaction (i.e. when it is the slave).\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param rx_buffer:\r
+ This parameter is a pointer to the memory buffer allocated by the caller\r
+ software to be used as a slave receive buffer.\r
+ \r
+ @param rx_size:\r
+ Size of the slave receive buffer. This is the amount of memory that is\r
+ allocated to the buffer pointed to by rx_buffer.\r
+ Note: This buffer size indirectly specifies the maximum I2C write\r
+ transaction length this CoreI2C channel can be the target of. This\r
+ is because this CoreI2C channel responds to further received\r
+ bytes with a non-acknowledge bit (NACK) as soon as its receive\r
+ buffer is full. This causes the write transaction to fail.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SLAVE_RX_BUFFER_SIZE 10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];\r
+\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, I2C serial\r
+ // address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Specify the buffer used to store the data written by the I2C master.\r
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer, \r
+ sizeof(g_slave_rx_buffer) );\r
+ }\r
+ @endcode\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
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave memory offset length configuration.\r
+ ------------------------------------------------------------------------------\r
+ This function is used as part of the configuration of a CoreI2C channel for\r
+ operation as a slave supporting write-read transactions. It specifies the\r
+ number of bytes expected as part of the write phase of a write-read\r
+ transaction. The bytes received during the write phase of a write-read\r
+ transaction will be interpreted as an offset into the slave's transmit buffer.\r
+ This allows random access into the I2C slave transmit buffer from a remote\r
+ I2C master.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param offset_length:\r
+ The offset_length parameter configures the number of bytes to be interpreted\r
+ by the CoreI2C slave as a memory offset value during the write phase of\r
+ write-read transactions. The maximum value for the offset_length parameter\r
+ is two. The value of offset_length has the following effect on the \r
+ interpretation of the received data.\r
+ \r
+ If offset_length is 0, the offset into the transmit buffer is fixed at 0.\r
+ \r
+ If offset_length is 1, a single byte of received data is interpreted as an\r
+ unsigned 8 bit offset value in the range 0 to 255.\r
+ \r
+ If offset_length is 2, 2 bytes of received data are interpreted as an\r
+ unsigned 16 bit offset value in the range 0 to 65535. The first byte\r
+ received in this case provides the high order bits of the offset and\r
+ the second byte provides the low order bits.\r
+ \r
+ If the number of bytes received does not match the non 0 value of\r
+ offset_length the transmit buffer offset is set to 0.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SLAVE_TX_BUFFER_SIZE 10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,\r
+ 6, 7, 8, 9, 10 };\r
+\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, I2C serial\r
+ // address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer, \r
+ sizeof(g_slave_tx_buffer) );\r
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );\r
+ }\r
+ @endcode \r
+ */\r
+void I2C_set_slave_mem_offset_length\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t offset_length\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C write handler registration. \r
+ ------------------------------------------------------------------------------\r
+ Register the function that is called to process the data written to this\r
+ CoreI2C channel when it is the slave in an I2C write transaction.\r
+ Note: If a write handler is registered, it is called on completion of the\r
+ write phase of a write-read transaction and responsible for processing\r
+ the received data in the slave receive buffer and populating the slave\r
+ transmit buffer with the data that will be transmitted to the I2C master\r
+ as part of the read phase of the write-read transaction. If a write\r
+ handler is not registered, the write data of a write read transaction is\r
+ interpreted as an offset into the slave\92s transmit buffer and handled by\r
+ the driver.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param handler:\r
+ Pointer to the function that will process the I2C write request.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SLAVE_TX_BUFFER_SIZE 10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,\r
+ 6, 7, 8, 9, 10 };\r
+\r
+ // local function prototype\r
+ void slave_write_handler\r
+ (\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t * p_rx_data,\r
+ uint16_t rx_size\r
+ );\r
+\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, I2C serial\r
+ // address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer, \r
+ sizeof(g_slave_tx_buffer) );\r
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );\r
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );\r
+ }\r
+ @endcode \r
+*/\r
+void I2C_register_write_handler\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ i2c_slave_wr_handler_t handler\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave enable.\r
+ ------------------------------------------------------------------------------\r
+ This function enables slave mode operation for a CoreI2C channel. It enables \r
+ the CoreI2C slave to receive data when it is the target of an I2C read, write\r
+ or write-read transaction.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return none.\r
+\r
+ Example:\r
+ @code\r
+ // Enable I2C slave\r
+ I2C_enable_slave( &g_i2c_inst );\r
+ @endcode\r
+ */\r
+void I2C_enable_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave disable.\r
+ ------------------------------------------------------------------------------\r
+ This function disables slave mode operation for a CoreI2C channel. It stops\r
+ the CoreI2C slave acknowledging I2C read, write or write-read transactions\r
+ targeted at it.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return none.\r
+\r
+ Example:\r
+ @code\r
+ // Disable I2C slave\r
+ I2C_disable_slave( &g_i2c_inst );\r
+ @endcode\r
+ */\r
+void I2C_disable_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+/*-------------------------------------------------------------------------*//**\r
+ Set I2C slave second address.\r
+ ------------------------------------------------------------------------------\r
+ The function I2C_set_slave_second_addr() sets the secondary slave address for\r
+ a CoreI2C slave device. This is an additional slave address which might be\r
+ required in certain applications, for example to enable fail-safe operation in\r
+ a system. As the CoreI2C device supports 7-bit addressing, the highest value\r
+ which can be assigned to second slave address is 127 (0x7F).\r
+ Note: 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
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param second_slave_addr:\r
+ The second_slave_addr parameter is the secondary slave address of the I2C\r
+ device.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SECOND_SLAVE_ADDR 0x20u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, primary I2C\r
+ // serial address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_set_slave_second_addr\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t second_slave_addr\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ Disable second slave address.\r
+ ------------------------------------------------------------------------------\r
+ The function I2C_disable_slave_second_addr() disables the secondary slave\r
+ address of the CoreI2C slave device. \r
+ Note: This version of the driver only supports CoreI2C hardware configured\r
+ with a programmable second slave address.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ i2c_instance_t g_i2c_inst;\r
+ I2C_disable_slave_second_addr( &g_i2c_inst);\r
+ @endcode\r
+ */\r
+void I2C_disable_slave_second_addr\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_set_gca() function is used to set the general call acknowledgement bit\r
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave\r
+ device respond to a general call or broadcast message from an I2C master.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ // Enable recognition of the General Call Address\r
+ I2C_set_gca( &g_i2c_inst ); \r
+ @endcode\r
+ */\r
+void I2C_set_gca\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_clear_gca() function is used to clear the general call acknowledgement\r
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave\r
+ device responding to any general call or broadcast message from the master.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ // Disable recognition of the General Call Address\r
+ I2C_clear_gca( &g_i2c_inst );\r
+ @endcode\r
+ */\r
+\r
+void I2C_clear_gca\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*------------------------------------------------------------------------------\r
+ I2C SMBUS specific APIs\r
+ ----------------------------------------------------------------------------*/\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a\r
+ CoreI2C channel.\r
+ Note: This and any of the other SMBus related functionality will only have an\r
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic\r
+ option checked.\r
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option\r
+ checked this function will enable the IPMI 3mS SCL low timeout but none\r
+ of the other SMBus functions will have any effect.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void system_init( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst);\r
+ }\r
+ @endcode \r
+ */\r
+void I2C_smbus_init\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel\92s \r
+ SMBSUS and SMBALERT SMBus interrupts.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param irq_type\r
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.\r
+ The two possible interrupts are:\r
+ I2C_SMBALERT_IRQ\r
+ I2C_SMBSUS_IRQ\r
+ To enable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.\r
+ \r
+ @return\r
+ none\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+ \r
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts\r
+ I2C_enable_smbus_irq( &g_i2c_inst,\r
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_enable_smbus_irq\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t irq_type\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_disable_smbus_irq() function is used to disable the CoreI2C channel\92s\r
+ SMBSUS and SMBALERT SMBus interrupts.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param irq_type\r
+ The irq_type specifies the SMBUS interrupt(s) which will be disabled.\r
+ The two possible interrupts are:\r
+ I2C_SMBALERT_IRQ\r
+ I2C_SMBSUS_IRQ\r
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+ \r
+ // Enable both SMBALERT & SMBSUS interrupts\r
+ I2C_enable_smbus_irq( &g_i2c_inst,\r
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));\r
+ \r
+ ... \r
+\r
+ // Disable the SMBALERT interrupt\r
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_disable_smbus_irq\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t irq_type\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The function I2C_suspend_smbus_slave() forces any SMBUS slave devices\r
+ connected to a CoreI2C channel into power down or suspend mode by asserting\r
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this\r
+ case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // suspend SMBus slaves\r
+ I2C_suspend_smbus_slave( &g_i2c_inst );\r
+\r
+ ...\r
+\r
+ // Re-enable SMBus slaves\r
+ I2C_resume_smbus_slave( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_suspend_smbus_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The function I2C_resume_smbus_slave() de-asserts the CoreI2C channel's SMBSUS\r
+ signal to take any connected slave devices out of suspend mode. The CoreI2C\r
+ channel is the SMBus master in this case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // suspend SMBus slaves\r
+ I2C_suspend_smbus_slave( &g_i2c_inst );\r
+\r
+ ...\r
+\r
+ // Re-enable SMBus slaves\r
+ I2C_resume_smbus_slave( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_resume_smbus_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection\r
+ by forcing SCLK low for 35mS. The reset is automatically cleared after 35ms\r
+ have elapsed. The CoreI2C channel is the SMBus master in this case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // Make sure the SMBus channel is in a known state by resetting it\r
+ I2C_reset_smbus( &g_i2c_inst ); \r
+ }\r
+ @endcode\r
+ */\r
+void I2C_reset_smbus\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_set_smbus_alert() function is used to force master communication with\r
+ an I2C slave device by asserting the CoreI2C channel\92s SMBALERT signal. The\r
+ CoreI2C channel is the SMBus slave in this case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // Get the SMBus masters attention\r
+ I2C_set_smbus_alert( &g_i2c_inst );\r
+\r
+ ...\r
+\r
+ // Once we are happy, drop the alert\r
+ I2C_clear_smbus_alert( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_set_smbus_alert\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_clear_smbus_alert() function is used de-assert the CoreI2C channel\92s \r
+ SMBALERT signal once a slave device has had a response from the master. The\r
+ CoreI2C channel is the SMBus slave in this case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // Get the SMBus masters attention\r
+ I2C_set_smbus_alert( &g_i2c_inst );\r
+\r
+ ...\r
+\r
+ // Once we are happy, drop the alert\r
+ I2C_clear_smbus_alert( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_clear_smbus_alert\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_get_irq_status function returns information on which interrupts are\r
+ currently pending in a CoreI2C channel.\r
+ The interrupts supported by CoreI2C are:\r
+ * SMBUSALERT\r
+ * SMBSUS\r
+ * INTR\r
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ and I2C_INTR_IRQ are\r
+ provided for use with this function.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ This function returns the status of the CoreI2C channel\92s interrupts as a \r
+ single byte bitmap where a bit is set to indicate a pending interrupt.\r
+ The following are the bit positions associated with each interrupt type:\r
+ Bit 0 - SMBUS_ALERT_IRQ\r
+ Bit 1 - SMBSUS_IRQ\r
+ Bit 2 - INTR_IRQ\r
+ It returns 0, if there are no pending interrupts.\r
+\r
+ Example\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;\r
+ uint8_t pending_irq = 0u;\r
+ \r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq\r
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );\r
+\r
+ // Get I2C IRQ type\r
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );\r
+\r
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.\r
+ // So pending_irq will return status of both the IRQs\r
+\r
+ if( pending_irq & I2C_SMBALERT_IRQ )\r
+ {\r
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list\r
+ }\r
+ if( pending_irq & I2C_INTR_IRQ )\r
+ {\r
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list\r
+ }\r
+ }\r
+ @endcode\r
+ */\r
+uint8_t I2C_get_irq_status\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_set_user_data() function is used to allow the association of a block\r
+ of application specific data with a CoreI2C channel. The composition of the \r
+ data block is an application matter and the driver simply provides the means\r
+ for the application to set and retrieve the pointer. This may for example be\r
+ used to provide additional channel specific information to the slave write \r
+ handler.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param p_user_data:\r
+ The p_user_data parameter is a pointer to the user specific data block for\r
+ this channel. It is defined as void * as the driver does not know the actual\r
+ type of data being pointed to and simply stores the pointer for later\r
+ retrieval by the application.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ app_data_t channel_xdata;\r
+ \r
+ void main( void )\r
+ {\r
+ app_data_t *p_xdata;\r
+\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Store location of user data in instance structure\r
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );\r
+\r
+ ...\r
+\r
+ // Retrieve location of user data and do some work on it\r
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );\r
+ if( NULL != p_xdata )\r
+ {\r
+ p_xdata->foo = 123;\r
+ }\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_set_user_data\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ void * p_user_data\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_get_user_data() function is used to allow the retrieval of the address\r
+ of a block of application specific data associated with a CoreI2C channel.\r
+ The composition of the data block is an application matter and the driver \r
+ simply provides the means for the application to set and retrieve the pointer.\r
+ This may for example be used to provide additional channel specific\r
+ information to the slave write handler.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ This function returns a pointer to the user specific data block for this \r
+ channel. It is defined as void * as the driver does not know the actual type\r
+ of data being pointed. If no user data has been registered for this channel\r
+ a NULL pointer is returned.\r
+ \r
+ Example\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ app_data_t channel_xdata;\r
+ \r
+ void main( void )\r
+ {\r
+ app_data_t *p_xdata;\r
+\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Store location of user data in instance structure\r
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );\r
+\r
+ ...\r
+ \r
+ // Retrieve location of user data and do some work on it\r
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );\r
+ if( NULL != p_xdata )\r
+ {\r
+ p_xdata->foo = 123;\r
+ }\r
+ }\r
+ @endcode\r
+ */\r
+void * I2C_get_user_data\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r