ISF  2.1
Intelligent Sensing Framework for Kinetis with Processor Expert
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
isf_i2c_master_adapter.c
Go to the documentation of this file.
1 /*!
2 ********************************************************************************
3 * File: isf_i2c_master_adapter.c
4 *
5 * Copyright (c) 2012-2014, Freescale Semiconductor, Inc.
6 *
7 *******************************************************************************/
8 /*!
9 * @file isf_i2c_master_adapter.c
10 * @brief \b isf_i2c_master_adapter.c implements i2c master protocol adapter.
11 */
12 #include "isf_target.h"
13 #include <lwevent.h>
14 #include <mqxlite.h>
15 #include <mutex.h>
16 #include "lwmem.h"
17 #include "isf.h"
18 #include "isf_i2c_master_adapter.h"
19 #include "fsl_i2c_master_driver.h"
20 #include "isf_devmsg.h"
21 #include "isf_util.h"
22 #include "isf_protocol_adapter.h"
23 #define I2C_MASTER_ADAPTER_LOCK_DEFAULT (0)
24 
25 static isf_status_t bus_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout );
26 static isf_status_t bus_unlock(busHandle_t *apBusHandle);
27 
28 extern MUTEX_STRUCT i2c_Master_mutexHandler[];
30 extern uint8 gSys_NumI2cBuses;
31 
32 /*******************************************************************************
33  * Functions
34  ******************************************************************************/
35 /***********************************************************************
36  *
37  * Function Name : i2c_master_adapter_init
38  * Description : This function Initialize the I2C master mode driver.
39  * It initialize the bus handle, reset all the registers and configure the control register for interrupt.
40  * This also initialize the lock functionality.
41  *
42  ***************************************************************************/
44 {
45  MUTEX_ATTR_STRUCT mutexattr;
46 
47  if( gSys_NumI2cBuses <= aBusId){
48  return COMM_ERROR_NOEXIST ;
49  }
50  // Initialize the bus handle.
51 
52  _int_disable();
53 
54  i2c_Master_busHandle_t *pBusHandle = &i2c_master_busHandle[aBusId];
55 
57  apBusHandle->pLock = &i2c_Master_mutexHandler[aBusId];
58  if(pBusHandle->busState == COMM_STATE_NO_INIT){
59  if (MQX_OK == _mutatr_init(&mutexattr)) {
60  _mutatr_set_sched_protocol(&mutexattr, MUTEX_PRIO_INHERIT);
61  }else{
62  _int_enable();
63  return COMM_ERROR_INIT;
64  }
65  if(MQX_OK != _mutex_init(apBusHandle->pLock, &mutexattr)){
66  _int_enable();
67  return COMM_ERROR_INIT;
68  }
69  //initialize the driver.
70  i2c_master_init(aBusId, &pBusHandle->master);
71  pBusHandle->busState = COMM_STATE_INIT;
72  }
73  apBusHandle->pHandle = pBusHandle;
74  _int_enable();
75  return ISF_SUCCESS;
76 }
77 
78 /***********************************************************************
79  *
80  * Function Name : i2c_master_adapter_configure
81  * Description : This function configure the of the I2C master mode driver for baudrate and timeout.
82  *
83  ***************************************************************************/
84 isf_status_t i2c_master_adapter_configure(busHandle_t *apBusHandle, void* apBusConfig)
85 {
87  i2c_device_t device;
88  if((apBusHandle == NULL) || (apBusConfig == NULL)){
89  return COMM_ERROR_NULL_PTR;
90  }
91 
92  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
93  if((pBusHandle->busState != COMM_STATE_INIT) && (pBusHandle->busState != COMM_STATE_STOPPED)){
94  return COMM_ERROR_STOP;
95  }
96  i2c_Master_BusConfig_t* pBusConfig = (i2c_Master_BusConfig_t*)apBusConfig;
97  ret = bus_lock(apBusHandle, pBusConfig->timeout);
98  device.baudRate_kbps = pBusConfig->defaultSpeed;
99  // Configure the baud rate.
100  ret = i2c_master_configure_bus(&pBusHandle->master, &device);
101  pBusHandle->master.lastBaudRate_kbps = pBusConfig->defaultSpeed;
102  pBusHandle->busConfig = *pBusConfig;
103  //release the lock.
104  bus_unlock(apBusHandle);
105  return ret;
106 }
107 /***********************************************************************
108  *
109  * Function Name : i2c_master_adapter_get_state
110  * Description : This function provides the current state of the bus for a given i2c bus.
111  *
112  ***************************************************************************/
114 {
115  if(apBusHandle == NULL){
116  return COMM_ERROR_NULL_PTR;
117  }
118  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
119  return pBusHandle->busState;
120 }
121 /***********************************************************************
122  *
123  * Function Name : i2c_master_adapter_get_config
124  * Description : This function provides the current configuration for a given i2c bus.
125  *
126  ***************************************************************************/
128 {
129  //verify the passed the parameter
130  if((apBusHandle == NULL) || (apBusConfig == NULL)){
131  return COMM_ERROR_NULL_PTR;
132  }
133  *((i2c_Master_BusConfig_t*)apBusConfig) = ((i2c_Master_busHandle_t *)apBusHandle->pHandle)->busConfig;
134  return ISF_SUCCESS;
135 }
136 /***********************************************************************
137  *
138  * Function Name : i2c_master_adapter_acquire_lock
139  * Description : This function provides explicit lock functionality for
140  * the multiple transactions.
141  * Note: It is important to explicit release by calling i2c_master_adapter_release_lock
142  * once the multi-transaction is done.
143  *
144  ***************************************************************************/
146 {
147  if(apBusHandle == NULL){
148  return COMM_ERROR_NULL_PTR;
149  }
151  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
152  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout);
153  return ret;
154 }
155 /***********************************************************************
156  *
157  * Function Name : i2c_master_adapter_release_lock
158  * Description : This function provides explicit release lock functionality for
159  * the multiple transactions.
160  *
161  ***************************************************************************/
163 {
164  if(apBusHandle == NULL){
165  return COMM_ERROR_NULL_PTR;
166  }
168  ret = bus_unlock(apBusHandle);
169  return ret;
170 }
171 /***********************************************************************
172  *
173  * Function Name : i2c_master_adapter_start
174  * Description : This function implements the start functionality of bus.
175  * Once the bus started the bus is ready to use.
176  *
177  ***************************************************************************/
179 {
180  if(apBusHandle == NULL){
181  return COMM_ERROR_NULL_PTR;
182  }
183  isf_status_t ret;
184  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
185 
186  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout);
187  i2c_hal_enable(pBusHandle->master.instance);
188  pBusHandle->busState = COMM_STATE_OK;
189  bus_unlock(apBusHandle);
190  return ret;
191 }
192 /***********************************************************************
193  *
194  * Function Name : i2c_master_adapter_stop
195  * Description : This function implements the stop functionality of bus.
196  * Once the bus stopped the bus is not ready for further use. It is necessary to start the bus again.
197  *
198  ***************************************************************************/
200 {
201  if(apBusHandle == NULL){
202  return COMM_ERROR_NULL_PTR;
203  }
204  isf_status_t ret;
205  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
206  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout);
207  i2c_hal_disable(pBusHandle->master.instance);
208  pBusHandle->busState = COMM_STATE_STOPPED;
209  bus_unlock(apBusHandle);
210  return ret;
211 }
212 /***********************************************************************
213  *
214  * Function Name : i2c_master_adapter_get_endpoint
215  * Description : This function uses to establish a communication endpoint
216  * between the devices for a given i2c bus. A bus can have multiple device connected.
217  * Each will be having separate a communication endpoint through which the master can talk the device.
218  *
219  ***************************************************************************/
220 isf_status_t i2c_master_adapter_get_endpoint(busHandle_t *apBusHandle, void *apDevice, void** apEndpointHandle)
221 {
222  isf_status_t ret;
223  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
224  i2c_device_t* pDevice = (i2c_device_t*)apDevice;
225  if((apBusHandle == NULL) || (apEndpointHandle == NULL)){
226  return COMM_ERROR_NULL_PTR;
227  }
228  // Cannot open if the bus is not started.
229  if(pBusHandle->busState != COMM_STATE_OK){
230  return COMM_ERROR_STOP;
231  }
232  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout);
233  if(ret != ISF_SUCCESS){
234  return ret;
235  }
236  i2c_Endpoint_t *pEndpoint = _lwmem_alloc_system_zero(sizeof(i2c_Endpoint_t));
237  uint8 tempBuff[1];
238  // Just make sure that a device can be accessed successfully.
239  ret = (isf_status_t)i2c_master_transfer(&pBusHandle->master, pDevice, kI2CRead, 0,
240  0, 1, (uint8*)&tempBuff, 1, NULL, pBusHandle->busConfig.timeout );
241 
242  bus_unlock(apBusHandle);
243  _int_disable();
244  if(ret == ISF_SUCCESS){
245  pEndpoint->device = *pDevice;
246  pEndpoint->pBusHandle = apBusHandle;
247  *apEndpointHandle = pEndpoint;
248  }else{
249  ret = COMM_ERROR_NOEXIST;
250  }
251  _int_enable();
252  return ret;
253 }
254 /***********************************************************************
255  *
256  * Function Name : i2c_master_adapter_release_endpoint
257  * Description : Its designed to release the communication endpoint.
258  * At this point there is nothing to implement.
259  *
260  ***************************************************************************/
261 
263 {
264  if(apEndpoint == NULL){
265  return COMM_ERROR_NULL_PTR;
266  }
267  _lwmem_free(apEndpoint);
268  return ISF_SUCCESS;
269 }
270 /***********************************************************************
271  *
272  * Function Name : i2c_master_adapter_write
273  * Description : The function provides write interface for the given i2c bus.
274  * It writes the data sequentially to the device byte at a time.
275  *
276  ***************************************************************************/
277 isf_status_t i2c_master_adapter_write(void* apEndpointHandle, int32 offset, void* pWriteBuffer, uint32 buffsize, uint32 nByteWrite, i2c_writeFlags_t aFlags)
278 {
279  if((NULL == apEndpointHandle) || (NULL == pWriteBuffer)){
280  return COMM_ERROR_NULL_PTR;
281  }
282  if(buffsize < nByteWrite){
283  return COMM_ERROR_BUF_SIZE;
284  }
285  isf_status_t ret;
286  i2c_Endpoint_t *pEndpoint = (i2c_Endpoint_t *)apEndpointHandle;
288  // Invalid bus state, cannot perform the write operation.
289  if(pBusHandle->busState != COMM_STATE_OK ){
290  return COMM_ERROR_INIT;
291  }
292 
293  ret = bus_lock(pEndpoint->pBusHandle, pBusHandle->busConfig.timeout);
294  if(ret != ISF_SUCCESS){
295  return ret;
296  }
297  // invoke the driver specfic read/write functions.
298  ret = i2c_master_transfer(&pBusHandle->master,&pEndpoint->device, kI2CWrite, aFlags,
299  offset, (offset == INVALID_OFFSET)? 0: 1, pWriteBuffer, nByteWrite, NULL, pBusHandle->busConfig.timeout );
300 
301  bus_unlock(pEndpoint->pBusHandle);
302  return ret;
303 
304  }
305 /***********************************************************************
306  *
307  * Function Name : i2c_master_adapter_write
308  * Description : The function provides read interface for the given i2c bus.
309  * It reads the data sequentially from the device byte at a time.
310  *
311  ***************************************************************************/
312 isf_status_t i2c_master_adapter_read(void* apEndpointHandle, int32 offset, void* pReadBuffer, uint32 buffsize, uint32 nByteRead, i2c_readFlags_t aFlags)
313 {
314 
315  if((NULL == apEndpointHandle) || (NULL == pReadBuffer)){
316  return COMM_ERROR_NULL_PTR;
317  }
318  if(buffsize < nByteRead){
319  return COMM_ERROR_BUF_SIZE;
320  }
321  isf_status_t ret;
322  i2c_Endpoint_t *pEndpoint = (i2c_Endpoint_t *)apEndpointHandle;
324  // Invalid bus state, cannot perform the read operation.
325  if(pBusHandle->busState != COMM_STATE_OK ){
326  return COMM_ERROR_INIT;
327  }
328  ret = bus_lock(pEndpoint->pBusHandle, pBusHandle->busConfig.timeout);
329  if(ret != ISF_SUCCESS){
330  return ret;
331  }
332  // invoke the driver specfic read/write functions.
333  ret = i2c_master_transfer(&pBusHandle->master,&pEndpoint->device, kI2CRead, aFlags,
334  offset, (offset == INVALID_OFFSET)? 0: 1, pReadBuffer, nByteRead, NULL, pBusHandle->busConfig.timeout );
335 
336  bus_unlock(pEndpoint->pBusHandle);
337 
338  return ret;
339 
340 }
341 /***********************************************************************
342  *
343  * Function Name : bus_lock
344  * Description : Internal function uses to lock the i2c bus.
345  * Each i2c bus has own lock that enables the concurrent access to bus safely.
346  * It uses mqx synchronization object mutex.
347  *
348  ***************************************************************************/
349  static isf_status_t bus_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout )
350  {
351  // Invalid bus.
352  if (NULL == apBusHandle->pLock){
353  return COMM_ERROR_LOCK;
354  }
355  //if there is a lock on the specific handler. should not take the mutex multiple time
356  // for the same handler
357  if (I2C_MASTER_ADAPTER_LOCK_DEFAULT == apBusHandle->nLock){
358  if(MQX_OK != _mutex_lock ((MUTEX_STRUCT*)apBusHandle->pLock)){
359  return COMM_ERROR_LOCK;
360  }
361  }
362  apBusHandle->nLock++;
363 
364  return ISF_SUCCESS;
365  }
366  /***********************************************************************
367  *
368  * Function Name : bus_unlock
369  * Description : Internal function uses to un-lock the i2c bus.
370  *
371  ***************************************************************************/
372 
373  static isf_status_t bus_unlock(busHandle_t *apBusHandle )
374  {
375  //if there is no lock associate with the handler
376  if(NULL == apBusHandle->pLock){
377  // No lock is associated with this bus.
378  return COMM_ERROR_LOCK;
379  }
380  if(0 == apBusHandle->nLock){
381  return ISF_SUCCESS;
382  }else if (I2C_MASTER_ADAPTER_LOCK_DEFAULT == --apBusHandle->nLock){
383  // release the resource
384  _mutex_unlock((MUTEX_STRUCT*)apBusHandle->pLock);
385  }
386 
387  return ISF_SUCCESS;
388  }
389 
390 
391 
392 
ISF board support header files.
unsigned char uint8
This defines uint8 as unsigned char.
Definition: isf_types.h:18
fsl_i2c_master_driver.h defines structures and types for the i2c master driver.
uint8 gSys_NumI2cBuses
isf_status_t i2c_master_adapter_read(void *apEndpointHandle, int32 offset, void *pReadBuffer, uint32 buffsize, uint32 nByteRead, i2c_readFlags_t aFlags)
This function reads from a i2c device.
isf_status_t i2c_master_adapter_release_lock(busHandle_t *apBusHandle)
This function releases exclusive bus access.
isf_status_t i2c_master_adapter_init(comm_Id_t aBusId, busHandle_t *apBusHandle)
This function initializes a i2c bus.
This structure defines the data bus handle.
isf_status_t i2c_master_adapter_configure(busHandle_t *apBusHandle, void *apBusConfig)
This function reconfigures an already initialized bus.
isf_status_t i2c_master_adapter_acquire_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout)
This function locks the bus for exclusive access.
Information necessary to communicate with an I2C slave device.
uint32 comm_Id_t
This type is for a numeric channel identifier- index into an array of channels in the system...
Definition: isf_comm.h:50
i2c_Master_BusConfig_t busConfig
This structure defines a device endpoint encapsulation for i2c handler.
isf_status_t i2c_master_adapter_start(busHandle_t *apBusHandle)
This function starts a bus.
unsigned long uint32
This defines uint32 as unsigned long.
Definition: isf_types.h:36
i2c_status_t i2c_master_configure_bus(i2c_master_t *master, const i2c_device_t *device)
Configure the I2C bus to access a device.
MUTEX_STRUCT i2c_Master_mutexHandler[]
#define I2C_MASTER_ADAPTER_LOCK_DEFAULT
isf_protocol_adapter.h defines the general interface definition for the protocol adapter.
void i2c_hal_disable(uint32 instance)
This function disables the HAL.
Definition: fsl_i2c_hal.c:40
isf_status_t i2c_master_adapter_release_endpoint(i2c_Endpoint_t *apEndpoint)
This function closes a particular endpoint.
The isf_util.h file contains the utility method declarations and macros.
isf_i2c_master_adapter.h defines the API definitions and types for the i2c master protocol adapter...
This structure is a declaration of a BusHandle type.
comm_Flags_t i2c_readFlags_t
isf_status_t i2c_master_adapter_write(void *apEndpointHandle, int32 offset, void *pWriteBuffer, uint32 buffsize, uint32 nByteWrite, i2c_writeFlags_t aFlags)
This function writes to a i2c device.
isf_status_t i2c_master_adapter_stop(busHandle_t *apBusHandle)
This function stops the given i2c bus.
comm_State_t i2c_master_adapter_get_state(busHandle_t *apBusHandle)
This function returns the current bus state.
uint32 isf_duration_t
ISF time duration in microseconds.
Definition: isf.h:59
long int32
This defines int32 as long.
Definition: isf_types.h:32
i2c_Master_busHandle_t i2c_master_busHandle[]
Main ISF header file. Contains code common to all ISF components.
void i2c_master_init(uint32_t instance, i2c_master_t *master)
Initialize the I2C master mode driver.
isf_status_t i2c_master_adapter_get_endpoint(busHandle_t *apBusHandle, void *apDevice, void **apEndpointHandle)
This function creates a endpoint for a device at a specified bus address.
i2c_status_t i2c_master_transfer(i2c_master_t *master, const i2c_device_t *device, i2c_direction_t direction, bool stopAfterTransfer, uint32_t subaddress, size_t subaddressLength, uint8_t *data, size_t dataLength, size_t *actualLengthTransferred, uint32_t timeout_ms)
Perform a blocking read or write transaction on the I2C bus.
int32 isf_status_t
ISF return status type.
Definition: isf.h:51
enum comm_State_vals comm_State_t
This enum holds an enumerated value describing the state of a channel.
Definition: isf_comm.h:53
#define INVALID_OFFSET
This macro defines the invalid offset for the read and write functions.
Definition: isf_devmsg.h:67
comm_Flags_t i2c_writeFlags_t
isf_devmsg.h defines the API definitions and types for the Intelligent Sensing (ISF) Device Messaging...
isf_status_t i2c_master_adapter_get_config(busHandle_t *apBusHandle, void *apBusConfig)
This function returns the current bus configuration.
void i2c_hal_enable(uint32 instance)
This function enables the HAL.
Definition: fsl_i2c_hal.c:27