1 /*****************************************************************************
2  * Copyright (c) 2019, Nations Technologies Inc.
3  *
4  * All rights reserved.
5  * ****************************************************************************
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the disclaimer below.
12  *
13  * Nations' name may not be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
19  * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  * ****************************************************************************/
27 
28 /**
29  * @file usb_int.c
30  * @author Nations
31  * @version v1.0.0
32  *
33  * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
34  */
35 #include "usb_lib.h"
36 
37 __IO uint16_t SaveRState;
38 __IO uint16_t SaveTState;
39 
40 extern void (*pEpInt_IN[7])(void);  /*  Handles IN  interrupts   */
41 extern void (*pEpInt_OUT[7])(void); /*  Handles OUT interrupts   */
42 
43 /**
44  * @brief Low priority Endpoint Correct Transfer interrupt's service routine.
45  */
USB_CorrectTransferLp(void)46 void USB_CorrectTransferLp(void)
47 {
48     __IO uint16_t wEPVal = 0;
49     /* stay in loop while pending interrupts */
50     while (((wIstr = _GetISTR()) & STS_CTRS) != 0)
51     {
52         /* extract highest priority endpoint number */
53         EPindex = (uint8_t)(wIstr & STS_EP_ID);
54         if (EPindex == 0)
55         {
56             /* Decode and service control endpoint interrupt */
57             /* calling related service routine */
58             /* (USB_ProcessSetup0, USB_ProcessIn0, USB_ProcessOut0) */
59 
60             /* save RX & TX status */
61             /* and set both to NAK */
62 
63             SaveRState = _GetENDPOINT(ENDP0);
64             SaveTState = SaveRState & EPTX_STS;
65             SaveRState &= EPRX_STS;
66             _SetEPRxTxStatus(ENDP0, EP_RX_NAK, EP_TX_NAK);
67 
68             /* DIR bit = origin of the interrupt */
69 
70             if ((wIstr & STS_DIR) == 0)
71             {
72                 /* DIR = 0 */
73 
74                 /* DIR = 0      => IN  int */
75                 /* DIR = 0 implies that (EP_CTRS_TX = 1) always  */
76 
77                 _ClearEP_CTR_TX(ENDP0);
78                 USB_ProcessIn0();
79 
80                 /* before terminate set Tx & Rx status */
81 
82                 _SetEPRxTxStatus(ENDP0, SaveRState, SaveTState);
83                 return;
84             }
85             else
86             {
87                 /* DIR = 1 */
88 
89                 /* DIR = 1 & CTR_RX       => SETUP or OUT int */
90                 /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
91 
92                 wEPVal = _GetENDPOINT(ENDP0);
93 
94                 if ((wEPVal & EP_SETUP) != 0)
95                 {
96                     _ClearEP_CTR_RX(ENDP0); /* SETUP bit kept frozen while CTR_RX = 1 */
97                     USB_ProcessSetup0();
98                     /* before terminate set Tx & Rx status */
99 
100                     _SetEPRxTxStatus(ENDP0, SaveRState, SaveTState);
101                     return;
102                 }
103 
104                 else if ((wEPVal & EP_CTRS_RX) != 0)
105                 {
106                     _ClearEP_CTR_RX(ENDP0);
107                     USB_ProcessOut0();
108                     /* before terminate set Tx & Rx status */
109 
110                     _SetEPRxTxStatus(ENDP0, SaveRState, SaveTState);
111                     return;
112                 }
113             }
114         } /* if (EPindex == 0) */
115         else
116         {
117             /* Decode and service non control endpoints interrupt  */
118 
119             /* process related endpoint register */
120             wEPVal = _GetENDPOINT(EPindex);
121             if ((wEPVal & EP_CTRS_RX) != 0)
122             {
123                 /* clear int flag */
124                 _ClearEP_CTR_RX(EPindex);
125 
126                 /* call OUT service function */
127                 (*pEpInt_OUT[EPindex - 1])();
128 
129             } /* if ((wEPVal & EP_CTRS_RX) */
130 
131             if ((wEPVal & EP_CTRS_TX) != 0)
132             {
133                 /* clear int flag */
134                 _ClearEP_CTR_TX(EPindex);
135 
136                 /* call IN service function */
137                 (*pEpInt_IN[EPindex - 1])();
138             } /* if ((wEPVal & EP_CTRS_TX) != 0) */
139 
140         } /* if (EPindex == 0) else */
141 
142     } /* while (...) */
143 }
144 
145 /**
146  * @brief High Priority Endpoint Correct Transfer interrupt's service routine.
147  */
USB_CorrectTransferHp(void)148 void USB_CorrectTransferHp(void)
149 {
150     uint32_t wEPVal = 0;
151 
152     while (((wIstr = _GetISTR()) & STS_CTRS) != 0)
153     {
154         _SetISTR((uint16_t)CLR_CTRS); /* clear CTR flag */
155         /* extract highest priority endpoint number */
156         EPindex = (uint8_t)(wIstr & STS_EP_ID);
157         /* process related endpoint register */
158         wEPVal = _GetENDPOINT(EPindex);
159         if ((wEPVal & EP_CTRS_RX) != 0)
160         {
161             /* clear int flag */
162             _ClearEP_CTR_RX(EPindex);
163 
164             /* call OUT service function */
165             (*pEpInt_OUT[EPindex - 1])();
166 
167         } /* if ((wEPVal & EP_CTRS_RX) */
168         else if ((wEPVal & EP_CTRS_TX) != 0)
169         {
170             /* clear int flag */
171             _ClearEP_CTR_TX(EPindex);
172 
173             /* call IN service function */
174             (*pEpInt_IN[EPindex - 1])();
175 
176         } /* if ((wEPVal & EP_CTRS_TX) != 0) */
177 
178     } /* while (...) */
179 }
180