@@ -124,6 +124,8 @@ void FTDISWDInterface::ResetInterface()
124124
125125/* *
126126 @brief Performs a SW-DP write transaction
127+
128+ TODO: optimize to 1 transaction using overrun detection?
127129 */
128130void FTDISWDInterface::WriteWord (uint8_t reg_addr, bool ap, uint32_t wdata)
129131{
@@ -163,7 +165,7 @@ void FTDISWDInterface::WriteWord(uint8_t reg_addr, bool ap, uint32_t wdata)
163165 (m_gpioDirection[1 ] << 5 ) |
164166 (m_gpioDirection[2 ] << 6 ) |
165167 (m_gpioDirection[3 ] << 7 ) |
166- 0x0B
168+ 0x0B ;
167169
168170 // Calculate the parity for the data
169171 uint32_t dpartmp = (wdata >> 16 ) | (wdata >> 8 ) | (wdata >> 4 ) | (wdata >> 2 ) | (wdata >> 1 ) | wdata;
@@ -246,16 +248,104 @@ uint32_t FTDISWDInterface::ReadWord(uint8_t reg_addr, bool ap)
246248{
247249 // Host to target: 8 bit header
248250 // LSB first: 1, AP / #DP, 1, A[2:3], Parity, 0, 1
251+ uint8_t header = 0x85 ;
252+ bool parity = true ;
253+ if (ap)
254+ {
255+ header |= 0x02 ;
256+ parity ^= 1 ;
257+ }
258+ if (reg_addr & 4 )
259+ {
260+ header |= 0x08 ;
261+ parity ^= 1 ;
262+ }
263+ if (reg_addr & 8 )
264+ {
265+ header |= 0x10 ;
266+ parity ^= 1 ;
267+ }
268+ if (parity)
269+ header |= 0x20 ;
249270
250- // 1 bit bus turnaround (tristate)
271+ // We need to switch the TDO/SWDIO pin back and forth from output to tristate a couple of times.
272+ // It's also a GPIO bitbang pin, though - so we need to reconfigure the low GPIO bank a bunch.
273+ // Bit 1 = TDI = output (1) by default
274+ unsigned char value_low =
275+ (m_gpioValue[0 ] << 4 ) |
276+ (m_gpioValue[1 ] << 5 ) |
277+ (m_gpioValue[2 ] << 6 ) |
278+ (m_gpioValue[3 ] << 7 ) |
279+ 0x08 ;
280+ unsigned char dir_low =
281+ (m_gpioDirection[0 ] << 4 ) |
282+ (m_gpioDirection[1 ] << 5 ) |
283+ (m_gpioDirection[2 ] << 6 ) |
284+ (m_gpioDirection[3 ] << 7 ) |
285+ 0x0B ;
251286
252- // 3 bit ACK from target
287+ uint8_t cmdbuf[] =
288+ {
289+ // The header
290+ header,
253291
254- // Read data from target to host: 32 bits, LSB first
292+ // Tristate TDI
293+ MPSSE_SET_DATA_LOW,
294+ value_low,
295+ dir_low ^ 0x2 , // flip TDI to an input
255296
256- // 1 bit parity
297+ // Send a 1-bit bus turnaround as tristate
298+ MPSSE_DUMMY_CLOCK_BITS,
299+ 0x00 ,
257300
301+ // Read the three-bit ACK from the target
302+ MPSSE_TXRX_BYTES,
303+ 0x02 ,
304+ 0x00 ,
305+ 0x00 // TDI is tristated so send data doesn't matter
306+ };
307+ WriteDataRaw (cmdbuf, sizeof (cmdbuf));
308+
309+ // Send everything up to the ACK then see what comes back (should be a single byte)
310+ uint8_t ack = 0 ;
311+ ReadData (&ack, 1 );
312+
313+ // WAIT request? TODO
314+ if (ack == 2 )
315+ {
316+ LogError (" TODO: Handle WAIT request from SW-DP\n " );
317+ return 0 ;
318+ }
319+
320+ // Some strange response that isn't what we expect
321+ else if (ack != 1 )
322+ {
323+ LogError (" Weird - we got something other than ACK or WAIT\n " );
324+ return 0 ;
325+ }
326+
327+ // Read data from target to host: 32 bits, LSB first
328+ // 1 bit parity
258329 // 1 bit bus turnaround (tristate)
330+ uint8_t rxd[5 ];
331+ uint8_t databuf[] =
332+ {
333+ // Read the data plus parity bits
334+ MPSSE_TXRX_BITS,
335+ 0x20 , // 33 total bits
336+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
337+
338+ // Send a bus turnaround cycle so the target can tristate the bus
339+ MPSSE_DUMMY_CLOCK_BITS,
340+ 0x00 , // 1 bit
341+
342+ // Reconfigure TDI to actually drive again
343+ MPSSE_SET_DATA_LOW,
344+ value_low,
345+ dir_low
346+ };
347+ WriteDataRaw (databuf, sizeof (databuf));
348+ ReadData (&rxd, 5 );
259349}
260350
261351#endif
0 commit comments