Statistics
| Branch: | Tag: | Revision:

mongoose / examples / PIC32 / mqtt_client / firmware / src / system_config / mx795_CC3100_e16 / framework / driver / spi / static / src / drv_spi_static.c @ eaef5bd1

History | View | Annotate | Download (14.9 KB)

1 eaef5bd1 Alexander Alashkin
/* clang-format off */
2
/*******************************************************************************
3
  SPI Driver Static implementation
4

5
  Company:
6
    Microchip Technology Inc.
7

8
  File Name:
9
    drv_spi_static.c
10

11
  Summary:
12
    Source code for the SPI driver static implementation.
13

14
  Description:
15
    The SPI device driver provides a simple interface to manage the SPI
16
    modules on Microchip microcontrollers. This file contains static implementation
17
    for the SPI driver.
18

19
  Remarks:
20
    Static interfaces incorporate the driver instance number within the names
21
    of the routines, eliminating the need for an object ID or object handle.
22

23
    Static single-open interfaces also eliminate the need for the open handle.
24
*******************************************************************************/
25
26
//DOM-IGNORE-BEGIN
27
/*******************************************************************************
28
Copyright (c) 2015 released Microchip Technology Inc.  All rights reserved.
29

30
Microchip licenses to you the right to use, modify, copy and distribute
31
Software only when embedded on a Microchip microcontroller or digital signal
32
controller that is integrated into your product or third party product
33
(pursuant to the sublicense terms in the accompanying license agreement).
34

35
You should refer to the license agreement accompanying this Software for
36
additional information regarding your rights and obligations.
37

38
SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
39
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
40
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
41
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
42
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
43
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
44
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
45
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
46
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
47
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
48
*******************************************************************************/
49
//DOM-IGNORE-END
50
51
// *****************************************************************************
52
// *****************************************************************************
53
// Section: Included Files
54
// *****************************************************************************
55
// *****************************************************************************
56
57
#include <string.h>
58
#include "system_config.h"
59
#include "system_definitions.h"
60
61
// *****************************************************************************
62
// *****************************************************************************
63
// Section: Global Data
64
// *****************************************************************************
65
// *****************************************************************************
66
static uint8_t sDrvSPIQueueArea[DRV_SPI_SYS_QUEUE_BUFFER_SIZE(DRV_SPI_INSTANCES_NUMBER, sizeof(DRV_SPI_JOB_OBJECT), DRV_SPI_INSTANCES_NUMBER * DRV_SPI_ELEMENTS_PER_QUEUE)];
67
68
/* This is the Queue manager object . */
69
static DRV_SPI_SYS_QUEUE_MANAGER_SETUP qmInitData = {
70
    sDrvSPIQueueArea,
71
    sizeof(sDrvSPIQueueArea),
72
    DRV_SPI_INSTANCES_NUMBER,
73
    sizeof(DRV_SPI_JOB_OBJECT),
74
    DRV_SPI_SYS_QUEUE_Fifo,
75
};
76
77
/* This is the Queue setup object . */
78
static DRV_SPI_SYS_QUEUE_SETUP qInitData =
79
{
80
    0,
81
    10,
82
    0,
83
};
84
85
/* This is the Queue Manager handle*/
86
DRV_SPI_SYS_QUEUE_MANAGER_HANDLE  hQueueManager;
87
88
89
// *****************************************************************************
90
// *****************************************************************************
91
// Section: Instance 0 static driver functions
92
// *****************************************************************************
93
// *****************************************************************************
94
/* This is the driver static object . */
95
DRV_SPI_OBJ  gDrvSPI0Obj ;
96
97
SYS_MODULE_OBJ DRV_SPI0_Initialize(void)
98
{
99
    DRV_SPI_OBJ *dObj = (DRV_SPI_OBJ*)NULL;
100
101
    dObj = &gDrvSPI0Obj;
102
103
    /* Disable the SPI module to configure it*/
104
    PLIB_SPI_Disable ( SPI_ID_1 );
105
106
    /* Set up Master or Slave Mode*/
107
    PLIB_SPI_MasterEnable ( SPI_ID_1 );
108
    PLIB_SPI_PinDisable(SPI_ID_1, SPI_PIN_SLAVE_SELECT);
109
110
    /* Set up if the SPI is allowed to run while the rest of the CPU is in idle mode*/
111
    PLIB_SPI_StopInIdleEnable( SPI_ID_1 );
112
113
    /* Set up clock Polarity and output data phase*/
114
    PLIB_SPI_ClockPolaritySelect( SPI_ID_1, SPI_CLOCK_POLARITY_IDLE_LOW );
115
    PLIB_SPI_OutputDataPhaseSelect( SPI_ID_1, SPI_OUTPUT_DATA_PHASE_ON_IDLE_TO_ACTIVE_CLOCK );
116
117
    /* Set up the Input Sample Phase*/
118
    PLIB_SPI_InputSamplePhaseSelect ( SPI_ID_1, SPI_INPUT_SAMPLING_PHASE_IN_MIDDLE);
119
120
    /* Communication Width Selection */
121
    PLIB_SPI_CommunicationWidthSelect ( SPI_ID_1, SPI_COMMUNICATION_WIDTH_8BITS );
122
123
    /* Baud rate selection */
124
    PLIB_SPI_BaudRateSet( SPI_ID_1 , SYS_CLK_PeripheralFrequencyGet(CLK_BUS_PERIPHERAL_2), 10000000 );
125
126
    /* Protocol selection */
127
    PLIB_SPI_FramedCommunicationDisable( SPI_ID_1  );
128
    #if defined (PLIB_SPI_ExistsAudioProtocolControl)
129
            if (PLIB_SPI_ExistsAudioProtocolControl(SPI_ID_1))
130
            {
131
                PLIB_SPI_AudioProtocolDisable(SPI_ID_1);
132
            }
133
    #endif
134
135
    /* Buffer type selection */
136
    #if defined (PLIB_SPI_ExistsFIFOControl)
137
        if (PLIB_SPI_ExistsFIFOControl( SPI_ID_1 ))
138
        {
139
            PLIB_SPI_FIFODisable( SPI_ID_1 );
140
        }
141
    #endif
142
143
    PLIB_SPI_BufferClear( SPI_ID_1 );
144
    PLIB_SPI_ReceiverOverflowClear ( SPI_ID_1 );
145
146
    /* Initialize Queue only once for all instances of SPI driver*/
147
    if (DRV_SPI_SYS_QUEUE_Initialize(&qmInitData, &hQueueManager) != DRV_SPI_SYS_QUEUE_SUCCESS)
148
    {
149
        SYS_ASSERT(false, "\r\nSPI Driver: Could not create queuing system.");
150
        return SYS_MODULE_OBJ_INVALID;
151
    }
152
153
    /* Update the Queue parameters. */
154
    qInitData.maxElements = 10; //Queue size
155
    qInitData.reserveElements = 1; //Mininmum number of job queues reserved
156
157
    /* Create Queue for this instance of SPI */
158
    if (DRV_SPI_SYS_QUEUE_CreateQueue(hQueueManager, &qInitData, &dObj->queue) != DRV_SPI_SYS_QUEUE_SUCCESS)
159
    {
160
        SYS_ASSERT(false, "\r\nSPI Driver: Could not set up driver instance queue.");
161
        return SYS_MODULE_OBJ_INVALID;
162
163
    }
164
165
    /* Update the SPI OBJECT parameters. */
166
    dObj->operationStarting = NULL;
167
    dObj->operationEnded = NULL;
168
    dObj->numTrfsSmPolled = 16;
169
170
    /* Enable the Module */
171
    PLIB_SPI_Enable(SPI_ID_1);
172
173
    return (SYS_MODULE_OBJ)DRV_SPI_INDEX_0 ;
174
}
175
176
void DRV_SPI0_Deinitialize ( void )
177
{
178
    /* Disable the SPI Module */
179
    PLIB_SPI_Disable(SPI_ID_1);
180
181
    return;
182
}
183
184
SYS_STATUS DRV_SPI0_Status ( void )
185
{
186
    /* Return the current status of driver instance */
187
    return SYS_STATUS_READY;
188
}
189
190
void DRV_SPI0_Tasks ( void )
191
{
192
    /* Call the respective task routine */
193
    DRV_SPI0_PolledMasterRM8BitTasks(&gDrvSPI0Obj);
194
}
195
196
DRV_HANDLE DRV_SPI0_Open ( const SYS_MODULE_INDEX index, const DRV_IO_INTENT intent )
197
{
198
    return (DRV_HANDLE)DRV_SPI_INDEX_0;
199
}
200
201
void DRV_SPI0_Close ( void )
202
{
203
    return;
204
}
205
206
int32_t DRV_SPI0_ClientConfigure ( const DRV_SPI_CLIENT_DATA * cfgData  )
207
{
208
    DRV_SPI_OBJ *dObj = (DRV_SPI_OBJ*)NULL;
209
210
    dObj = &gDrvSPI0Obj;
211
212
    if (cfgData == NULL)
213
    {
214
        /* Nothing to do */
215
        return 0;
216
    }
217
218
    if (cfgData->operationStarting != NULL)
219
    {
220
        dObj->operationStarting = cfgData->operationStarting;
221
    }
222
223
    if (cfgData->operationEnded != NULL)
224
    {
225
        dObj->operationEnded = cfgData->operationEnded;
226
    }
227
228
    if (cfgData->baudRate != 0)
229
    {
230
231
        PLIB_SPI_BaudRateSet (SPI_ID_1,
232
                              SYS_CLK_PeripheralFrequencyGet(CLK_BUS_PERIPHERAL_2),
233
                              cfgData->baudRate);
234
    }
235
236
    return 0;
237
}
238
239
DRV_SPI_BUFFER_HANDLE DRV_SPI0_BufferAddRead2 ( void *rxBuffer, size_t size, DRV_SPI_BUFFER_EVENT_HANDLER completeCB, void * context, DRV_SPI_BUFFER_HANDLE * jobHandle)
240
{
241
    DRV_SPI_OBJ *dObj = (DRV_SPI_OBJ*)NULL;
242
243
    dObj = &gDrvSPI0Obj;
244
245
    DRV_SPI_JOB_OBJECT * pJob = NULL;
246
247
    if (DRV_SPI_SYS_QUEUE_AllocElementLock(dObj->queue, (void **)&pJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
248
    {
249
        SYS_ASSERT(false, "\r\nSPI Driver: Error trying to get a free entry.");
250
        return (DRV_SPI_BUFFER_HANDLE)NULL;
251
    }
252
253
    memset(pJob, 0, sizeof(DRV_SPI_JOB_OBJECT));
254
255
    pJob->rxBuffer = rxBuffer;
256
    pJob->dataLeftToRx = size;
257
    pJob->dummyLeftToTx = size;
258
    pJob->completeCB = completeCB;
259
    pJob->context = context;
260
    pJob->status = DRV_SPI_BUFFER_EVENT_PENDING;
261
262
    if (jobHandle != NULL )
263
    {
264
        *jobHandle = (DRV_SPI_BUFFER_HANDLE)pJob;
265
    }
266
267
    if (DRV_SPI_SYS_QUEUE_EnqueueLock(dObj->queue, (void*)pJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
268
    {
269
        SYS_ASSERT(false, "\r\nSPI Driver: Error enqueing new job.");
270
        return (DRV_SPI_BUFFER_HANDLE)NULL;
271
    }
272
273
    return (DRV_SPI_BUFFER_HANDLE)pJob;
274
}
275
276
277
DRV_SPI_BUFFER_HANDLE DRV_SPI0_BufferAddWrite2 ( void *txBuffer, size_t size, DRV_SPI_BUFFER_EVENT_HANDLER completeCB, void * context, DRV_SPI_BUFFER_HANDLE * jobHandle )
278
{
279
    DRV_SPI_OBJ *dObj = (DRV_SPI_OBJ*)NULL;
280
281
    dObj = &gDrvSPI0Obj;
282
283
    DRV_SPI_JOB_OBJECT * pJob = NULL;
284
    if (DRV_SPI_SYS_QUEUE_AllocElementLock(dObj->queue, (void **)&pJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
285
    {
286
        SYS_ASSERT(false, "\r\nSPI Driver: Error trying to get a free entry.");
287
        return (DRV_SPI_BUFFER_HANDLE)NULL;
288
    }
289
290
    memset(pJob, 0, sizeof(DRV_SPI_JOB_OBJECT));
291
    pJob->txBuffer = txBuffer;
292
    pJob->dataLeftToTx = size;
293
    pJob->dummyLeftToRx = size;
294
    pJob->completeCB = completeCB;
295
    pJob->context = context;
296
    pJob->status = DRV_SPI_BUFFER_EVENT_PENDING;
297
298
    if (jobHandle != NULL )
299
    {
300
        *jobHandle = (DRV_SPI_BUFFER_HANDLE)pJob;
301
    }
302
303
    if (DRV_SPI_SYS_QUEUE_EnqueueLock(dObj->queue, (void*)pJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
304
    {
305
        SYS_ASSERT(false, "\r\nSPI Driver: Error enqueing new job.");
306
        return (DRV_SPI_BUFFER_HANDLE)NULL;
307
    }
308
309
    return (DRV_SPI_BUFFER_HANDLE)pJob;
310
}
311
312
313
DRV_SPI_BUFFER_HANDLE DRV_SPI0_BufferAddWriteRead2 ( void *txBuffer, size_t txSize, void *rxBuffer, size_t rxSize, DRV_SPI_BUFFER_EVENT_HANDLER completeCB, void * context, DRV_SPI_BUFFER_HANDLE * jobHandle )
314
{
315
    DRV_SPI_OBJ *dObj = (DRV_SPI_OBJ*)NULL;
316
317
    dObj = &gDrvSPI0Obj;
318
319
    DRV_SPI_JOB_OBJECT * pJob = NULL;
320
    if (DRV_SPI_SYS_QUEUE_AllocElementLock(dObj->queue, (void **)&pJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
321
    {
322
        SYS_ASSERT(false, "\r\nSPI Driver: Error trying to get a free entry.");
323
        return (DRV_SPI_BUFFER_HANDLE)NULL;
324
    }
325
326
    memset(pJob, 0, sizeof(DRV_SPI_JOB_OBJECT));
327
    pJob->txBuffer = txBuffer;
328
    pJob->dataLeftToTx = txSize;
329
    pJob->rxBuffer = rxBuffer;
330
    pJob->dataLeftToRx = rxSize;
331
332
    if (jobHandle != NULL )
333
    {
334
        *jobHandle = (DRV_SPI_BUFFER_HANDLE)pJob;
335
    }
336
    if (rxSize > txSize)
337
    {
338
        pJob->dummyLeftToTx = rxSize - txSize;
339
    }
340
    if (txSize > rxSize)
341
    {
342
        pJob->dummyLeftToRx = txSize - rxSize;
343
    }
344
    pJob->completeCB = completeCB;
345
    pJob->context = context;
346
    pJob->status = DRV_SPI_BUFFER_EVENT_PENDING;
347
348
    if (DRV_SPI_SYS_QUEUE_EnqueueLock(dObj->queue, (void*)pJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
349
    {
350
        SYS_ASSERT(false, "\r\nSPI Driver: Error enqueing new job.");
351
        return (DRV_SPI_BUFFER_HANDLE)NULL;
352
    }
353
354
    return (DRV_SPI_BUFFER_HANDLE)pJob;
355
}
356
357
358
DRV_SPI_BUFFER_HANDLE DRV_SPI0_BufferAddRead ( void *rxBuffer, size_t size, DRV_SPI_BUFFER_EVENT_HANDLER completeCB, void * context)
359
{
360
    return DRV_SPI0_BufferAddRead2(rxBuffer, size, completeCB, context, NULL);
361
}
362
363
DRV_SPI_BUFFER_HANDLE DRV_SPI0_BufferAddWrite ( void *txBuffer, size_t size, DRV_SPI_BUFFER_EVENT_HANDLER completeCB, void * context )
364
{
365
    return DRV_SPI0_BufferAddWrite2(txBuffer, size, completeCB, context, NULL);
366
}
367
368
DRV_SPI_BUFFER_EVENT DRV_SPI0_BufferStatus ( DRV_SPI_BUFFER_HANDLE bufferHandle )
369
{
370
    DRV_SPI_JOB_OBJECT * pJob = (DRV_SPI_JOB_OBJECT *)bufferHandle;
371
372
    return pJob->status;
373
}
374
375
376
int32_t DRV_SPI0_PolledErrorTasks(struct DRV_SPI_OBJ * dObj)
377
{
378
379
    if (dObj->currentJob == NULL)
380
    {
381
        return 0;
382
    }
383
384
    register DRV_SPI_JOB_OBJECT * currentJob = dObj->currentJob;
385
386
    if (PLIB_SPI_ReceiverHasOverflowed(SPI_ID_1))
387
    {
388
        currentJob->status = DRV_SPI_BUFFER_EVENT_ERROR;
389
        if (currentJob->completeCB != NULL)
390
        {
391
            (*currentJob->completeCB)(DRV_SPI_BUFFER_EVENT_ERROR, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
392
        }
393
        if (dObj->operationEnded != NULL)
394
        {
395
            (*dObj->operationEnded)(DRV_SPI_BUFFER_EVENT_ERROR, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
396
        }
397
        if (DRV_SPI_SYS_QUEUE_FreeElementLock(dObj->queue, currentJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
398
        {
399
            SYS_ASSERT(false, "\r\nSPI Driver: Queue free element error.");
400
            return 0;
401
        }
402
        dObj->currentJob = NULL;
403
        PLIB_SPI_BufferClear(SPI_ID_1 );
404
        PLIB_SPI_ReceiverOverflowClear (SPI_ID_1 );
405
    }
406
    return 0;
407
}
408
409
410
// *********************************************************************************************
411
// *********************************************************************************************
412
// Section: Old static driver compatibility APIs, these will be deprecated.
413
// *********************************************************************************************
414
// *********************************************************************************************
415
bool DRV_SPI0_ReceiverBufferIsFull(void)
416
{
417
    return (PLIB_SPI_ReceiverBufferIsFull(SPI_ID_1));
418
}
419
420
bool DRV_SPI0_TransmitterBufferIsFull(void)
421
{
422
    return (PLIB_SPI_TransmitBufferIsFull(SPI_ID_1));
423
}
424
425
int32_t DRV_SPI0_BufferAddWriteRead(const void * txBuffer, void * rxBuffer, uint32_t size)
426
{
427
    bool continueLoop;
428
    int32_t txcounter = 0;
429
    int32_t rxcounter = 0;
430
    do {
431
        continueLoop = false;
432
        if(!PLIB_SPI_TransmitBufferIsFull(SPI_ID_1) && txcounter < size)
433
        {
434
            PLIB_SPI_BufferWrite(SPI_ID_1, ((uint8_t*)txBuffer)[txcounter]);
435
            txcounter++;
436
            continueLoop = true;
437
        }
438
439
        while (txcounter != rxcounter)
440
        {
441
            while(!PLIB_SPI_ReceiverBufferIsFull(SPI_ID_1));
442
            ((uint8_t*)rxBuffer)[rxcounter] = PLIB_SPI_BufferRead(SPI_ID_1);
443
            rxcounter++;
444
            continueLoop = true;
445
        }
446
        if (txcounter > rxcounter)
447
        {
448
            continueLoop = true;
449
        }
450
    }while(continueLoop);
451
    return txcounter;
452
}
453