ISF  2.1
Intelligent Sensing Framework for Kinetis with Processor Expert
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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) 2012-2014, Freescale Semiconductor, Inc.
6 *
7 *******************************************************************************/
8 /*!
9 * @file isf_spi_master_adapter.c
10 * @brief \b isf_spi_master_adapter.c implements spi 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_spi_master_adapter.h"
19 #include "fsl_spi_master_driver.h"
20 #include "isf_devmsg.h"
21 #include "isf_util.h"
22 #include "isf_protocol_adapter.h"
23 #define ISF_SPI_LOCK_DEFAULT (0)
24 
25 static isf_status_t bus_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout, uint8 type);
26 static isf_status_t bus_unlock(busHandle_t *apBusHandle, uint8 type);
27 
28 extern MUTEX_STRUCT spi_master_lock[];
29 extern MUTEX_STRUCT spi_master_rdlock[];
31 extern uint8 gSys_NumSpiBuses;
33 
34 /*******************************************************************************
35  * Functions
36  ******************************************************************************/
37 /***********************************************************************
38  *
39  * Function Name : spi_master_adapter_init
40  * Description : This function Initialize the spi driver.
41  * It initialize the bus handle, reset all the registers and configure the control register for interrupt.
42  * This also initialize the lock functionality.
43  *
44  ***************************************************************************/
46 {
47  MUTEX_ATTR_STRUCT mutexattr;
48 
49  if( gSys_NumSpiBuses <= aBusId){
50  return COMM_ERROR_NOEXIST ;
51  }
52  // Initialize the bus handle.
53 
54  _int_disable();
55 
56  spi_master_busHandle_t *pBusHandle = &spi_master_busHandle[aBusId];
57 
58  apBusHandle->nLock = ISF_SPI_LOCK_DEFAULT;
59  apBusHandle->pLock = &spi_master_lock[aBusId];
60  apBusHandle->nRdLock = ISF_SPI_LOCK_DEFAULT;
61  apBusHandle->pRdLock = &spi_master_rdlock[aBusId];
62  if(pBusHandle->busState == COMM_STATE_NO_INIT){
63  if (MQX_OK == _mutatr_init(&mutexattr)) {
64  _mutatr_set_sched_protocol(&mutexattr, MUTEX_PRIO_INHERIT);
65  }else{
66  _int_enable();
67  return COMM_ERROR_INIT;
68  }
69  // Initialize the common lock
70  if(MQX_OK != _mutex_init(apBusHandle->pLock, &mutexattr)){
71  _int_enable();
72  return COMM_ERROR_INIT;
73  }
74  // Initialize the read lock
75  if(MQX_OK != _mutex_init(apBusHandle->pRdLock, &mutexattr)){
76  _int_enable();
77  return COMM_ERROR_INIT;
78  }
79 
80  //initialize the driver.
81  //pBusHandle->busConfig = gSys_SpiMasterBusConfig[aBusId];
82  spi_master_init(aBusId);
83  pBusHandle->busState = COMM_STATE_INIT;
84  }
85  apBusHandle->pHandle = pBusHandle;
86  _int_enable();
87  return ISF_SUCCESS;
88 }
89 /***********************************************************************
90  *
91  * Function Name : spi_master_adapter_configure
92  * Description : This function configure the of the baudrate and timeout.
93  *
94  ***************************************************************************/
96 {
98  if((NULL == apBusHandle) || (NULL == apBusConfig)){
99  return COMM_ERROR_NULL_PTR;
100  }
101 
102  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
103  if((COMM_STATE_STOPPED != pBusHandle->busState ) && (COMM_STATE_INIT != pBusHandle->busState)){
104  return COMM_ERROR_STOP;
105  }
106  spi_master_busConfig_t* pBusConfig = (spi_master_busConfig_t*)&pBusHandle->busConfig;
107  ret = bus_lock(apBusHandle, pBusConfig->timeout, SPI_LOCK_COMMON);
108  ret = bus_lock(apBusHandle, pBusConfig->timeout, SPI_LOCK_READ);
109  // SPI hal init
110  spi_master_configure_bus(pBusHandle->spiHandle.instance, apBusConfig);
111  // Copy the user specific configuration to bushandle.
112  *pBusConfig = *apBusConfig;
113  //release the both lock.
114  bus_unlock(apBusHandle, SPI_LOCK_COMMON);
115  bus_unlock(apBusHandle, SPI_LOCK_READ);
116  return ret;
117 }
118 /***********************************************************************
119  *
120  * Function Name : spi_master_adapter_get_state
121  * Description : This function provides the current state of the bus for a given SPI bus.
122  *
123  ***************************************************************************/
125 {
126  if(NULL == apBusHandle){
127  return COMM_ERROR_NULL_PTR;
128  }
129  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
130  return pBusHandle->busState;
131 }
132 /***********************************************************************
133  *
134  * Function Name : spi_master_adapter_get_config
135  * Description : This function provides the current configuration for a given SPI bus.
136  *
137  ***************************************************************************/
139 {
140  //verify the passed the parameter
141  if((NULL == apBusHandle) || (NULL == apBusConfig)){
142  return COMM_ERROR_NULL_PTR;
143  }
144  *((spi_master_busConfig_t*)apBusConfig) = ((spi_master_busHandle_t *)apBusHandle->pHandle)->busConfig;
145  return ISF_SUCCESS;
146 }
147 /***********************************************************************
148  *
149  * Function Name : spi_master_adapter_acquire_lock
150  * Description : This function provides explicit lock functionality for
151  * the multiple transactions.
152  * Note: It is important to explicit release by calling spi_master_adapter_release_lock
153  * once the multi-transaction is done.
154  *
155  ***************************************************************************/
157 {
158  if(NULL == apBusHandle){
159  return COMM_ERROR_NULL_PTR;
160  }
162  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
163  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
164  return ret;
165 }
166 /***********************************************************************
167  *
168  * Function Name : spi_master_adapter_release_lock
169  * Description : This function provides explicit release lock functionality for
170  * the multiple transactions.
171  *
172  ***************************************************************************/
174 {
175  if(NULL == apBusHandle){
176  return COMM_ERROR_NULL_PTR;
177  }
179  ret = bus_unlock(apBusHandle, SPI_LOCK_COMMON);
180  return ret;
181 }
182 /***********************************************************************
183  *
184  * Function Name : spi_master_adapter_start
185  * Description : This function implements the start functionality of bus.
186  * Once the bus started the bus is ready to use.
187  *
188  ***************************************************************************/
190 {
191  if(NULL == apBusHandle){
192  return COMM_ERROR_NULL_PTR;
193  }
194  isf_status_t ret;
195  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
196 
197  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
198  // Enable the SPI module.
199  spi_hal_enable(pBusHandle->spiHandle.instance);
200  pBusHandle->busState = COMM_STATE_OK;
201  bus_unlock(apBusHandle, SPI_LOCK_COMMON);
202  return ret;
203 }
204 /***********************************************************************
205  *
206  * Function Name : spi_master_adapter_stop
207  * Description : This function implements the stop functionality of bus.
208  * Once the bus stopped the bus is not ready for further use. It is necessary to start the bus again.
209  *
210  ***************************************************************************/
212 {
213  if( NULL == apBusHandle){
214  return COMM_ERROR_NULL_PTR;
215  }
216  isf_status_t ret;
217  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
218  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
219  // Disable the SPI Module.
220  spi_hal_disable(pBusHandle->spiHandle.instance);
221 
222  // State settings for the bus.
223  pBusHandle->busState = COMM_STATE_STOPPED;
224  bus_unlock(apBusHandle, SPI_LOCK_COMMON);
225  return ret;
226 }
227 /***********************************************************************
228  *
229  * Function Name : spi_master_adapter_get_endpoint
230  * Description : This function uses to establish a communication endpoint
231  * between the devices for a given UART bus. A bus can have multiple device connected virtually.
232  * Each will be having separate a communication endpoint through which the master can talk the device.
233  *
234  ***************************************************************************/
235 isf_status_t spi_master_adapter_get_endpoint(busHandle_t *apBusHandle, void *apDevice, void** apEndpointHandle)
236 {
237  isf_status_t ret;
238  spi_master_busHandle_t *pBusHandle = (spi_master_busHandle_t *)apBusHandle->pHandle;
239  if((NULL == apBusHandle) || (NULL == apEndpointHandle) || (NULL == apDevice)){
240  return COMM_ERROR_NULL_PTR;
241  }
242  // Cannot open if the bus is not started.
243  if(COMM_STATE_OK != pBusHandle->busState){
244  return COMM_ERROR_STOP;
245  }
246  ret = bus_lock(apBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
247  if(ISF_SUCCESS != ret){
248  return ret;
249  }
250  // create the endpoint and initialize the endpoint.
251  spi_master_Endpoint_t *pEndpoint = _lwmem_alloc_system_zero(sizeof(spi_master_Endpoint_t));
252  pEndpoint->pBusHandle = apBusHandle;
253  *apEndpointHandle = pEndpoint;
254  pEndpoint->pSlaveInfo = (spi_master_slaveInfo_t*)apDevice;
255  pEndpoint->pSlaveInfo->slaveinit(); // Initialize slave specific spi.
256  bus_unlock(apBusHandle, SPI_LOCK_COMMON);
257  return ret;
258 }
259 /***********************************************************************
260  *
261  * Function Name : spi_master_adapter_release_endpoint
262  * Description : Its designed to release the communication endpoint.
263  * At this point there is nothing to implement.
264  *
265  ***************************************************************************/
266 
268 {
269  if(NULL == apEndpoint){
270  return COMM_ERROR_NULL_PTR;
271  }
272  _lwmem_free(apEndpoint);
273  return ISF_SUCCESS;
274 }
275 /***********************************************************************
276  *
277  * Function Name : spi_master_adapter_write
278  * Description : The function provides write interface for the given UART bus.
279  * It writes the data sequentially to the device byte at a time.
280  *
281  ***************************************************************************/
282 isf_status_t spi_master_adapter_write(void* apEndpointHandle, int32 offset, void* pWriteBuffer, uint32 buffsize, uint32 nByteWrite, spi_master_writeFlags_t aFlags)
283 {
284 
285  isf_status_t ret;
286  spi_master_Endpoint_t *pEndpoint = (spi_master_Endpoint_t *)apEndpointHandle;
288  spi_mater_slaveCmd_t slaveCmd = {0} ;
289  if((NULL == pEndpoint) || (NULL == pWriteBuffer) || (NULL == pEndpoint->pSlaveInfo)){
290  return COMM_ERROR_NULL_PTR;
291  }
292  if(buffsize < nByteWrite){
293  return COMM_ERROR_BUF_SIZE;
294  }
295  // Invalid bus state, cannot perform the write operation.
296  if(COMM_STATE_OK != pBusHandle->busState){
297  return COMM_ERROR_INIT;
298  }
299 
300  ret = bus_lock(pEndpoint->pBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_COMMON);
301  if(ISF_SUCCESS != ret){
302  return ret;
303  }
304  // prepare the slave command and pre-processing logic before the transaction.
305  if(ISF_SUCCESS != pEndpoint->pSlaveInfo->writepreProcess(&slaveCmd, offset, nByteWrite, pWriteBuffer)){
306  return COMM_ERROR_OTHER;
307  }
308  if(SPI_ASYNC == aFlags){
309  // invoke driver specific asynchronized write functions.
310  ret = spi_master_transfer_async(pBusHandle->spiHandle.instance, NULL, slaveCmd.pWriteBuffer, slaveCmd.pReadBuffer, slaveCmd.size);
311  }else{
312  // invoke driver specific synchronized write function.
313  ret = spi_master_transfer(pBusHandle->spiHandle.instance, NULL, slaveCmd.pWriteBuffer, slaveCmd.pReadBuffer, slaveCmd.size, pBusHandle->busConfig.timeout);
314  }
315  // post-processing logic.
316  pEndpoint->pSlaveInfo->writepostProcess(&slaveCmd);
317  bus_unlock(pEndpoint->pBusHandle, SPI_LOCK_COMMON);
318  return ret;
319 
320  }
321 /***********************************************************************
322  *
323  * Function Name : spi_master_adapter_write
324  * Description : The function provides read interface for the given SPI bus.
325  * It reads the data sequentially from the device byte at a time.
326  *
327  ***************************************************************************/
328 isf_status_t spi_master_adapter_read(void* apEndpointHandle, int32 offset, void* pReadBuffer, uint32 buffsize, uint32 nByteRead, spi_master_readFlags_t aFlags)
329 {
330 
331 
333  spi_master_Endpoint_t *pEndpoint = (spi_master_Endpoint_t *)apEndpointHandle;
335  spi_mater_slaveCmd_t slaveCmd = {0} ; // slave command.
336  if((NULL == pEndpoint) || (NULL == pReadBuffer) || (NULL == pEndpoint->pSlaveInfo)){
337  return COMM_ERROR_NULL_PTR;
338  }
339  if(buffsize < nByteRead){
340  return COMM_ERROR_BUF_SIZE;
341  }
342  // Invalid bus state, cannot perform the read operation.
343  if(pBusHandle->busState != COMM_STATE_OK ){
344  return COMM_ERROR_INIT;
345  }
346  ret = bus_lock(pEndpoint->pBusHandle, pBusHandle->busConfig.timeout, SPI_LOCK_READ);
347  if(ISF_SUCCESS != ret){
348  return ret;
349  }
350  // prepare the slave command and pre-processing logic before the transaction.
351  if(ISF_SUCCESS != pEndpoint->pSlaveInfo->readpreProcess(&slaveCmd, offset, nByteRead)){
352  return COMM_ERROR_OTHER;
353  }
354 
355  if(SPI_ASYNC == aFlags){
356  // invoke driver specific asynchronized read function.
357  ret = spi_master_transfer_async(pBusHandle->spiHandle.instance, NULL, slaveCmd.pWriteBuffer, slaveCmd.pReadBuffer, slaveCmd.size);
358  }else{
359  // invoke driver specific synchronized read function.
360  ret = spi_master_transfer(pBusHandle->spiHandle.instance, NULL, slaveCmd.pWriteBuffer, slaveCmd.pReadBuffer, slaveCmd.size, pBusHandle->busConfig.timeout);
361  }
362  pEndpoint->pSlaveInfo->readpostProcess(&slaveCmd, pReadBuffer);
363  bus_unlock(pEndpoint->pBusHandle, SPI_LOCK_READ);
364 
365  return ret;
366 
367 }
368 /***********************************************************************
369  *
370  * Function Name : bus_lock
371  * Description : Internal function uses to lock the SPI.
372  * Each SPI has own lock that enables the concurrent access to bus safely.
373  * It uses mqx synchronization object mutex.
374  *
375  ***************************************************************************/
376  static isf_status_t bus_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout, uint8 type)
377  {
378  uint8 *pnLock;
379  void* pLock;
380 
381  if(SPI_LOCK_READ == type){
382  pLock = apBusHandle->pRdLock;
383  pnLock = &apBusHandle->nRdLock;
384  }else{
385  pLock = apBusHandle->pLock;
386  pnLock = &apBusHandle->nLock;
387  }
388  // Invalid bus.
389  if (NULL == pLock){
390  return COMM_ERROR_LOCK;
391  }
392  //if there is a lock on the specific handler. should not take the mutex multiple time
393  // for the same handler
394  if (ISF_SPI_LOCK_DEFAULT == *pnLock){
395  if(MQX_OK != _mutex_lock ((MUTEX_STRUCT*)pLock)){
396  return COMM_ERROR_LOCK;
397  }
398  }
399  (*pnLock)++;
400  return ISF_SUCCESS;
401 
402 
403  }
404  /***********************************************************************
405  *
406  * Function Name : bus_unlock
407  * Description : Internal function uses to un-lock the SPI
408  *
409  ***************************************************************************/
410 
411  static isf_status_t bus_unlock(busHandle_t *apBusHandle, uint8 type )
412  {
413  uint8 *pnLock;
414  void* pLock;
415  if(SPI_LOCK_READ == type){
416  pLock = apBusHandle->pRdLock;
417  pnLock = &apBusHandle->nRdLock;
418  }else{
419  pLock = apBusHandle->pLock;
420  pnLock = &apBusHandle->nLock;
421  }
422  //if there is no lock associate with the handler
423  if(NULL == pLock){
424  // No lock is associated with this bus.
425  return COMM_ERROR_LOCK;
426  }
427  if(0 == *pnLock){
428  return ISF_SUCCESS;
429  }else if (ISF_SPI_LOCK_DEFAULT == --*pnLock){
430  // release the resource
431  _mutex_unlock((MUTEX_STRUCT*)pLock);
432  }
433  return ISF_SUCCESS;
434  }
435 
436 
437 
438 
439 
ISF board support header files.
unsigned char uint8
This defines uint8 as unsigned char.
Definition: isf_types.h:18
spi_master_busConfig_t gSys_SpiMasterBusConfig[]
spi_master_busHandle_t spi_master_busHandle[]
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...
fsl_spi_master_driver.h defines structures and types for the spi master driver.
isf_status_t spi_master_adapter_release_endpoint(spi_master_Endpoint_t *apEndpoint)
This function closes a particular endpoint.
This structure defines the slave specific spi information.
isf_status_t spi_master_adapter_configure(busHandle_t *apBusHandle, spi_master_busConfig_t *apBusConfig)
This function reconfigures an already initialized bus.
unsigned long uint32
This defines uint32 as unsigned long.
Definition: isf_types.h:36
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.
void spi_hal_enable(uint32 instance)
Definition: fsl_spi_hal.c:21
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.
void spi_master_init(uint32_t instance)
Initialize a SPI instance for master mode operation.
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.
spi_status_t spi_master_transfer_async(uint32_t instance, const spi_user_config_t *device, const uint8_t *sendBuffer, uint8_t *receiveBuffer, uint16_t transferByteCount)
Perform an non-blocking SPI master mode transfer.
MUTEX_STRUCT spi_master_lock[]
uint8 gSys_NumSpiBuses
The isf_util.h file contains the utility method declarations and macros.
comm_Flags_t spi_master_writeFlags_t
MUTEX_STRUCT spi_master_rdlock[]
This structure is a declaration of a BusHandle type.
spi_status_t spi_master_transfer(uint32_t instance, const spi_user_config_t *device, const uint8_t *sendBuffer, uint8_t *receiveBuffer, uint16_t transferByteCount, uint32_t timeout)
Perform a blocking SPI master mode transfer.
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:59
long int32
This defines int32 as long.
Definition: isf_types.h:32
void spi_master_configure_bus(uint32_t instance, const spi_user_config_t *device)
Configure the SPI port to access a device on the bus.
Main ISF header file. Contains code common to all ISF components.
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: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
isf_status_t spi_master_adapter_acquire_lock(busHandle_t *apBusHandle, isf_duration_t aTimeout)
This function locks the bus for exclusive access.
void spi_hal_disable(uint32 instance)
Definition: fsl_spi_hal.c:31
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.