XCORE SDK
XCORE Software Development Kit
xud_xfer_data.h
1 // Copyright 2021 XMOS LIMITED.
2 // This Software is subject to the terms of the XMOS Public Licence: Version 1.
3 
4 #ifndef XUD_XFER_DATA_H_
5 #define XUD_XFER_DATA_H_
6 
7 #include <xcore/chanend.h>
8 #include <xcore/assert.h>
9 #include <xud.h>
10 
11 #define XUD_DEV_XS3 1
12 
13 static inline XUD_Result_t xud_data_get_start(XUD_ep ep, uint8_t *buffer)
14 {
15  int chan_array_ptr;
16  unsigned int *ep_struct = (unsigned int *) ep;
17 
18  /* Firstly check if we have missed a USB reset - endpoint should not receive after a reset */
19  if (ep_struct[9]) {
20  return XUD_RES_RST;
21  }
22 
23  asm ("ldw %0, %1[0]":"=r"(chan_array_ptr):"r"(ep));
24  asm ("stw %0, %1[3]"::"r"(buffer),"r"(ep));
25  asm ("stw %0, %1[0]"::"r"(ep),"r"(chan_array_ptr));
26 
27  return XUD_RES_OKAY;
28 }
29 
30 static inline XUD_Result_t xud_data_get_check(chanend_t c, unsigned *length, int *is_setup)
31 {
32  int32_t word_len;
33  int8_t tail_bitlen;
34  int32_t byte_len;
35 
36  /* Test if there is a RESET */
37  if (chanend_test_control_token_next_byte(c)) {
38  *length = 0;
39  *is_setup = 0;
40  return XUD_RES_RST;
41  }
42 
43  /* First word on channel is packet word length */
44  word_len = chanend_in_word(c);
45 
46  /* Test if this is a SETUP packet */
47  if (chanend_test_control_token_next_byte(c)) {
48  *is_setup = 1;
49  tail_bitlen = chanend_in_control_token(c);
50  } else {
51  *is_setup = 0;
52  tail_bitlen = chanend_in_byte(c);
53 
54  /*
55  * Data packets have a 16 bit CRC. Subtract this from
56  * the length.
57  */
58  tail_bitlen -= 16;
59  }
60 
61  byte_len = (4 * word_len) + (tail_bitlen / 8);
62 
63  if (byte_len >= 0) {
64  *length = byte_len;
65  return XUD_RES_OKAY;
66  } else {
67  *length = 0;
68  return XUD_RES_ERR;
69  }
70 }
71 
72 XUD_Result_t xud_data_get_finish(XUD_ep ep);
73 XUD_Result_t xud_setup_data_get_finish(XUD_ep ep);
74 
75 static inline XUD_Result_t xud_data_set_start(XUD_ep ep, uint8_t *buffer, int len)
76 {
77  int chan_array_ptr;
78  int tmp, tmp2;
79  int wordLength;
80  int tailLength;
81  unsigned int *ep_struct = (unsigned int *) ep;
82 
83  /* Firstly check if we have missed a USB reset - endpoint may not want to send out old data after a reset */
84  if (ep_struct[9]) {
85  return XUD_RES_RST;
86  }
87 
88 #if XUD_DEV_XS3
89  /* Tail length is in bits */
90  tailLength = (8 * len) & 0x1F;
91 #endif
92 
93  wordLength = len / sizeof(uint32_t);
94 
95 #if XUD_DEV_XS3
96  /* Tail length must not be 0 */
97  if ((tailLength == 0) && (wordLength != 0)) {
98  wordLength--;
99  tailLength = 32;
100  }
101 #else
102  wordLength *= sizeof(uint32_t);
103  tailLength = (32 * len) & 0x7F;
104  asm ("ldw %0, %1[0]":"=r"(chan_array_ptr):"r"(ep));
105 #endif
106 
107 #if XUD_DEV_XS3
108  /* Get end off buffer address */
109  asm ("add %0, %1, %2":"=r"(tmp):"r"(buffer),"r"(wordLength << 2));
110 
111  /* Produce negative offset from end of buffer */
112  asm ("neg %0, %1":"=r"(tmp2):"r"(wordLength));
113 #else
114  /* Get end off buffer address */
115  asm ("add %0, %1, %2":"=r"(tmp):"r"(buffer),"r"(wordLength));
116 
117  /* Produce negative offset from end of buffer */
118  asm ("neg %0, %1":"=r"(tmp2):"r"(len>>2));
119 #endif
120 
121  /* Store neg index */
122  asm ("stw %0, %1[6]"::"r"(tmp2),"r"(ep));
123 
124  /* Store buffer pointer */
125  asm ("stw %0, %1[3]"::"r"(tmp),"r"(ep));
126 
127  /* Store tail len */
128  asm ("stw %0, %1[7]"::"r"(tailLength),"r"(ep));
129 
130  /* Finally, mark ready */
131 #if XUD_DEV_XS3
132  asm ("ldw %0, %1[0]":"=r"(chan_array_ptr):"r"(ep));
133 #endif
134  asm ("stw %0, %1[0]"::"r"(ep),"r"(chan_array_ptr));
135 
136  return XUD_RES_OKAY;
137 }
138 
139 XUD_Result_t xud_data_set_finish(chanend_t c, XUD_ep ep);
140 
141 #endif /* XUD_XFER_DATA_H_ */