Statistics
| Branch: | Tag: | Revision:

mongoose / examples / PIC32 / http_server / firmware / src / system_config / pic32mx_eth_sk2_encx24j600 / framework / driver / spi / dynamic / drv_spi_tasks.c @ eaef5bd1

History | View | Annotate | Download (8.95 KB)

1
/* clang-format off */
2
/*******************************************************************************
3
  SPI Driver Functions for Dynamic Driver Tasks Functions
4

5
  Company:
6
    Microchip Technology Inc.
7

8
  File Name:
9
    drv_spi_dynamic_tasks.c
10

11
  Summary:
12
    SPI driver tasks functions
13

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

19
  Remarks:
20
  This file is generated from framework/driver/spi/template/drv_spi_dynamic_tasks.c.ftl
21
*******************************************************************************/
22

    
23
//DOM-IGNORE-BEGIN
24
/*******************************************************************************
25
Copyright (c) 2013 released Microchip Technology Inc.  All rights reserved.
26

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

32
You should refer to the license agreement accompanying this Software for
33
additional information regarding your rights and obligations.
34

35
SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
36
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
37
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
38
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
39
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
40
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
41
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
42
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
43
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
44
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
45
*******************************************************************************/
46
//DOM-IGNORE-END
47
#include "driver/spi/src/dynamic/drv_spi_internal.h"
48
#include <stdbool.h>
49

    
50

    
51

    
52
int32_t DRV_SPI_ISRMasterEBM8BitTasks ( struct DRV_SPI_DRIVER_OBJECT * pDrvInstance )
53
{
54
    volatile bool continueLoop;
55

    
56
    /* Disable the interrupts */
57
    SYS_INT_SourceDisable(pDrvInstance->rxInterruptSource);
58
    SYS_INT_SourceDisable(pDrvInstance->txInterruptSource);
59
    SYS_INT_SourceDisable(pDrvInstance->errInterruptSource);
60
    do {
61

    
62
        DRV_SPI_JOB_OBJECT * currentJob = pDrvInstance->currentJob;
63
        SPI_MODULE_ID spiId = pDrvInstance->spiId;
64
        /* Check for a new task */
65
        if (pDrvInstance->currentJob == NULL)
66
        {
67
            if (DRV_SPI_SYS_QUEUE_Dequeue(pDrvInstance->queue, (void *)&(pDrvInstance->currentJob)) != DRV_SPI_SYS_QUEUE_SUCCESS)
68
            {
69
                SYS_ASSERT(false, "\r\nSPI Driver: Error in dequeing.");
70
                return 0;
71
            }
72
            if (pDrvInstance->currentJob == NULL)
73
            {
74
                pDrvInstance->txEnabled = false;
75
                return 0;
76
            }
77
            currentJob = pDrvInstance->currentJob;
78

    
79
            pDrvInstance->symbolsInProgress = 0;
80

    
81
            /* Call the operation starting function pointer.  This can be used to modify the slave select lines */
82
            DRV_SPI_CLIENT_OBJECT * pClient = (DRV_SPI_CLIENT_OBJECT*)currentJob->pClient;
83
            if (pClient->operationStarting != NULL)
84
            {
85
                (*pClient->operationStarting)(DRV_SPI_BUFFER_EVENT_PROCESSING, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
86
            }
87
            /* Check the baud rate.  If its different set the new baud rate*/
88
            if (pClient->baudRate != pDrvInstance->currentBaudRate)
89
            {
90
                PLIB_SPI_BaudRateSet( spiId , SYS_CLK_PeripheralFrequencyGet(pDrvInstance->spiClk), pClient->baudRate );
91
                pDrvInstance->currentBaudRate = pClient->baudRate;
92
            }
93

    
94
            /* List the new job as processing*/
95
            currentJob->status = DRV_SPI_BUFFER_EVENT_PROCESSING;
96
            if (currentJob->dataLeftToTx +currentJob->dummyLeftToTx > PLIB_SPI_RX_8BIT_FIFO_SIZE(spiId))
97
            {
98
                PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_TRANSMIT_BUFFER_IS_1HALF_EMPTY_OR_MORE);
99
                PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_RECEIVE_BUFFER_IS_1HALF_FULL_OR_MORE);
100
            }
101
            /* Flush out the Receive buffer */
102
            PLIB_SPI_BufferClear(spiId);
103
        }
104

    
105

    
106
        continueLoop = false;
107
        /* Execute the sub tasks */
108
             if
109
            (currentJob->dataLeftToTx +currentJob->dummyLeftToTx != 0)
110
        {
111
            DRV_SPI_MasterEBMSend8BitISR(pDrvInstance);
112
        }
113

    
114
        DRV_SPI_ISRErrorTasks(pDrvInstance);
115

    
116
        /* Figure out how many bytes are left to be received */
117
        volatile size_t bytesLeft = currentJob->dataLeftToRx + currentJob->dummyLeftToRx;
118
        // Check to see if we have any data left to receive and update the bytes left.
119

    
120
        if (bytesLeft != 0)
121
        {
122
            DRV_SPI_MasterEBMReceive8BitISR(pDrvInstance);
123
            bytesLeft = currentJob->dataLeftToRx + currentJob->dummyLeftToRx;
124
        }
125

    
126
        if (bytesLeft == 0)
127
        {
128
                    // Disable the interrupt, or more correctly don't re-enable it later*/
129
                    pDrvInstance->rxEnabled = false;
130
                    /* Job is complete*/
131
                    currentJob->status = DRV_SPI_BUFFER_EVENT_COMPLETE;
132
                    /* Call the job complete call back*/
133
                    if (currentJob->completeCB != NULL)
134
                    {
135
                        (*currentJob->completeCB)(DRV_SPI_BUFFER_EVENT_COMPLETE, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
136
                    }
137
                    /* Call the operation complete call back.  This is different than the
138
                       job complete callback.  This can be used to modify the Slave Select line.
139
                       The job complete callback can be used to free a client that is blocked
140
                       waiting for complete*/
141
                    DRV_SPI_CLIENT_OBJECT * pClient = (DRV_SPI_CLIENT_OBJECT*)currentJob->pClient;
142
                    if (pClient->operationEnded != NULL)
143
                    {
144
                        (*pClient->operationEnded)(DRV_SPI_BUFFER_EVENT_COMPLETE, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
145
                    }
146
                    /* Return the job back to the free queue*/
147
                    if (DRV_SPI_SYS_QUEUE_FreeElement(pDrvInstance->queue, currentJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
148
                    {
149
                        SYS_ASSERT(false, "\r\nSPI Driver: Queue free element error.");
150
                        return 0;
151
                    }
152
                    /* Clean up */
153
                    pDrvInstance->currentJob = NULL;
154
                    if (!DRV_SPI_SYS_QUEUE_IsEmpty(pDrvInstance->queue))
155
                    {
156
                        continueLoop = true;
157
                        continue;
158
                    }
159
                    else
160
                    {
161
                        break;
162
                    }
163
                }
164

    
165

    
166
        /* Check to see if the interrupts would fire again if so just go back into
167
           the loop instead of suffering the interrupt latency of exiting and re-entering*/
168
        if (pDrvInstance->currentJob != NULL)
169
        {
170
            /* Clear the Interrupts */
171
            SYS_INT_SourceStatusClear(pDrvInstance->rxInterruptSource);
172
            SYS_INT_SourceStatusClear(pDrvInstance->txInterruptSource);
173
            SYS_INT_SourceStatusClear(pDrvInstance->errInterruptSource);
174
            /* Interrupts should immediately become active again if they're in a fired condition */
175
            if ((SYS_INT_SourceStatusGet(pDrvInstance->rxInterruptSource)) ||
176
                (SYS_INT_SourceStatusGet(pDrvInstance->txInterruptSource)) ||
177
                (SYS_INT_SourceStatusGet(pDrvInstance->errInterruptSource)))
178
            {
179
                /* Interrupt would fire again anyway so we should just go back to the start*/
180
                continueLoop = true;
181
                continue;
182
            }
183
            /* If we're here then we know that the interrupt should not be firing again immediately, so re-enable them and exit*/
184
            SYS_INT_SourceEnable(pDrvInstance->rxInterruptSource);
185
            SYS_INT_SourceEnable(pDrvInstance->txInterruptSource);
186

    
187
            return 0;
188
        }
189

    
190
    } while(continueLoop);
191
    /* if we're here it means that we have no more jobs in the queue, tx and rx interrupts will be re-enabled by the BufferAdd* functions*/
192
    SYS_INT_SourceStatusClear(pDrvInstance->rxInterruptSource);
193
    SYS_INT_SourceStatusClear(pDrvInstance->txInterruptSource);
194
    return 0;
195
}
196

    
197

    
198

    
199

    
200

    
201

    
202

    
203