1+ /*
2+ Copyright (c) 2017 Jean THOMAS.
3+
4+ Permission is hereby granted, free of charge, to any person obtaining
5+ a copy of this software and associated documentation files (the "Software"),
6+ to deal in the Software without restriction, including without limitation
7+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+ and/or sell copies of the Software, and to permit persons to whom the Software
9+ is furnished to do so, subject to the following conditions:
10+ The above copyright notice and this permission notice shall be included in
11+ all copies or substantial portions of the Software.
12+
13+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
19+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+ */
21+
22+ #include <stdint.h>
23+ #include <stdbool.h>
24+ #include <string.h>
25+
26+ #include <pico/stdlib.h>
27+ #include <hardware/clocks.h>
28+ #include <hardware/gpio.h>
29+
30+ #include "jtag.pio.h"
31+ #include "tusb.h"
32+ #include "pio_jtag.h"
33+ #include "cmd.h"
34+
35+
36+ enum CommandIdentifier {
37+ CMD_STOP = 0x00 ,
38+ CMD_INFO = 0x01 ,
39+ CMD_FREQ = 0x02 ,
40+ CMD_XFER = 0x03 ,
41+ CMD_SETSIG = 0x04 ,
42+ CMD_GETSIG = 0x05 ,
43+ CMD_CLK = 0x06 ,
44+ CMD_SETVOLTAGE = 0x07 ,
45+ CMD_GOTOBOOTLOADER = 0x08
46+ };
47+
48+ enum CommandModifier {
49+ NO_READ = 0x80 ,
50+ EXTEND_LENGTH = 0x40
51+ };
52+
53+ enum SignalIdentifier {
54+ SIG_TCK = 1 << 1 ,
55+ SIG_TDI = 1 << 2 ,
56+ SIG_TDO = 1 << 3 ,
57+ SIG_TMS = 1 << 4 ,
58+ SIG_TRST = 1 << 5 ,
59+ SIG_SRST = 1 << 6
60+ };
61+
62+ /**
63+ * @brief Handle CMD_INFO command
64+ *
65+ * CMD_INFO returns a string to the host software. This
66+ * could be used to check DirtyJTAG firmware version
67+ * or supported commands. As of now it is implemented
68+ * but not usefull.
69+ *
70+ * @param usbd_dev USB device
71+ */
72+ static void cmd_info ();
73+
74+ /**
75+ * @brief Handle CMD_FREQ command
76+ *
77+ * CMD_FREQ sets the clock frequency on the probe.
78+ * Currently this does not changes anything.
79+ *
80+ * @param commands Command data
81+ */
82+ static void cmd_freq (pio_jtag_inst_t * jtag , const uint8_t * commands );
83+
84+ /**
85+ * @brief Handle CMD_XFER command
86+ *
87+ * CMD_XFER reads and writes data simultaneously.
88+ *
89+ * @param usbd_dev USB device
90+ * @param commands Command data
91+ */
92+ static void cmd_xfer (pio_jtag_inst_t * jtag , const uint8_t * commands , bool extend_length , bool no_read , uint8_t * tx_buf );
93+
94+ /**
95+ * @brief Handle CMD_SETSIG command
96+ *
97+ * CMD_SETSIG set the logic state of the JTAG signals.
98+ *
99+ * @param commands Command data
100+ */
101+ static void cmd_setsig (pio_jtag_inst_t * jtag , const uint8_t * commands );
102+
103+ /**
104+ * @brief Handle CMD_GETSIG command
105+ *
106+ * CMD_GETSIG gets the current signal state.
107+ *
108+ * @param usbd_dev USB device
109+ */
110+ static void cmd_getsig (pio_jtag_inst_t * jtag );
111+
112+ /**
113+ * @brief Handle CMD_CLK command
114+ *
115+ * CMD_CLK sends clock pulses with specific TMS and TDI state.
116+ *
117+ * @param commands Command data
118+ */
119+ static void cmd_clk (pio_jtag_inst_t * jtag , const uint8_t * commands );
120+ /**
121+ * @brief Handle CMD_SETVOLTAGE command
122+ *
123+ * CMD_SETVOLTAGE sets the I/O voltage for devices that support this feature.
124+ *
125+ * @param commands Command data
126+ */
127+ static void cmd_setvoltage (const uint8_t * commands );
128+
129+ /**
130+ * @brief Handle CMD_GOTOBOOTLOADER command
131+ *
132+ * CMD_GOTOBOOTLOADER resets the MCU and enters its bootloader (if installed)
133+ */
134+ static void cmd_gotobootloader (void );
135+
136+ uint8_t cmd_handle (pio_jtag_inst_t * jtag , uint8_t * rxbuf , uint32_t count , uint8_t * tx_buf ) {
137+ uint8_t * commands = (uint8_t * )rxbuf ;
138+
139+ while (* commands != CMD_STOP ) {
140+ switch ((* commands )& 0x0F ) {
141+ case CMD_INFO :
142+ cmd_info ();
143+ break ;
144+
145+ case CMD_FREQ :
146+ cmd_freq (jtag , commands );
147+ commands += 2 ;
148+ break ;
149+
150+ case CMD_XFER :
151+ case CMD_XFER |NO_READ :
152+ case CMD_XFER |EXTEND_LENGTH :
153+ case CMD_XFER |NO_READ |EXTEND_LENGTH :
154+ cmd_xfer (jtag , commands , * commands & EXTEND_LENGTH , * commands & NO_READ , tx_buf );
155+ return !!(* commands & NO_READ );
156+ break ;
157+
158+ case CMD_SETSIG :
159+ cmd_setsig (jtag , commands );
160+ commands += 2 ;
161+ break ;
162+
163+ case CMD_GETSIG :
164+ cmd_getsig (jtag );
165+ return 0 ;
166+ break ;
167+
168+ case CMD_CLK :
169+ cmd_clk (jtag , commands );
170+ commands += 2 ;
171+ break ;
172+
173+ case CMD_SETVOLTAGE :
174+ cmd_setvoltage (commands );
175+ commands += 1 ;
176+ break ;
177+
178+ case CMD_GOTOBOOTLOADER :
179+ cmd_gotobootloader ();
180+ break ;
181+
182+ default :
183+ return 1 ; /* Unsupported command, halt */
184+ break ;
185+ }
186+
187+ commands ++ ;
188+ }
189+
190+ return 1 ;
191+ }
192+
193+ static void cmd_info () {
194+ char info_string [10 ] = "DJTAG2\n" ;
195+
196+ tud_vendor_write ((uint8_t * )info_string , 10 );
197+ }
198+
199+ static void cmd_freq (pio_jtag_inst_t * jtag , const uint8_t * commands ) {
200+ jtag_set_clk_freq (jtag , (commands [1 ] << 8 ) | commands [2 ]);
201+ }
202+
203+ //static uint8_t output_buffer[64];
204+
205+ static void cmd_xfer (pio_jtag_inst_t * jtag , const uint8_t * commands , bool extend_length , bool no_read , uint8_t * tx_buf ) {
206+ uint16_t transferred_bits ;
207+ uint8_t * output_buffer = 0 ;
208+
209+ /* Fill the output buffer with zeroes */
210+ if (!no_read ) {
211+ output_buffer = tx_buf ;
212+ memset (output_buffer , 0 , 64 );
213+ }
214+
215+ /* This is the number of transfered bits in one transfer command */
216+ transferred_bits = commands [1 ];
217+ if (extend_length ) {
218+ transferred_bits += 256 ;
219+ // Ensure we don't do over-read
220+ if (transferred_bits > 62 * 8 ) {
221+ return ;
222+ }
223+ }
224+ jtag_transfer (jtag , transferred_bits , commands + 2 , output_buffer );
225+
226+ /* Send the transfer response back to host */
227+ if (!no_read ) {
228+ tud_vendor_write (output_buffer , (transferred_bits + 7 )/8 );
229+ }
230+ }
231+
232+
233+
234+ static void cmd_setsig (pio_jtag_inst_t * jtag , const uint8_t * commands ) {
235+ uint8_t signal_mask , signal_status ;
236+
237+ signal_mask = commands [1 ];
238+ signal_status = commands [2 ];
239+
240+ if (signal_mask & SIG_TCK ) {
241+ jtag_set_clk (jtag ,signal_status & SIG_TCK );
242+ }
243+
244+ if (signal_mask & SIG_TDI ) {
245+ jtag_set_tdi (jtag , signal_status & SIG_TDI );
246+ }
247+
248+ if (signal_mask & SIG_TMS ) {
249+ jtag_set_tms (jtag , signal_status & SIG_TMS );
250+ }
251+
252+ if (signal_mask & SIG_TRST ) {
253+ jtag_set_trst (jtag , signal_status & SIG_TRST );
254+ }
255+
256+ if (signal_mask & SIG_SRST ) {
257+ jtag_set_rst (jtag , signal_status & SIG_SRST );
258+ }
259+ }
260+
261+ static void cmd_getsig (pio_jtag_inst_t * jtag ) {
262+ uint8_t signal_status = 0 ;
263+
264+ if (jtag_get_tdo (jtag )) {
265+ signal_status |= SIG_TDO ;
266+ }
267+ tud_vendor_write (& signal_status , 1 );
268+ }
269+
270+ static void cmd_clk (pio_jtag_inst_t * jtag , const uint8_t * commands ) {
271+ uint8_t signals , clk_pulses ;
272+
273+ signals = commands [1 ];
274+ clk_pulses = commands [2 ];
275+
276+ jtag_strobe (jtag , clk_pulses , signals & SIG_TMS , signals & SIG_TDI );
277+ }
278+
279+ static void cmd_setvoltage (const uint8_t * commands ) {
280+ (void )commands ;
281+ }
282+
283+ static void cmd_gotobootloader (void ) {
284+
285+ }
0 commit comments