ISF  2.2 rev 5
Intelligent Sensing Framework for Kinetis with Processor Expert
isf_spi_master_adapter.c
Go to the documentation of this file.
1 /*!
2  ********************************************************************************
3  * File:isf_spi_master_adapter.c
4  *
5  * Copyright (c) 2015, Freescale Semiconductor, Inc.
6  *
7  *******************************************************************************/
8 /*!
9  * @file File:isf_spi_master_adapter.c
10  * @brief \b File:isf_spi_master_adapter.c implements spi protocol adapter.
11  */
12 #include "isf.h"
13 #include "isf_spi_master_adapter.h"
14 #include "isf_devmsg.h"
15 #include "isf_util.h"
16 #include "isf_protocol_adapter.h"
17 
18 
19 #define ISF_SPI_LOCK_DEFAULT (0)
20 
21 static isf_status_t bus_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout, uint8 type);
22 static isf_status_t bus_unlock(busHandle_t *apBusHandle, uint8 type);
23 
24 extern uint8 gSys_NumSpiBuses;
26 extern mutex_t spi_lock[];
27 extern mutex_t spi_rdlock[];
28 
29 /*******************************************************************************
30  * Functions
31  ******************************************************************************/
32 /***********************************************************************
33  *
34  * Function Name : spi_master_adapter_init
35  * Description : This function Initialize the spi driver.
36  * It initialize the bus handle, reset all the registers and configure the control register for interrupt.
37  * This also initialize the lock functionality.
38  *
39  ***************************************************************************/
41 {
42 
43  // Initialize the bus handle.
44 
45  if( gSys_NumSpiBuses <= aBusId){
46  return COMM_ERROR_NOEXIST ;
47  }
48  OSA_EnterCritical(kCriticalDisableInt);
49 
50  //spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)OSA_MemAllocZero(sizeof(spi_master_busHandle_t));
51  spi_master_busHandle_t *pBusHandle = &spi_busHandle[aBusId];
52  apBusHandle->nLock = ISF_SPI_LOCK_DEFAULT;
53  //apBusHandle->pLock = OSA_MemAllocZero(sizeof(mutex_t));
54  apBusHandle->pLock = &spi_lock[aBusId];
55  apBusHandle->nRdLock = ISF_SPI_LOCK_DEFAULT;
56  //apBusHandle->pRdLock = OSA_MemAllocZero(sizeof(mutex_t));
57  apBusHandle->pRdLock = &spi_rdlock[aBusId];
58  if(pBusHandle->busState == COMM_STATE_NO_INIT){
59  OSA_MutexCreate(apBusHandle->pLock);
60  OSA_MutexCreate(apBusHandle->pRdLock);
61  SPI_Type * base = g_dspiBase[pBusHandle->instance];
62  // Initialize the driver, Turn off the FIFO and enable the shift register.
63  SPI_BWR_MCR_DIS_RXF(base, 1);
64  SPI_BWR_MCR_DIS_TXF(base, 1);
65  SPI_BWR_MCR_ROOE(base,1);
66  DSPI_HAL_SetDelay(base, kDspiCtar0, 1, 2, kDspiPcsToSck);
67  DSPI_HAL_SetDelay(base, kDspiCtar0, 1, 2, kDspiLastSckToPcs);
68  DSPI_HAL_SetDelay(base, kDspiCtar0, 1, 2, kDspiAfterTransfer);
69  pBusHandle->instance = aBusId;
70  pBusHandle->busState = COMM_STATE_OK;
71  }
72  apBusHandle->pHandle = pBusHandle;
73  _int_enable();
74  return ISF_SUCCESS;
75 }
76 /***********************************************************************
77  *
78  * Function Name : spi_master_adapter_configure
79  * Description : This function configure the of the baudrate and timeout.
80  *
81  ***************************************************************************/
83 {
85  uint32_t calculatedBaudRate;
86  if((NULL == apBusHandle) || (NULL == apBusConfig)){
87  return COMM_ERROR_NULL_PTR;
88  }
89 
90  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
91  if((COMM_STATE_STOPPED != pBusHandle->busState ) && (COMM_STATE_INIT != pBusHandle->busState)){
92  return COMM_ERROR_STOP;
93  }
94  ret = bus_lock(apBusHandle, OSA_WAIT_FOREVER, SPI_LOCK_COMMON);
95  ret = bus_lock(apBusHandle, OSA_WAIT_FOREVER, SPI_LOCK_READ);
96  pBusHandle->busConfig = *apBusConfig;
97  dspi_status_t status = DSPI_DRV_MasterConfigureBus(pBusHandle->instance,&apBusConfig->device, &calculatedBaudRate);
98  pBusHandle->busConfig.device.bitsPerSec = calculatedBaudRate;
99 
100  //release the both lock.
101  bus_unlock(apBusHandle, SPI_LOCK_COMMON);
102  bus_unlock(apBusHandle, SPI_LOCK_READ);
103  return ret;
104 }
105 /***********************************************************************
106  *
107  * Function Name : spi_master_adapter_get_state
108  * Description : This function provides the current state of the bus for a given SPI bus.
109  *
110  ***************************************************************************/
112 {
113  if(NULL == apBusHandle){
114  return COMM_ERROR_NULL_PTR;
115  }
116  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
117  return pBusHandle->busState;
118 }
119 /***********************************************************************
120  *
121  * Function Name : spi_master_adapter_get_config
122  * Description : This function provides the current configuration for a given SPI bus.
123  *
124  ***************************************************************************/
126 {
127  //verify the passed the parameter
128  if((NULL == apBusHandle) || (NULL == apBusConfig)){
129  return COMM_ERROR_NULL_PTR;
130  }
131  *((spi_master_busConfig_t*)apBusConfig) = ((spi_master_busHandle_t *)apBusHandle->pHandle)->busConfig;
132  return ISF_SUCCESS;
133 }
134 /***********************************************************************
135  *
136  * Function Name : spi_master_adapter_acquire_lock
137  * Description : This function provides explicit lock functionality for
138  * the multiple transactions.
139  * Note: It is important to explicit release by calling spi_master_adapter_release_lock
140  * once the multi-transaction is done.
141  *
142  ***************************************************************************/
144 {
145  if(NULL == apBusHandle){
146  return COMM_ERROR_NULL_PTR;
147  }
149  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
150  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
151  return ret;
152 }
153 /***********************************************************************
154  *
155  * Function Name : spi_master_adapter_release_lock
156  * Description : This function provides explicit release lock functionality for
157  * the multiple transactions.
158  *
159  ***************************************************************************/
161 {
162  if(NULL == apBusHandle){
163  return COMM_ERROR_NULL_PTR;
164  }
166  ret = bus_unlock(apBusHandle, SPI_LOCK_COMMON);
167  return ret;
168 }
169 /***********************************************************************
170  *
171  * Function Name : spi_master_adapter_start
172  * Description : This function implements the start functionality of bus.
173  * Once the bus started the bus is ready to use.
174  *
175  ***************************************************************************/
177 {
178  if(NULL == apBusHandle){
179  return COMM_ERROR_NULL_PTR;
180  }
181  isf_status_t ret;
182  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
183 
184  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
185  // Enable the SPI module.
186  DSPI_HAL_Enable(g_dspiBase[pBusHandle->instance]);
187 
188  pBusHandle->busState = COMM_STATE_OK;
189  bus_unlock(apBusHandle, SPI_LOCK_COMMON);
190  return ret;
191 }
192 /***********************************************************************
193  *
194  * Function Name : spi_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( NULL == apBusHandle){
202  return COMM_ERROR_NULL_PTR;
203  }
204  isf_status_t ret;
205  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
206  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
207  // Disable the SPI Module.
208  DSPI_HAL_Disable(g_dspiBase[pBusHandle->instance]);
209 
210  // State settings for the bus.
211  pBusHandle->busState = COMM_STATE_STOPPED;
212  bus_unlock(apBusHandle, SPI_LOCK_COMMON);
213  return ret;
214 }
215 /***********************************************************************
216  *
217  * Function Name : spi_master_adapter_get_endpoint
218  * Description : This function uses to establish a communication endpoint
219  * between the devices for a given UART bus. A bus can have multiple device connected virtually.
220  * Each will be having separate a communication endpoint through which the master can talk the device.
221  *
222  ***************************************************************************/
223 isf_status_t spi_master_adapter_get_endpoint(busHandle_t *apBusHandle, void *apDevice, void** apEndpointHandle)
224 {
225  isf_status_t ret;
226  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
227  pBusHandle->busConfig = ((spi_master_CommSpecificInfo_t*)apDevice)->busConfig;
228  if((NULL == apBusHandle) || (NULL == apEndpointHandle) || (NULL == apDevice)){
229  return COMM_ERROR_NULL_PTR;
230  }
231  // Cannot open if the bus is not started.
232  if(COMM_STATE_OK != pBusHandle->busState){
233  return COMM_ERROR_STOP;
234  }
235  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
236  if(ISF_SUCCESS != ret){
237  return ret;
238  }
239  // create the endpoint and initialize the endpoint.
240  spi_master_Endpoint_t *pEndpoint = OSA_MemAllocZero(sizeof(spi_master_Endpoint_t));
241  pEndpoint->pBusHandle = apBusHandle;
242  *apEndpointHandle = pEndpoint;
243  pEndpoint->pSlaveInfo = ((spi_master_CommSpecificInfo_t*)apDevice)->pSlaveInfo;
244  pEndpoint->pSlaveInfo->slaveinit(); // Initialize slave specific spi.
245  bus_unlock(apBusHandle, SPI_LOCK_COMMON);
246  return ret;
247 }
248 /***********************************************************************
249  *
250  * Function Name : spi_master_adapter_release_endpoint
251  * Description : Its designed to release the communication endpoint.
252  * At this point there is nothing to implement.
253  *
254  ***************************************************************************/
255 
257 {
258  if(NULL == apEndpoint){
259  return COMM_ERROR_NULL_PTR;
260  }
261  OSA_MemFree(apEndpoint);
262  return ISF_SUCCESS;
263 }
264 /***********************************************************************
265  *
266  * Function Name : spi_master_adapter_write
267  * Description : The function provides write interface for the given UART bus.
268  * It writes the data sequentially to the device byte at a time.
269  *
270  ***************************************************************************/
271 isf_status_t spi_master_adapter_write(void* apEndpointHandle, int32 offset, void* pWriteBuffer, uint32 buffsize, uint32 nByteWrite, spi_master_writeFlags_t aFlags)
272 {
273 
274  isf_status_t ret;
275  spi_master_Endpoint_t *pEndpoint = (spi_master_Endpoint_t *)apEndpointHandle;
277  spi_mater_slaveCmd_t slaveCmd = {0} ;
278  if((NULL == pEndpoint) || (NULL == pWriteBuffer) || (NULL == pEndpoint->pSlaveInfo)){
279  return COMM_ERROR_NULL_PTR;
280  }
281  if(buffsize < nByteWrite){
282  return COMM_ERROR_BUF_SIZE;
283  }
284  // Invalid bus state, cannot perform the write operation.
285  if(COMM_STATE_OK != pBusHandle->busState){
286  return COMM_ERROR_INIT;
287  }
288 
289  ret = bus_lock(pEndpoint->pBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
290  if(ISF_SUCCESS != ret){
291  return ret;
292  }
293  // prepare the slave command and pre-processing logic before the transaction.
294  if(ISF_SUCCESS != pEndpoint->pSlaveInfo->writepreProcess(&slaveCmd, offset, nByteWrite, pWriteBuffer)){
295  return COMM_ERROR_OTHER;
296  }
297  ret = DSPI_DRV_MasterTransferBlocking(pBusHandle->instance,NULL,
298  (const uint8_t *) slaveCmd.pWriteBuffer, slaveCmd.pReadBuffer,
299  slaveCmd.size, pBusHandle->busConfig.timeout);
300 
301  // post-processing logic.
302  pEndpoint->pSlaveInfo->writepostProcess(&slaveCmd);
303  bus_unlock(pEndpoint->pBusHandle, SPI_LOCK_COMMON);
304  return ret;
305 
306 }
307 /***********************************************************************
308  *
309  * Function Name : spi_master_adapter_write
310  * Description : The function provides read interface for the given SPI bus.
311  * It reads the data sequentially from the device byte at a time.
312  *
313  ***************************************************************************/
314 isf_status_t spi_master_adapter_read(void* apEndpointHandle, int32 offset, void* pReadBuffer, uint32 buffsize, uint32 nByteRead, spi_master_readFlags_t aFlags)
315 {
316 
317 
319  spi_master_Endpoint_t *pEndpoint = (spi_master_Endpoint_t *)apEndpointHandle;
321  spi_mater_slaveCmd_t slaveCmd = {0} ; // slave command.
322  if((NULL == pEndpoint) || (NULL == pReadBuffer) || (NULL == pEndpoint->pSlaveInfo)){
323  return COMM_ERROR_NULL_PTR;
324  }
325  if(buffsize < nByteRead){
326  return COMM_ERROR_BUF_SIZE;
327  }
328  // Invalid bus state, cannot perform the read operation.
329  if(pBusHandle->busState != COMM_STATE_OK ){
330  return COMM_ERROR_INIT;
331  }
332  ret = bus_lock(pEndpoint->pBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_READ);
333  if(ISF_SUCCESS != ret){
334  return ret;
335  }
336  // prepare the slave command and pre-processing logic before the transaction.
337  if(ISF_SUCCESS != pEndpoint->pSlaveInfo->readpreProcess(&slaveCmd, offset, nByteRead)){
338  return COMM_ERROR_OTHER;
339  }
340  ret = DSPI_DRV_MasterTransferBlocking(pBusHandle->instance,NULL,
341  (const uint8_t *)slaveCmd.pWriteBuffer,slaveCmd.pReadBuffer, slaveCmd.size, pBusHandle->busConfig.timeout);
342 
343  pEndpoint->pSlaveInfo->readpostProcess(&slaveCmd, pReadBuffer);
344  bus_unlock(pEndpoint->pBusHandle, SPI_LOCK_READ);
345 
346  return ret;
347 
348 }
349 /***********************************************************************
350  *
351  * Function Name : bus_lock
352  * Description : Internal function uses to lock the SPI.
353  * Each SPI has own lock that enables the concurrent access to bus safely.
354  * It uses mqx synchronization object mutex.
355  *
356  ***************************************************************************/
357 static isf_status_t bus_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout, uint8 type)
358 {
359  uint8 *pnLock;
360  void* pLock;
361 
362  if(SPI_LOCK_READ == type){
363  pLock = apBusHandle->pRdLock;
364  pnLock = &apBusHandle->nRdLock;
365  }else{
366  pLock = apBusHandle->pLock;
367  pnLock = &apBusHandle->nLock;
368  }
369  // Invalid bus.
370  if (NULL == pLock){
371  return COMM_ERROR_LOCK;
372  }
373  //if there is a lock on the specific handler. should not take the mutex multiple time
374  // for the same handler
375  if (ISF_SPI_LOCK_DEFAULT == *pnLock){
376  if(kStatus_OSA_Success != OSA_MutexLock((mutex_t*)pLock, OSA_WAIT_FOREVER)){
377  return COMM_ERROR_LOCK;
378  }
379  }
380  (*pnLock)++;
381  return ISF_SUCCESS;
382 
383 
384 }
385 /***********************************************************************
386  *
387  * Function Name : bus_unlock
388  * Description : Internal function uses to un-lock the SPI
389  *
390  ***************************************************************************/
391 
392 static isf_status_t bus_unlock(busHandle_t *apBusHandle, uint8 type )
393 {
394  uint8 *pnLock;
395  void* pLock;
396  if(SPI_LOCK_READ == type){
397  pLock = apBusHandle->pRdLock;
398  pnLock = &apBusHandle->nRdLock;
399  }else{
400  pLock = apBusHandle->pLock;
401  pnLock = &apBusHandle->nLock;
402  }
403  //if there is no lock associate with the handler
404  if(NULL == pLock){
405  // No lock is associated with this bus.
406  return COMM_ERROR_LOCK;
407  }
408  if(0 == *pnLock){
409  return ISF_SUCCESS;
410  }else if (ISF_SPI_LOCK_DEFAULT == --*pnLock){
411  // release the resource
412  OSA_MutexUnlock((mutex_t*)pLock);
413  }
414  return ISF_SUCCESS;
415 }
416 
417 
418 
419 
420 
421 
unsigned char uint8
Definition: isf_types.h:76
isf_status_t spi_master_adapter_init(comm_Id_t aBusId, busHandle_t *apBusHandle)
This function initializes a spi bus.
isf_status_t spi_master_adapter_read(void *apEndpointHandle, int32 offset, void *pReadBuffer, uint32 buffsize, uint32 nByteRead, spi_master_readFlags_t aFlags)
This function reads from a spi 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
isf_spi_master_adapter.h defines the API definitions and types for the spi master protocol adapter...
isf_status_t spi_master_adapter_release_endpoint(spi_master_Endpoint_t *apEndpoint)
This function closes a particular endpoint.
isf_status_t spi_master_adapter_configure(busHandle_t *apBusHandle, spi_master_busConfig_t *apBusConfig)
This function reconfigures an already initialized bus.
isf_status_t spi_master_adapter_get_config(busHandle_t *apBusHandle, void *apBusConfig)
This function returns the current bus configuration.
spi_master_slaveInfo_t * pSlaveInfo
isf_status_t spi_master_adapter_start(busHandle_t *apBusHandle)
This function starts a bus.
isf_status_t spi_master_adapter_release_lock(busHandle_t *apBusHandle)
This function releases exclusive bus access.
comm_State_t spi_master_adapter_get_state(busHandle_t *apBusHandle)
This function returns the current bus state.
This structure defines a device endpoint encapsulation for spi handler.
comm_Flags_t spi_master_readFlags_t
#define ISF_SPI_LOCK_DEFAULT
isf_protocol_adapter.h defines the general interface definition for the protocol adapter.
mutex_t spi_lock[]
uint8 gSys_NumSpiBuses
The isf_util.h file contains the utility method declarations and macros.
comm_Flags_t spi_master_writeFlags_t
This structure is a declaration of a BusHandle type.
spi_master_busHandle_t spi_busHandle[]
isf_status_t spi_master_adapter_get_endpoint(busHandle_t *apBusHandle, void *apDevice, void **apEndpointHandle)
This function creates a endpoint for a device at a specified bus address.
This structure defines the spi slave command format.
uint32 isf_duration_t
ISF time duration in microseconds.
Definition: isf.h:84
Main ISF header file. Contains code common to all ISF components.
signed long int int32
Definition: isf_types.h:74
isf_status_t spi_master_adapter_stop(busHandle_t *apBusHandle)
This function stops the given spi bus.
spi_master_busConfig_t busConfig
int32 isf_status_t
ISF return status type.
Definition: isf.h:76
mutex_t spi_rdlock[]
enum comm_State_vals comm_State_t
This enum holds an enumerated value describing the state of a channel.
Definition: isf_comm.h:53
isf_status_t spi_master_adapter_acquire_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout)
This function locks the bus for exclusive access.
unsigned long int uint32
Definition: isf_types.h:78
This structure defines the data bus handle.
isf_devmsg.h defines the API definitions and types for the Intelligent Sensing (ISF) Device Messaging...
isf_status_t spi_master_adapter_write(void *apEndpointHandle, int32 offset, void *pWriteBuffer, uint32 buffsize, uint32 nByteWrite, spi_master_writeFlags_t aFlags)
This function writes to a spi device.