1 /**
2   **************************************************************************
3   * @file     usbd_int.c
4   * @brief    usb interrupt request
5   **************************************************************************
6   *                       Copyright notice & Disclaimer
7   *
8   * The software Board Support Package (BSP) that is made available to
9   * download from Artery official website is the copyrighted work of Artery.
10   * Artery authorizes customers to use, copy, and distribute the BSP
11   * software and its related documentation for the purpose of design and
12   * development in conjunction with Artery microcontrollers. Use of the
13   * software is governed by this copyright notice and the following disclaimer.
14   *
15   * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
16   * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
17   * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
18   * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
19   * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
21   *
22   **************************************************************************
23   */
24 
25 #include "usbd_int.h"
26 
27 /** @defgroup USBD_drivers_interrupt
28   * @brief usb device interrupt
29   * @{
30   */
31 
32 /** @defgroup USBD_int_private_functions
33   * @{
34   */
35 
36 #ifdef BSP_USING_USBD
37 
38 /**
39   * @brief  usb device interrput request handler.
40   * @param  udev: to the structure of usbd_core_type
41   * @retval none
42   */
usbd_irq_handler(usbd_core_type * udev)43 void usbd_irq_handler(usbd_core_type *udev)
44 {
45   usbd_type *usbx = udev->usb_reg;
46   uint32_t sts_val = usbx->intsts;
47   uint32_t sts_ien = usbx->ctrl;
48 
49   if(sts_val & USB_TC_FLAG)
50   {
51     /* endpoint tc interrupt handler */
52     usbd_ept_loop_handler(udev);
53   }
54 
55   if(sts_val & USB_RST_FLAG)
56   {
57     /* clear reset flag */
58     usb_flag_clear(usbx, USB_RST_FLAG);
59 
60     /* reset interrupt handler */
61     usbd_reset_handler(udev);
62   }
63 
64   if((sts_val & USB_SOF_FLAG) &&
65     (sts_ien & USB_SOF_INT))
66   {
67     /* clear sof flag */
68     usb_flag_clear(usbx, USB_SOF_FLAG);
69 
70     /* sof interrupt handler */
71     usbd_sof_callback(udev);
72   }
73 
74   if((sts_val & USB_LSOF_FLAG) &&
75     (sts_ien & USB_LSOF_INT))
76   {
77     /* clear lsof flag */
78     usb_flag_clear(usbx, USB_LSOF_FLAG);
79   }
80 
81   if((sts_val & USB_SP_FLAG) &&
82     (sts_ien & USB_SP_INT))
83   {
84     /* clear suspend flag */
85     usb_flag_clear(usbx, USB_SP_FLAG);
86 
87     /* usb suspend interrupt handler */
88     usbd_suspend_handler(udev);
89   }
90 
91   if((sts_val & USB_WK_FLAG) &&
92     (sts_ien & USB_WK_INT))
93   {
94     /* usb wakeup interrupt handler */
95     usbd_wakeup_handler(udev);
96 
97     /* clear wakeup flag */
98     usb_flag_clear(usbx, USB_WK_FLAG);
99   }
100 }
101 
102 /**
103   * @brief  usb device endpoint request handler.
104   * @param  udev: to the structure of usbd_core_type
105   * @param  ept_num: endpoint number
106   * @retval none
107   */
usbd_eptn_handler(usbd_core_type * udev,usb_ept_number_type ept_num)108 void usbd_eptn_handler(usbd_core_type *udev, usb_ept_number_type ept_num)
109 {
110   usbd_type *usbx = udev->usb_reg;
111   usb_ept_info *ept_info;
112   uint32_t ept_val = usbx->ept[ept_num];
113   uint16_t length;
114 
115   /* in interrupt request  */
116   if(ept_val & USB_TXTC)
117   {
118     /* get endpoint register and in transfer info struct */
119     ept_info = &udev->ept_in[ept_num];
120 
121     /* clear endpoint tc flag */
122     USB_CLEAR_TXTC(ept_num);
123 
124     /* get endpoint tx length */
125     ept_info->trans_len = USB_GET_TX_LEN(ept_num);
126 
127     /* offset the trans buffer */
128     ept_info->trans_buf += ept_info->trans_len;
129 
130     if(ept_info->total_len == 0 || ept_num == USB_EPT0)
131     {
132       /* in transfer complete */
133       usbd_data_in_stage_callback(udev,ept_num);
134     }
135     else
136     {
137       /* endpoint continue send data */
138       usbd_ept_send(udev, ept_num, ept_info->trans_buf, ept_info->total_len);
139     }
140     /* set the host assignment address */
141     if(udev->conn_state == USB_CONN_STATE_ADDRESSED && udev->device_addr > 0)
142     {
143       usb_set_address(udev->usb_reg, udev->device_addr);
144       udev->device_addr = 0;
145     }
146   }
147   else
148   {
149     /* setup and out interrupt request */
150 
151     /* get endpoint register and out transfer info struct */
152     ept_info = &udev->ept_out[ept_num];
153 
154     if((ept_val & USB_SETUPTC) != 0)
155     {
156       /* endpoint setup interrupt request */
157 
158       /* get endpoint received data length */
159       ept_info->trans_len = USB_GET_RX_LEN(ept_num);
160 
161       /* read endpoint received data */
162       usb_read_packet(udev->setup_buffer, ept_info->rx_addr, ept_info->trans_len);
163 
164       /* clear endpoint rx tc flag */
165       USB_CLEAR_RXTC(USB_EPT0);
166 
167       /* endpoint setup complete handler */
168       usbd_core_setup_handler(udev, ept_num);
169       usbd_setup_phase_done_callback(udev);
170     }
171     else if(ept_val & USB_RXTC )
172     {
173       /* endpoint out interrupt request */
174       USB_CLEAR_RXTC(ept_num);
175 
176       if(ept_info->is_double_buffer == 0)
177       {
178         /* get endpoint received data length */
179         length = USB_GET_RX_LEN(ept_num);
180 
181         /* read endpoint received data */
182         usb_read_packet(ept_info->trans_buf, ept_info->rx_addr, length);
183       }
184       else
185       {
186         if( ept_val & USB_RXDTS)
187         {
188           length = USB_DBUF0_GET_LEN(ept_num);
189           usb_read_packet(ept_info->trans_buf, ept_info->tx_addr, length);
190         }
191         else
192         {
193           length = USB_DBUF1_GET_LEN(ept_num);
194           usb_read_packet(ept_info->trans_buf, ept_info->rx_addr, length);
195         }
196         USB_FREE_DB_USER_BUFFER(ept_num, DATA_TRANS_OUT);
197       }
198 
199       /* set received data length */
200       ept_info->trans_len += length;
201       ept_info->trans_buf += length;
202 
203       if(ept_info->total_len == 0 || length < ept_info->maxpacket || ept_num == USB_EPT0)
204       {
205         /* out transfer complete */
206         usbd_data_out_stage_callback(udev, ept_num);
207       }
208       else
209       {
210         /* endpoint continue receive data  */
211         usbd_ept_recv(udev, ept_num, ept_info->trans_buf, ept_info->total_len);
212       }
213     }
214   }
215 }
216 
217 /**
218   * @brief  usb device endpoint loop handler.
219   * @param  udev: to the structure of usbd_core_type
220   * @retval none
221   */
usbd_ept_loop_handler(usbd_core_type * udev)222 void usbd_ept_loop_handler(usbd_core_type *udev)
223 {
224   usbd_type *usbx = udev->usb_reg;
225   usb_ept_number_type ept_num = USB_EPT0;
226   uint32_t sts_val;
227 
228   while((sts_val = usbx->intsts) & USB_TC_FLAG)
229   {
230     /* get the interrupt endpoint number */
231     ept_num = (usb_ept_number_type)(sts_val & USB_EPT_NUM_FLAG);
232 
233     usbd_eptn_handler(udev, ept_num);
234   }
235 }
236 
237 /**
238   * @brief  usb device reset interrupt request handler.
239   * @param  udev: to the structure of usbd_core_type
240   * @retval none
241   */
usbd_reset_handler(usbd_core_type * udev)242 void usbd_reset_handler(usbd_core_type *udev)
243 {
244   /* free usb buffer */
245   usb_buffer_free();
246 
247   usbd_ept_defaut_init(udev);
248 #ifndef USB_EPT_AUTO_MALLOC_BUFFER
249   usbd_ept_buf_custom_define(udev, 0x80, EPT0_TX_ADDR);
250   usbd_ept_buf_custom_define(udev, 0x00, EPT0_RX_ADDR);
251 #endif
252 
253   /* open endpoint 0 out */
254   usbd_ept_open(udev, 0x00, EPT_CONTROL_TYPE, 0x40);
255 
256   /* open endpoint 0 in */
257   usbd_ept_open(udev, 0x80, EPT_CONTROL_TYPE, 0x40);
258 
259   /* set device address to 0 */
260   usb_set_address(udev->usb_reg, 0);
261 
262   /* usb connect state set to default */
263   udev->conn_state = USB_CONN_STATE_DEFAULT;
264 
265   /* user define reset event */
266   usbd_reset_callback(udev);
267 }
268 
269 /**
270   * @brief  usb device sof interrupt request handler.
271   * @param  udev: to the structure of usbd_core_type
272   * @retval none
273   */
usbd_sof_handler(usbd_core_type * udev)274 void usbd_sof_handler(usbd_core_type *udev)
275 {
276   /* user sof handler in class define*/
277   if(udev->class_handler->sof_handler)
278     udev->class_handler->sof_handler(udev);
279 }
280 
281 /**
282   * @brief  usb device suspend interrupt request handler.
283   * @param  udev: to the structure of usbd_core_type
284   * @retval none
285   */
usbd_suspend_handler(usbd_core_type * udev)286 void usbd_suspend_handler(usbd_core_type *udev)
287 {
288   /* save connect state */
289   udev->old_conn_state = udev->conn_state;
290 
291   /* set current state to suspend */
292   udev->conn_state = USB_CONN_STATE_SUSPENDED;
293 
294   /* enter suspend mode */
295   usbd_enter_suspend(udev);
296 }
297 
298 /**
299   * @brief  usb device wakup interrupt request handler.
300   * @param  udev: to the structure of usbd_core_type
301   * @retval none
302   */
usbd_wakeup_handler(usbd_core_type * udev)303 void usbd_wakeup_handler(usbd_core_type *udev)
304 {
305   /* exit suspend mode */
306   usb_exit_suspend(udev->usb_reg);
307 
308   /* restore connect state */
309   udev->conn_state = udev->old_conn_state;
310 
311   /* user define wakeup event */
312 }
313 
usbd_reset_callback(usbd_core_type * udev)314 rt_weak void usbd_reset_callback(usbd_core_type *udev)
315 {
316 }
317 
usbd_setup_phase_done_callback(usbd_core_type * udev)318 rt_weak void usbd_setup_phase_done_callback(usbd_core_type *udev)
319 {
320 }
321 
usbd_data_in_stage_callback(usbd_core_type * udev,uint32_t ept_num)322 rt_weak void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num)
323 {
324 }
325 
usbd_sof_callback(usbd_core_type * udev)326 rt_weak void usbd_sof_callback(usbd_core_type *udev)
327 {
328 }
329 
usbd_data_out_stage_callback(usbd_core_type * udev,uint32_t ept_num)330 rt_weak void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num)
331 {
332 }
333 
usbd_connectCallback(usbd_core_type * udev)334 rt_weak void usbd_connectCallback(usbd_core_type *udev)
335 {
336 }
337 
usbd_disconnectCallback(usbd_core_type * udev)338 rt_weak void usbd_disconnectCallback(usbd_core_type *udev)
339 {
340 }
341 
342 #endif
343 
344 /**
345   * @}
346   */
347 
348 /**
349   * @}
350   */
351 
352