1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /****************************************************************************
5 Contents : usb communication handling code for NanoXplore USB-JTAG *
6 ANGIE adapter hardware. *
7 Based on openULINK project code by: Martin Schmoelzer. *
8 Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
9 <aboudjelida@nanoxplore.com> *
10 <ahmederrachedbjld@gmail.com> *
11 *****************************************************************************/
17 #include "reg_ezusb.h"
18 #include <fx2macros.h>
23 /* Also update external declarations in "include/usb.h" if making changes to
26 volatile bool ep1_out
;
29 volatile __xdata __at
0xE6B8 struct setup_data setup_data
;
31 /* Define number of endpoints (except Control Endpoint 0) in a central place.
32 * Be sure to include the necessary endpoint descriptors!
34 #define NUM_ENDPOINTS 3
36 __code
struct usb_device_descriptor device_descriptor
= {
37 .blength
= sizeof(struct usb_device_descriptor
),
38 .bdescriptortype
= DESCRIPTOR_TYPE_DEVICE
,
39 .bcdusb
= 0x0200, /* BCD: 02.00 (Version 2.0 USB spec) */
41 .bdevicesubclass
= 0x02,
42 .bdeviceprotocol
= 0x01,
43 .bmaxpacketsize0
= 64,
50 .bnumconfigurations
= 1
53 /* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
55 __code
struct usb_config_descriptor config_descriptor
= {
56 .blength
= sizeof(struct usb_config_descriptor
),
57 .bdescriptortype
= DESCRIPTOR_TYPE_CONFIGURATION
,
58 .wtotallength
= sizeof(struct usb_config_descriptor
) +
59 3 * sizeof(struct usb_interface_descriptor
) +
60 ((NUM_ENDPOINTS
+ 2) * sizeof(struct usb_endpoint_descriptor
)),
62 .bconfigurationvalue
= 1,
63 .iconfiguration
= 1, /* String describing this configuration */
64 .bmattributes
= 0x80, /* Only MSB set according to USB spec */
65 .maxpower
= 50 /* 100 mA */
68 __code
struct usb_interface_association_descriptor interface_association_descriptor
= {
69 .blength
= sizeof(struct usb_interface_association_descriptor
),
70 .bdescriptortype
= DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION
,
71 .bfirstinterface
= 0x01,
72 .binterfacecount
= 0x02,
73 .bfunctionclass
= 0x02,
74 .bfunctionsubclass
= 0x00,
75 .bfunctionprotocol
= 0x00,
79 __code
struct usb_interface_descriptor interface_descriptor00
= {
80 .blength
= sizeof(struct usb_interface_descriptor
),
81 .bdescriptortype
= DESCRIPTOR_TYPE_INTERFACE
,
82 .binterfacenumber
= 0,
83 .balternatesetting
= 0,
84 .bnumendpoints
= NUM_ENDPOINTS
,
85 .binterfaceclass
= 0XFF,
86 .binterfacesubclass
= 0x00,
87 .binterfaceprotocol
= 0x00,
91 __code
struct usb_endpoint_descriptor bulk_ep1_out_endpoint_descriptor
= {
92 .blength
= sizeof(struct usb_endpoint_descriptor
),
93 .bdescriptortype
= 0x05,
94 .bendpointaddress
= (1 | USB_DIR_OUT
),
100 __code
struct usb_endpoint_descriptor bulk_ep1_in_endpoint_descriptor
= {
101 .blength
= sizeof(struct usb_endpoint_descriptor
),
102 .bdescriptortype
= 0x05,
103 .bendpointaddress
= (1 | USB_DIR_IN
),
104 .bmattributes
= 0x02,
105 .wmaxpacketsize
= 64,
109 __code
struct usb_endpoint_descriptor bulk_ep2_endpoint_descriptor
= {
110 .blength
= sizeof(struct usb_endpoint_descriptor
),
111 .bdescriptortype
= 0x05,
112 .bendpointaddress
= (2 | USB_DIR_OUT
),
113 .bmattributes
= 0x02,
114 .wmaxpacketsize
= 512,
118 __code
struct usb_interface_descriptor interface_descriptor01
= {
119 .blength
= sizeof(struct usb_interface_descriptor
),
120 .bdescriptortype
= DESCRIPTOR_TYPE_INTERFACE
,
121 .binterfacenumber
= 1,
122 .balternatesetting
= 0,
124 .binterfaceclass
= 0x0A,
125 .binterfacesubclass
= 0x00,
126 .binterfaceprotocol
= 0x00,
130 __code
struct usb_endpoint_descriptor bulk_ep6_out_endpoint_descriptor
= {
131 .blength
= sizeof(struct usb_endpoint_descriptor
),
132 .bdescriptortype
= 0x05,
133 .bendpointaddress
= (6 | USB_DIR_OUT
),
134 .bmattributes
= 0x02,
135 .wmaxpacketsize
= 512,
139 __code
struct usb_endpoint_descriptor bulk_ep8_in_endpoint_descriptor
= {
140 .blength
= sizeof(struct usb_endpoint_descriptor
),
141 .bdescriptortype
= 0x05,
142 .bendpointaddress
= (8 | USB_DIR_IN
),
143 .bmattributes
= 0x02,
144 .wmaxpacketsize
= 512,
147 __code
struct usb_language_descriptor language_descriptor
= {
149 .bdescriptortype
= DESCRIPTOR_TYPE_STRING
,
150 .wlangid
= {0x0409} /* US English */
153 __code
struct usb_string_descriptor strmanufacturer
=
154 STR_DESCR(16, 'N', 'a', 'n', 'o', 'X', 'p', 'l', 'o', 'r', 'e', ',', ' ', 'S', 'A', 'S', '.');
156 __code
struct usb_string_descriptor strproduct
=
157 STR_DESCR(13, 'A', 'N', 'G', 'I', 'E', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
159 __code
struct usb_string_descriptor strserialnumber
=
160 STR_DESCR(6, '0', '0', '0', '0', '0', '1');
162 __code
struct usb_string_descriptor strconfigdescr
=
163 STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
165 /* Table containing pointers to string descriptors */
166 __code
struct usb_string_descriptor
*__code en_string_descriptors
[4] = {
172 void sudav_isr(void)__interrupt SUDAV_ISR
174 EXIF
&= ~0x10; /* Clear USBINT: Main global interrupt */
177 usb_handle_setup_data();
179 void sof_isr(void)__interrupt SOF_ISR
182 void sutok_isr(void)__interrupt SUTOK_ISR
185 void suspend_isr(void)__interrupt SUSPEND_ISR
188 void usbreset_isr(void)__interrupt USBRESET_ISR
191 void highspeed_isr(void)__interrupt HIGHSPEED_ISR
194 void ep0ack_isr(void)__interrupt EP0ACK_ISR
197 void stub_isr(void)__interrupt STUB_ISR
200 void ep0in_isr(void)__interrupt EP0IN_ISR
203 void ep0out_isr(void)__interrupt EP0OUT_ISR
206 void ep1in_isr(void)__interrupt EP1IN_ISR
210 EXIF
&= ~0x10; /* Clear USBINT: Main global interrupt */
211 EPIRQ
= 0x04; /* Clear individual EP1IN IRQ */
213 void ep1out_isr(void)__interrupt EP1OUT_ISR
217 EXIF
&= ~0x10; /* Clear USBINT: Main global interrupt */
218 EPIRQ
= 0x08; /* Clear individual EP1OUT IRQ */
220 void ep2_isr(void)__interrupt EP2_ISR
222 ep1_out
= false; /* Does nothing but required by the compiler */
224 void ep4_isr(void)__interrupt EP4_ISR
227 void ep6_isr(void)__interrupt EP6_ISR
230 EXIF
&= ~0x10; /* Clear USBINT: Main global interrupt */
231 EPIRQ
= 0x40; /* Clear individual EP6OUT IRQ */
234 void ep8_isr(void)__interrupt EP8_ISR
236 EXIF
&= ~0x10; /* Clear USBINT: Main global interrupt */
237 EPIRQ
= 0x80; /* Clear individual EP8IN IRQ */
239 void ibn_isr(void)__interrupt IBN_ISR
242 void ep0pingnak_isr(void)__interrupt EP0PINGNAK_ISR
245 void ep1pingnak_isr(void)__interrupt EP1PINGNAK_ISR
248 void ep2pingnak_isr(void)__interrupt EP2PINGNAK_ISR
251 void ep4pingnak_isr(void)__interrupt EP4PINGNAK_ISR
254 void ep6pingnak_isr(void)__interrupt EP6PINGNAK_ISR
257 void ep8pingnak_isr(void)__interrupt EP8PINGNAK_ISR
260 void errorlimit_isr(void)__interrupt ERRORLIMIT_ISR
263 void ep2piderror_isr(void)__interrupt EP2PIDERROR_ISR
266 void ep4piderror_isr(void)__interrupt EP4PIDERROR_ISR
269 void ep6piderror_isr(void)__interrupt EP6PIDERROR_ISR
272 void ep8piderror_isr(void)__interrupt EP8PIDERROR_ISR
275 void ep2pflag_isr(void)__interrupt EP2PFLAG_ISR
278 void ep4pflag_isr(void)__interrupt EP4PFLAG_ISR
281 void ep6pflag_isr(void)__interrupt EP6PFLAG_ISR
284 void ep8pflag_isr(void)__interrupt EP8PFLAG_ISR
287 void ep2eflag_isr(void)__interrupt EP2EFLAG_ISR
290 void ep4eflag_isr(void)__interrupt EP4EFLAG_ISR
293 void ep6eflag_isr(void)__interrupt EP6EFLAG_ISR
296 void ep8eflag_isr(void)__interrupt EP8EFLAG_ISR
299 void ep2fflag_isr(void)__interrupt EP2FFLAG_ISR
302 void ep4fflag_isr(void)__interrupt EP4FFLAG_ISR
305 void ep6fflag_isr(void)__interrupt EP6FFLAG_ISR
308 void ep8fflag_isr(void)__interrupt EP8FFLAG_ISR
311 void gpifcomplete_isr(void)__interrupt GPIFCOMPLETE_ISR
314 void gpifwaveform_isr(void)__interrupt GPIFWAVEFORM_ISR
319 * Return the control/status register for an endpoint
321 * @param ep endpoint address
322 * @return on success: pointer to Control & Status register for endpoint
324 * @return on failure: NULL
326 __xdata
uint8_t *usb_get_endpoint_cs_reg(uint8_t ep
)
328 /* Mask direction bit */
329 uint8_t ep_num
= ep
& ~0x80;
335 return ep
& 0x80 ? &EP1INCS
: &EP1OUTCS
;
349 void usb_reset_data_toggle(uint8_t ep
)
352 +----+-----+-----+------+-----+-------+-------+-------+
353 | Q | S | R | IO | EP3 | EP2 | EP1 | EP0 |
354 +----+-----+-----+------+-----+-------+-------+-------+
356 To reset data toggle bits, we have to write the endpoint direction (IN/OUT)
357 to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a
358 separate write cycle, the R bit needs to be set.
360 TOGCTL
= (((ep
& 0x80) >> 3) + (ep
& 0x0F));
361 TOGCTL
|= BMRESETTOGGLE
;
365 * Handle GET_STATUS request.
367 * @return on success: true
368 * @return on failure: false
370 bool usb_handle_get_status(void)
373 switch (setup_data
.bmrequesttype
) {
375 /* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup.
376 * Byte 1: reserved, reset to zero */
387 /* Always return two zero bytes according to USB 1.1 spec, p. 191 */
398 /* Get stall bit for endpoint specified in low byte of wIndex */
399 ep_cs
= usb_get_endpoint_cs_reg(setup_data
.windex
& 0xff);
401 if (*ep_cs
& EPSTALL
)
406 /* Second byte sent has to be always zero */
422 * Handle CLEAR_FEATURE request.
424 * @return on success: true
425 * @return on failure: false
427 bool usb_handle_clear_feature(void)
429 __xdata
uint8_t *ep_cs
;
431 switch (setup_data
.bmrequesttype
) {
433 /* Clear remote wakeup not supported: stall EP0 */
437 if (setup_data
.wvalue
== 0) {
438 /* Unstall the endpoint specified in wIndex */
439 ep_cs
= usb_get_endpoint_cs_reg(setup_data
.windex
);
444 /* Unsupported feature, stall EP0 */
449 /* Vendor commands... */
456 * Handle SET_FEATURE request.
458 * @return on success: true
459 * @return on failure: false
461 bool usb_handle_set_feature(void)
463 __xdata
uint8_t *ep_cs
;
465 switch (setup_data
.bmrequesttype
) {
467 if (setup_data
.wvalue
== 2)
471 if (setup_data
.wvalue
== 0) {
472 /* Stall the endpoint specified in wIndex */
473 ep_cs
= usb_get_endpoint_cs_reg(setup_data
.windex
);
478 /* Unsupported endpoint feature */
483 /* Vendor commands... */
491 * Handle GET_DESCRIPTOR request.
493 * @return on success: true
494 * @return on failure: false
496 bool usb_handle_get_descriptor(void)
498 __xdata
uint8_t descriptor_type
;
499 __xdata
uint8_t descriptor_index
;
501 descriptor_type
= (setup_data
.wvalue
& 0xff00) >> 8;
502 descriptor_index
= setup_data
.wvalue
& 0x00ff;
504 switch (descriptor_type
) {
505 case DESCRIPTOR_TYPE_DEVICE
:
506 SUDPTRH
= HI8(&device_descriptor
);
507 SUDPTRL
= LO8(&device_descriptor
);
509 case DESCRIPTOR_TYPE_CONFIGURATION
:
510 SUDPTRH
= HI8(&config_descriptor
);
511 SUDPTRL
= LO8(&config_descriptor
);
513 case DESCRIPTOR_TYPE_STRING
:
514 if (setup_data
.windex
== 0) {
515 /* Supply language descriptor */
516 SUDPTRH
= HI8(&language_descriptor
);
517 SUDPTRL
= LO8(&language_descriptor
);
518 } else if (setup_data
.windex
== 0x0409 /* US English */) {
519 /* Supply string descriptor */
520 SUDPTRH
= HI8(en_string_descriptors
[descriptor_index
- 1]);
521 SUDPTRL
= LO8(en_string_descriptors
[descriptor_index
- 1]);
527 /* Unsupported descriptor type */
534 * Handle SET_INTERFACE request.
536 void usb_handle_set_interface(void)
538 /* Reset Data Toggle */
539 usb_reset_data_toggle(USB_DIR_IN
| 4);
540 usb_reset_data_toggle(USB_DIR_OUT
| 2);
542 /* Unstall & clear busy flag of all valid IN endpoints */
545 /* Unstall all valid OUT endpoints, reset bytecounts */
551 /* Initialize GPIF interface transfer count */
552 void set_gpif_cnt(uint32_t count
)
554 GPIFTCB3
= (uint8_t)(((uint32_t)(count
) >> 24) & 0x000000ff);
556 GPIFTCB2
= (uint8_t)(((uint32_t)(count
) >> 16) & 0x000000ff);
558 GPIFTCB1
= (uint8_t)(((uint32_t)(count
) >> 8) & 0x000000ff);
560 GPIFTCB0
= (uint8_t)((uint32_t)(count
) & 0x000000ff);
564 * Vendor commands handling:
566 #define VR_CFGOPEN 0xB0
567 #define VR_CFGCLOSE 0xB1
571 uint8_t __xdata
*eptr
;
573 uint32_t __xdata gcnt
;
574 bool usb_handle_send_bitstream(void)
576 eptr
= EP0BUF
; /* points to EP0BUF 64-byte register */
577 wcnt
= setup_data
.wlength
; /* total transfer count */
579 /* Clear EP0BUF for OUT requests */
580 if (setup_data
.bmrequesttype
& 0x80) {
581 bcnt
= ((wcnt
> 64) ? 64 : wcnt
);
582 for (ix
= 0; ix
< bcnt
; ix
++)
586 switch (setup_data
.brequest
) {
588 /* Clear bytecount / to allow new data in / to stops NAKing */
591 while (EP0CS
& EPBSY
)
592 ; /* wait to finish transferring in EP0BUF, until not busy */
593 gcnt
= ((uint32_t)(eptr
[0]) << 24) | ((uint32_t)(eptr
[1]) << 16)
594 | ((uint32_t)(eptr
[2]) << 8) | (uint32_t)(eptr
[3]);
595 /* Angie board FPGA bitstream download */
596 switch ((setup_data
.wvalue
) & 0x00C0) {
598 PIN_PROGRAM_B
= 0; /* Apply RPGM- pulse */
599 GPIFWFSELECT
= 0xF2; /* Restore Config mode waveforms select */
601 EP2FIFOCFG
= BMAUTOOUT
; /* and Automatic 8-bit GPIF OUT mode */
603 PIN_PROGRAM_B
= 1; /* Negate RPGM- pulse */
604 delay_ms(10); /* FPGA init time < 10mS */
605 set_gpif_cnt(gcnt
); /* Initialize GPIF interface transfer count */
608 GPIFTRIG
= GPIF_EP2
; /* Trigger GPIF OUT transfer on EP2 */
617 /* wait until GPIF transaction has been completed */
618 while ((GPIFTRIG
& BMGPIFDONE
) == 0) {
624 switch ((setup_data
.wvalue
) & 0x00C0) {
628 IFCONFIG
&= 0xFC; /* Exit gpif mode */
634 EP0BCL
= (uint8_t)(setup_data
.wlength
); /* Signal buffer is filled */
637 return true; /* Error: unknown VR command */
639 return false; /* no error; command handled OK */
643 * Handle the arrival of a USB Control Setup Packet.
645 void usb_handle_setup_data(void)
647 switch (setup_data
.brequest
) {
649 if (!usb_handle_get_status())
653 if (!usb_handle_clear_feature())
657 /* Reserved values */
661 if (!usb_handle_set_feature())
665 /* Handled by USB core */
668 /* Set Descriptor not supported. */
672 if (!usb_handle_get_descriptor())
675 case GET_CONFIGURATION
:
676 /* ANGIE has only one configuration, return its index */
677 EP0BUF
[0] = config_descriptor
.bconfigurationvalue
;
682 case SET_CONFIGURATION
:
683 /* ANGIE has only one configuration -> nothing to do */
686 /* ANGIE only has one interface, return its number */
687 EP0BUF
[0] = interface_descriptor00
.binterfacenumber
;
693 usb_handle_set_interface();
696 /* Isochronous endpoints not used -> nothing to do */
699 /* if not Vendor command, Stall EndPoint 0 */
700 if (usb_handle_send_bitstream())
707 * Handle the initialization of endpoints.
742 /* Standard procedure to reset FIFOs */
743 FIFORESET
= BMNAKALL
; /* NAK all transfers during the reset */
745 FIFORESET
= 0x02; /* reset EP2 FIFO */
747 FIFORESET
= 0x00; /* deactivate the NAK all */
751 EP2FIFOCFG
= BMAUTOOUT
; /* Automatic 8-bit GPIF OUT mode */
755 void i2c_recieve(void)
758 if (EP6FIFOBUF
[0] == 1) {
759 uint8_t rdwr
= EP6FIFOBUF
[0]; //read
760 uint8_t reg_adr_check
= EP6FIFOBUF
[1];
761 uint8_t count
= EP6FIFOBUF
[2]; //request data count
762 uint8_t adr
= EP6FIFOBUF
[3]; //address
763 uint8_t reg_adr
= EP6FIFOBUF
[4];
764 uint8_t address
= get_address(adr
, rdwr
); //address byte (read command)
765 uint8_t address_2
= get_address(adr
, 0); //address byte 2 (write command)
767 printf("%d\n", address
);
772 send_byte(address_2
); //write
774 uint8_t ack
= get_ack();
779 if (reg_adr_check
) { //if there is a byte reg
787 /* repeated start: */
797 for (uint8_t i
= 0; i
< count
; i
++) {
798 EP8FIFOBUF
[i
] = receive_byte();
813 EP8BCL
= count
; //EP8
819 uint8_t rdwr
= EP6FIFOBUF
[0]; //write
820 uint8_t count
= EP6FIFOBUF
[1]; //data count
821 uint8_t adr
= EP6FIFOBUF
[2]; //address
822 uint8_t address
= get_address(adr
, rdwr
); //address byte (read command)
828 send_byte(address
); //write
833 for (uint8_t i
= 0; i
< count
; i
++) {
834 send_byte(EP6FIFOBUF
[i
+ 3]);
844 EP8FIFOBUF
[0] = ack_cnt
;
857 * Interrupt initialization. Configures USB interrupts.
859 void interrupt_init(void)
861 /* Enable Interrupts */
864 /* Enable USB interrupt (EIE register) */
868 /* Enable INT 2 & 4 Autovectoring */
869 INTSETUP
|= (AV2EN
| AV4EN
);
871 /* Enable individual EP1OUT&IN & EP6&8 interrupts */
874 /* Clear individual USB interrupt IRQ */
877 /* Enable SUDAV interrupt */
880 /* Clear SUDAV interrupt */
885 * Handle the initialization of io ports.
890 PORTACFG
= 0x01; /* 0: normal ou 1: alternate function (each bit) */
891 OEA
= 0xEF; /* all OUT exept INIT_B IN */
898 OEB
= 0xEF; /* all OUT exept TDO */
909 PORTCCFG
= 0x00; /* 0: normal ou 1: alternate function (each bit) */
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)