ISF  2.2 rev 5
Intelligent Sensing Framework for Kinetis with Processor Expert
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) 2015, 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.h"
13 #include "isf_i2c_master_adapter.h"
14 #include "fsl_i2c_master_driver.h"
15 #include "isf_devmsg.h"
16 #include "isf_util.h"
17 #include "isf_protocol_adapter.h"
18 #define I2C_MASTER_ADAPTER_LOCK_DEFAULT (0)
19 
20 static isf_status_t bus_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout );
21 static isf_status_t bus_unlock(busHandle_t *apBusHandle);
22 extern mutex_t i2c_Master_mutexHandler[];
24 extern uint8 gSys_NumI2cBuses;
25 
26 /*******************************************************************************
27  * Functions
28  ******************************************************************************/
29 /***********************************************************************
30  *
31  * Function Name : i2c_master_adapter_init
32  * Description : This function Initialize the I2C master mode driver.
33  * It initialize the bus handle, reset all the registers and configure the control register for interrupt.
34  * This also initialize the lock functionality.
35  *
36  ***************************************************************************/
38 {
39 
40  if( gSys_NumI2cBuses <= aBusId){
41  return COMM_ERROR_NOEXIST ;
42  }
43  // Initialize the bus handle.
44 
45  OSA_EnterCritical(kCriticalDisableInt);
46 
47  i2c_Master_busHandle_t *pBusHandle = &i2c_master_busHandle[aBusId];
49  apBusHandle->pLock = &i2c_Master_mutexHandler[aBusId];
50 
51  if(pBusHandle->busState == COMM_STATE_NO_INIT){
52  OSA_MutexCreate(apBusHandle->pLock);
53  //Driver initial is already done. So there is no need of calling master I2C_DRV_MasterInit again here.
54  pBusHandle->busInstance = aBusId;
55  pBusHandle->busState = COMM_STATE_INIT;
56  }
57  apBusHandle->pHandle = pBusHandle;
58  OSA_ExitCritical(kCriticalDisableInt);
59 
60  return ISF_SUCCESS;
61 }
62 
63 /***********************************************************************
64  *
65  * Function Name : i2c_master_adapter_configure
66  * Description : This function configure the of the I2C master mode driver for baudrate and timeout.
67  *
68  ***************************************************************************/
69 isf_status_t i2c_master_adapter_configure(busHandle_t *apBusHandle, void* apBusConfig)
70 {
72  i2c_device_t device;
73  if((apBusHandle == NULL) || (apBusConfig == NULL)){
74  return COMM_ERROR_NULL_PTR;
75  }
76 
77  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
78  if((pBusHandle->busState != COMM_STATE_INIT) && (pBusHandle->busState != COMM_STATE_STOPPED)){
79  return COMM_ERROR_STOP;
80  }
81  i2c_Master_BusConfig_t* pBusConfig = (i2c_Master_BusConfig_t*)apBusConfig;
82  ret = bus_lock(apBusHandle, pBusConfig->timeout);
83  device.baudRate_kbps = pBusConfig->defaultSpeed;
84  // Configure the baud rate.
85  I2C_DRV_MasterSetBaudRate(pBusHandle->busInstance, &device);
86  pBusHandle->master.lastBaudRate_kbps = pBusConfig->defaultSpeed;
87  pBusHandle->busConfig = *pBusConfig;
88  //release the lock.
89  bus_unlock(apBusHandle);
90  return ret;
91 }
92 /***********************************************************************
93  *
94  * Function Name : i2c_master_adapter_get_state
95  * Description : This function provides the current state of the bus for a given i2c bus.
96  *
97  ***************************************************************************/
99 {
100  if(apBusHandle == NULL){
101  return COMM_ERROR_NULL_PTR;
102  }
103  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
104  return pBusHandle->busState;
105 }
106 /***********************************************************************
107  *
108  * Function Name : i2c_master_adapter_get_config
109  * Description : This function provides the current configuration for a given i2c bus.
110  *
111  ***************************************************************************/
113 {
114  //verify the passed the parameter
115  if((apBusHandle == NULL) || (apBusConfig == NULL)){
116  return COMM_ERROR_NULL_PTR;
117  }
118  *((i2c_Master_BusConfig_t*)apBusConfig) = ((i2c_Master_busHandle_t *)apBusHandle->pHandle)->busConfig;
119  return ISF_SUCCESS;
120 }
121 /***********************************************************************
122  *
123  * Function Name : i2c_master_adapter_acquire_lock
124  * Description : This function provides explicit lock functionality for
125  * the multiple transactions.
126  * Note: It is important to explicit release by calling i2c_master_adapter_release_lock
127  * once the multi-transaction is done.
128  *
129  ***************************************************************************/
131 {
132  if(apBusHandle == NULL){
133  return COMM_ERROR_NULL_PTR;
134  }
136  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
137  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout);
138  return ret;
139 }
140 /***********************************************************************
141  *
142  * Function Name : i2c_master_adapter_release_lock
143  * Description : This function provides explicit release lock functionality for
144  * the multiple transactions.
145  *
146  ***************************************************************************/
148 {
149  if(apBusHandle == NULL){
150  return COMM_ERROR_NULL_PTR;
151  }
153  ret = bus_unlock(apBusHandle);
154  return ret;
155 }
156 /***********************************************************************
157  *
158  * Function Name : i2c_master_adapter_start
159  * Description : This function implements the start functionality of bus.
160  * Once the bus started the bus is ready to use.
161  *
162  ***************************************************************************/
164 {
165  if(apBusHandle == NULL){
166  return COMM_ERROR_NULL_PTR;
167  }
168  isf_status_t ret;
169  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
170 
171  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout);
172  I2C_Type* base = g_i2cBase[pBusHandle->busInstance];
173  I2C_HAL_Enable(base);
174  pBusHandle->busState = COMM_STATE_OK;
175  bus_unlock(apBusHandle);
176  return ret;
177 }
178 /***********************************************************************
179  *
180  * Function Name : i2c_master_adapter_stop
181  * Description : This function implements the stop functionality of bus.
182  * Once the bus stopped the bus is not ready for further use. It is necessary to start the bus again.
183  *
184  ***************************************************************************/
186 {
187  if(apBusHandle == NULL){
188  return COMM_ERROR_NULL_PTR;
189  }
190  isf_status_t ret;
191  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
192  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout);
193  I2C_Type* base = g_i2cBase[pBusHandle->busInstance];
194  I2C_HAL_Disable(base);
195  pBusHandle->busState = COMM_STATE_STOPPED;
196  bus_unlock(apBusHandle);
197  return ret;
198 }
199 /***********************************************************************
200  *
201  * Function Name : i2c_master_adapter_get_endpoint
202  * Description : This function uses to establish a communication endpoint
203  * between the devices for a given i2c bus. A bus can have multiple device connected.
204  * Each will be having separate a communication endpoint through which the master can talk the device.
205  *
206  ***************************************************************************/
207 isf_status_t i2c_master_adapter_get_endpoint(busHandle_t *apBusHandle, void *apDevice, void** apEndpointHandle)
208 {
209  isf_status_t ret;
210  i2c_Master_busHandle_t *pBusHandle = (i2c_Master_busHandle_t *)apBusHandle->pHandle;
211  i2c_device_t* pDevice = (i2c_device_t*)apDevice;
212  if((apBusHandle == NULL) || (apEndpointHandle == NULL)){
213  return COMM_ERROR_NULL_PTR;
214  }
215  // Cannot open if the bus is not started.
216  if(pBusHandle->busState != COMM_STATE_OK){
217  return COMM_ERROR_STOP;
218  }
219  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout);
220  if(ret != ISF_SUCCESS){
221  return ret;
222  }
223 
224  i2c_Endpoint_t *pEndpoint = OSA_MemAllocZero(sizeof(i2c_Endpoint_t));
225  uint8 tempBuff[1];
226 
227  const uint8_t cmdBuff[] = {0}; // dummy read
228  ret = I2C_DRV_MasterReceiveDataBlocking(pBusHandle->busInstance, pDevice, cmdBuff, sizeof(cmdBuff),
229  tempBuff, sizeof(tempBuff), pBusHandle->busConfig.timeout );
230 
231  bus_unlock(apBusHandle);
232  OSA_EnterCritical(kCriticalDisableInt);
233  if(ret == ISF_SUCCESS){
234  pEndpoint->device = *pDevice;
235  pEndpoint->pBusHandle = apBusHandle;
236  *apEndpointHandle = pEndpoint;
237  }else{
238  ret = COMM_ERROR_NOEXIST;
239  }
240 
241  OSA_ExitCritical(kCriticalDisableInt);
242  return ret;
243 }
244 /***********************************************************************
245  *
246  * Function Name : i2c_master_adapter_release_endpoint
247  * Description : Its designed to release the communication endpoint.
248  * At this point there is nothing to implement.
249  *
250  ***************************************************************************/
251 
253 {
254  if(apEndpoint == NULL){
255  return COMM_ERROR_NULL_PTR;
256  }
257 
258  OSA_MemFree(apEndpoint);
259 
260  return ISF_SUCCESS;
261 }
262 /***********************************************************************
263  *
264  * Function Name : i2c_master_adapter_write
265  * Description : The function provides write interface for the given i2c bus.
266  * It writes the data sequentially to the device byte at a time.
267  *
268  ***************************************************************************/
269 isf_status_t i2c_master_adapter_write(void* apEndpointHandle, int32 offset, void* pWriteBuffer, uint32 buffsize, uint32 nByteWrite, i2c_writeFlags_t aFlags)
270 {
271  if((NULL == apEndpointHandle) || (NULL == pWriteBuffer)){
272  return COMM_ERROR_NULL_PTR;
273  }
274  if(buffsize < nByteWrite){
275  return COMM_ERROR_BUF_SIZE;
276  }
277  isf_status_t ret;
278  i2c_Endpoint_t *pEndpoint = (i2c_Endpoint_t *)apEndpointHandle;
280  // Invalid bus state, cannot perform the write operation.
281  if(pBusHandle->busState != COMM_STATE_OK ){
282  return COMM_ERROR_INIT;
283  }
284 
285  ret = bus_lock(pEndpoint->pBusHandle, pBusHandle->busConfig.timeout);
286  if(ret != ISF_SUCCESS){
287  return ret;
288  }
289 
290  ret = I2C_DRV_MasterSendDataBlocking(pBusHandle->busInstance, &pEndpoint->device, (offset != INVALID_OFFSET)? (const uint8_t*)&offset : NULL,
291  1, (const uint8_t *)pWriteBuffer, nByteWrite, pBusHandle->busConfig.timeout);
292 
293 
294  bus_unlock(pEndpoint->pBusHandle);
295  return ret;
296 
297  }
298 /***********************************************************************
299  *
300  * Function Name : i2c_master_adapter_write
301  * Description : The function provides read interface for the given i2c bus.
302  * It reads the data sequentially from the device byte at a time.
303  *
304  ***************************************************************************/
305 isf_status_t i2c_master_adapter_read(void* apEndpointHandle, int32 offset, void* pReadBuffer, uint32 buffsize, uint32 nByteRead, i2c_readFlags_t aFlags)
306 {
307 
308  if((NULL == apEndpointHandle) || (NULL == pReadBuffer)){
309  return COMM_ERROR_NULL_PTR;
310  }
311  if(buffsize < nByteRead){
312  return COMM_ERROR_BUF_SIZE;
313  }
314  isf_status_t ret;
315  i2c_Endpoint_t *pEndpoint = (i2c_Endpoint_t *)apEndpointHandle;
317  // Invalid bus state, cannot perform the read operation.
318  if(pBusHandle->busState != COMM_STATE_OK ){
319  return COMM_ERROR_INIT;
320  }
321  ret = bus_lock(pEndpoint->pBusHandle, pBusHandle->busConfig.timeout);
322  if(ret != ISF_SUCCESS){
323  return ret;
324  }
325 
326  ret = I2C_DRV_MasterReceiveDataBlocking(pBusHandle->busInstance, &pEndpoint->device,
327  (offset != INVALID_OFFSET)? (const uint8_t*)&offset : NULL, 1,
328  (uint8_t*)pReadBuffer, nByteRead, pBusHandle->busConfig.timeout );
329 
330  bus_unlock(pEndpoint->pBusHandle);
331 
332  return ret;
333 
334 }
335 /***********************************************************************
336  *
337  * Function Name : bus_lock
338  * Description : Internal function uses to lock the i2c bus.
339  * Each i2c bus has own lock that enables the concurrent access to bus safely.
340  * It uses mqx synchronization object mutex.
341  *
342  ***************************************************************************/
343  static isf_status_t bus_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout )
344  {
345 
346  // Invalid bus.
347  if (NULL == apBusHandle->pLock){
348  return COMM_ERROR_LOCK;
349  }
350  //if there is a lock on the specific handler. should not take the mutex multiple time
351  // for the same handler
352  if (I2C_MASTER_ADAPTER_LOCK_DEFAULT == apBusHandle->nLock){
353  if(kStatus_OSA_Success != OSA_MutexLock((mutex_t*)apBusHandle->pLock, OSA_WAIT_FOREVER)){
354  return COMM_ERROR_LOCK;
355  }
356  }
357  apBusHandle->nLock++;
358 
359  return ISF_SUCCESS;
360  }
361  /***********************************************************************
362  *
363  * Function Name : bus_unlock
364  * Description : Internal function uses to un-lock the i2c bus.
365  *
366  ***************************************************************************/
367 
368  static isf_status_t bus_unlock(busHandle_t *apBusHandle )
369  {
370  //if there is no lock associate with the handler
371  if(NULL == apBusHandle->pLock){
372  // No lock is associated with this bus.
373  return COMM_ERROR_LOCK;
374  }
375  if(0 == apBusHandle->nLock){
376  return ISF_SUCCESS;
377  }else if (I2C_MASTER_ADAPTER_LOCK_DEFAULT == --apBusHandle->nLock){
378  // release the resource
379  OSA_MutexUnlock((mutex_t*)apBusHandle->pLock);
380  }
381  return ISF_SUCCESS;
382  }
383 
384 
385 
386 
387 
unsigned char uint8
Definition: isf_types.h:76
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.
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.
#define I2C_MASTER_ADAPTER_LOCK_DEFAULT
isf_protocol_adapter.h defines the general interface definition for the protocol adapter.
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:84
i2c_Master_busHandle_t i2c_master_busHandle[]
Main ISF header file. Contains code common to all ISF components.
signed long int int32
Definition: isf_types.h:74
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.
int32 isf_status_t
ISF return status type.
Definition: isf.h:76
enum comm_State_vals comm_State_t
This enum holds an enumerated value describing the state of a channel.
Definition: isf_comm.h:53
mutex_t i2c_Master_mutexHandler[]
unsigned long int uint32
Definition: isf_types.h:78
#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.