Skip to content

Commit 1267a8c

Browse files
committed
DAP: fix atomic command support
Two bugs - ignoring DAP_QueueCommand, and calling DAP_ProcessCommand instead of DAP_Executecommand
1 parent bdb1bf2 commit 1267a8c

File tree

1 file changed

+67
-11
lines changed

1 file changed

+67
-11
lines changed

src/tusb_edpt_handler.c

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ static uint8_t _rhport;
1212

1313
volatile uint32_t _resp_len;
1414

15-
uint8_t _out_ep_addr;
16-
uint8_t _in_ep_addr;
15+
static uint8_t _out_ep_addr;
16+
static uint8_t _in_ep_addr;
1717

18-
buffer_t USBRequestBuffer;
19-
buffer_t USBResponseBuffer;
18+
static buffer_t USBRequestBuffer;
19+
static buffer_t USBResponseBuffer;
20+
21+
static uint8_t DAPRequestBuffer[DAP_PACKET_SIZE];
22+
static uint8_t DAPResponseBuffer[DAP_PACKET_SIZE];
2023

2124
#define WR_IDX(x) (x.wptr % DAP_PACKET_COUNT)
2225
#define RD_IDX(x) (x.rptr % DAP_PACKET_COUNT)
@@ -43,8 +46,40 @@ void dap_edpt_reset(uint8_t __unused rhport)
4346
itf_num = 0;
4447
}
4548

49+
char * dap_cmd_string[] = {
50+
[ID_DAP_Info ] = "DAP_Info",
51+
[ID_DAP_HostStatus ] = "DAP_HostStatus",
52+
[ID_DAP_Connect ] = "DAP_Connect",
53+
[ID_DAP_Disconnect ] = "DAP_Disconnect",
54+
[ID_DAP_TransferConfigure ] = "DAP_TransferConfigure",
55+
[ID_DAP_Transfer ] = "DAP_Transfer",
56+
[ID_DAP_TransferBlock ] = "DAP_TransferBlock",
57+
[ID_DAP_TransferAbort ] = "DAP_TransferAbort",
58+
[ID_DAP_WriteABORT ] = "DAP_WriteABORT",
59+
[ID_DAP_Delay ] = "DAP_Delay",
60+
[ID_DAP_ResetTarget ] = "DAP_ResetTarget",
61+
[ID_DAP_SWJ_Pins ] = "DAP_SWJ_Pins",
62+
[ID_DAP_SWJ_Clock ] = "DAP_SWJ_Clock",
63+
[ID_DAP_SWJ_Sequence ] = "DAP_SWJ_Sequence",
64+
[ID_DAP_SWD_Configure ] = "DAP_SWD_Configure",
65+
[ID_DAP_SWD_Sequence ] = "DAP_SWD_Sequence",
66+
[ID_DAP_JTAG_Sequence ] = "DAP_JTAG_Sequence",
67+
[ID_DAP_JTAG_Configure ] = "DAP_JTAG_Configure",
68+
[ID_DAP_JTAG_IDCODE ] = "DAP_JTAG_IDCODE",
69+
[ID_DAP_SWO_Transport ] = "DAP_SWO_Transport",
70+
[ID_DAP_SWO_Mode ] = "DAP_SWO_Mode",
71+
[ID_DAP_SWO_Baudrate ] = "DAP_SWO_Baudrate",
72+
[ID_DAP_SWO_Control ] = "DAP_SWO_Control",
73+
[ID_DAP_SWO_Status ] = "DAP_SWO_Status",
74+
[ID_DAP_SWO_ExtendedStatus ] = "DAP_SWO_ExtendedStatus",
75+
[ID_DAP_SWO_Data ] = "DAP_SWO_Data",
76+
[ID_DAP_QueueCommands ] = "DAP_QueueCommands",
77+
[ID_DAP_ExecuteCommands ] = "DAP_ExecuteCommands",
78+
};
79+
80+
4681
uint16_t dap_edpt_open(uint8_t __unused rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
47-
{
82+
{
4883

4984
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass &&
5085
PICOPROBE_INTERFACE_SUBCLASS == itf_desc->bInterfaceSubClass &&
@@ -92,13 +127,13 @@ uint16_t dap_edpt_open(uint8_t __unused rhport, tusb_desc_interface_t const *itf
92127
}
93128

94129
bool dap_edpt_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_control_request_t const *request)
95-
{
130+
{
96131
return false;
97132
}
98133

99134
// Manage USBResponseBuffer (request) write and USBRequestBuffer (response) read indices
100135
bool dap_edpt_xfer_cb(uint8_t __unused rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
101-
{
136+
{
102137
const uint8_t ep_dir = tu_edpt_dir(ep_addr);
103138

104139
if(ep_dir == TUSB_DIR_IN)
@@ -152,15 +187,33 @@ bool dap_edpt_xfer_cb(uint8_t __unused rhport, uint8_t ep_addr, xfer_result_t re
152187

153188
void dap_thread(void *ptr)
154189
{
155-
uint8_t DAPRequestBuffer[DAP_PACKET_SIZE];
156-
uint8_t DAPResponseBuffer[DAP_PACKET_SIZE];
157-
190+
uint32_t n;
158191
do
159192
{
160193
while(USBRequestBuffer.rptr != USBRequestBuffer.wptr)
161194
{
195+
/*
196+
* Atomic command support - buffer QueueCommands, but don't process them
197+
* until a non-QueueCommands packet is seen.
198+
*/
199+
n = USBRequestBuffer.rptr;
200+
while (USBRequestBuffer.data[n % DAP_PACKET_COUNT][0] == ID_DAP_QueueCommands) {
201+
picoprobe_info("%u %u DAP queued cmd %s len %02x\n",
202+
USBRequestBuffer.wptr, USBRequestBuffer.rptr,
203+
dap_cmd_string[USBRequestBuffer.data[n % DAP_PACKET_COUNT][0]], USBRequestBuffer.data[n % DAP_PACKET_COUNT][1]);
204+
USBRequestBuffer.data[n % DAP_PACKET_COUNT][0] = ID_DAP_ExecuteCommands;
205+
n++;
206+
while (n == USBRequestBuffer.wptr) {
207+
/* Need yield in a loop here, as IN callbacks will also wake the thread */
208+
picoprobe_info("DAP wait\n");
209+
vTaskSuspend(dap_taskhandle);
210+
}
211+
}
162212
// Read a single packet from the USB buffer into the DAP Request buffer
163213
memcpy(DAPRequestBuffer, RD_SLOT_PTR(USBRequestBuffer), DAP_PACKET_SIZE);
214+
picoprobe_info("%u %u DAP cmd %s len %02x\n",
215+
USBRequestBuffer.wptr, USBRequestBuffer.rptr,
216+
dap_cmd_string[DAPRequestBuffer[0]], DAPRequestBuffer[1]);
164217
USBRequestBuffer.rptr++;
165218

166219
// If the buffer was full in the out callback, we need to queue up another buffer for the endpoint to consume, now that we know there is space in the buffer.
@@ -173,7 +226,10 @@ void dap_thread(void *ptr)
173226
xTaskResumeAll();
174227
}
175228

176-
_resp_len = DAP_ProcessCommand(DAPRequestBuffer, DAPResponseBuffer);
229+
_resp_len = DAP_ExecuteCommand(DAPRequestBuffer, DAPResponseBuffer);
230+
picoprobe_info("%u %u DAP resp %s\n",
231+
USBResponseBuffer.wptr, USBResponseBuffer.rptr,
232+
dap_cmd_string[DAPResponseBuffer[0]]);
177233

178234

179235
// Suspend the scheduler to avoid stale values/race conditions between threads

0 commit comments

Comments
 (0)