66
77#include "tusb_edpt_handler.h"
88#include "DAP.h"
9+ #include "semphr.h"
10+
911
1012static uint8_t itf_num ;
1113static uint8_t _rhport ;
1214
13- volatile uint32_t _resp_len ;
1415
1516static uint8_t _out_ep_addr ;
1617static uint8_t _in_ep_addr ;
1718
1819static buffer_t USBRequestBuffer ;
1920static buffer_t USBResponseBuffer ;
2021
21- static uint8_t DAPRequestBuffer [DAP_PACKET_SIZE ];
22- static uint8_t DAPResponseBuffer [DAP_PACKET_SIZE ];
22+ static SemaphoreHandle_t edpt_spoon ;
2323
2424#define WR_IDX (x ) (x.wptr % DAP_PACKET_COUNT)
2525#define RD_IDX (x ) (x.rptr % DAP_PACKET_COUNT)
@@ -38,15 +38,15 @@ bool buffer_empty(buffer_t *buffer)
3838}
3939
4040void dap_edpt_init (void ) {
41-
41+ edpt_spoon = xSemaphoreCreateMutex ();
42+ xSemaphoreGive (edpt_spoon );
4243}
4344
4445bool dap_edpt_deinit (void )
4546{
46- memset (DAPRequestBuffer , 0 , sizeof (DAPRequestBuffer ));
47- memset (DAPResponseBuffer , 0 , sizeof (DAPResponseBuffer ));
48- USBRequestBuffer .wptr = USBRequestBuffer .rptr = 0 ;
49- USBResponseBuffer .wptr = USBResponseBuffer .rptr = 0 ;
47+ memset (& USBRequestBuffer , 0 , sizeof (USBRequestBuffer ));
48+ memset (& USBResponseBuffer , 0 , sizeof (USBResponseBuffer ));
49+ vSemaphoreDelete (edpt_spoon );
5050 return true;
5151}
5252
@@ -131,6 +131,8 @@ uint16_t dap_edpt_open(uint8_t __unused rhport, tusb_desc_interface_t const *itf
131131 // The IN endpoint doesn't need a transfer to initialise it, as this will be done by the main loop of dap_thread
132132 usbd_edpt_open (rhport , edpt_desc );
133133
134+ // Spawn DAP thread?
135+
134136 return drv_len ;
135137
136138}
@@ -149,29 +151,29 @@ bool dap_edpt_xfer_cb(uint8_t __unused rhport, uint8_t ep_addr, xfer_result_t re
149151 {
150152 if (xferred_bytes >= 0u && xferred_bytes <= DAP_PACKET_SIZE )
151153 {
154+ xSemaphoreTake (edpt_spoon , portMAX_DELAY );
152155 USBResponseBuffer .rptr ++ ;
153-
154156 // This checks that the buffer was not empty in DAP thread, which means the next buffer was not queued up for the in endpoint callback
155157 // So, queue up the buffer at the new read index, since we expect read to catch up to write at this point.
156158 // It is possible for the read index to be multiple spaces behind the write index (if the USB callbacks are lagging behind dap thread),
157159 // so we account for this by only setting wasEmpty to true if the next callback will empty the buffer
158160 if (!USBResponseBuffer .wasEmpty )
159161 {
160- usbd_edpt_xfer (rhport , ep_addr , RD_SLOT_PTR (USBResponseBuffer ), ( uint16_t ) _resp_len );
162+ usbd_edpt_xfer (rhport , ep_addr , RD_SLOT_PTR (USBResponseBuffer ), USBResponseBuffer . data_len [ RD_IDX ( USBResponseBuffer )] );
161163 USBResponseBuffer .wasEmpty = (USBResponseBuffer .rptr + 1 ) == USBResponseBuffer .wptr ;
162164 }
163-
165+ xSemaphoreGive ( edpt_spoon );
164166 // Wake up DAP thread after processing the callback
165- vTaskResume (dap_taskhandle );
167+ xTaskNotify (dap_taskhandle , 0 , eSetValueWithOverwrite );
166168 return true;
167169 }
168-
169170 return false;
170171
171- } else if (ep_dir == TUSB_DIR_OUT ) {
172+ } else if (ep_dir == TUSB_DIR_OUT ) {
172173
173174 if (xferred_bytes >= 0u && xferred_bytes <= DAP_PACKET_SIZE )
174175 {
176+ xSemaphoreTake (edpt_spoon , portMAX_DELAY );
175177 // Only queue the next buffer in the out callback if the buffer is not full
176178 // If full, we set the wasFull flag, which will be checked by dap thread
177179 if (!buffer_full (& USBRequestBuffer ))
@@ -183,22 +185,26 @@ bool dap_edpt_xfer_cb(uint8_t __unused rhport, uint8_t ep_addr, xfer_result_t re
183185 else {
184186 USBRequestBuffer .wasFull = true;
185187 }
186-
188+ xSemaphoreGive ( edpt_spoon );
187189 // Wake up DAP thread after processing the callback
188- vTaskResume (dap_taskhandle );
190+ xTaskNotify (dap_taskhandle , 0 , eSetValueWithOverwrite );
189191 return true;
190192 }
191-
192193 return false;
193194 }
194- else return false;
195+ return false;
195196}
196197
197198void dap_thread (void * ptr )
198199{
199200 uint32_t n ;
201+ uint32_t cmd ;
202+ uint16_t resp_len ;
200203 do
201204 {
205+ // Wait for usb CB wake
206+ xTaskNotifyWait (0 , 0xFFFFFFFFu , & cmd , 1 );
207+
202208 while (USBRequestBuffer .rptr != USBRequestBuffer .wptr )
203209 {
204210 /*
@@ -219,53 +225,45 @@ void dap_thread(void *ptr)
219225 }
220226 }
221227 // Read a single packet from the USB buffer into the DAP Request buffer
222- memcpy (DAPRequestBuffer , RD_SLOT_PTR (USBRequestBuffer ), DAP_PACKET_SIZE );
223228 probe_info ("%lu %lu DAP cmd %s len %02x\n" ,
224- USBRequestBuffer .wptr , USBRequestBuffer .rptr ,
225- dap_cmd_string [DAPRequestBuffer [0 ]], DAPRequestBuffer [1 ]);
226- USBRequestBuffer .rptr ++ ;
229+ USBRequestBuffer .wptr , USBRequestBuffer .rptr ,
230+ dap_cmd_string [RD_SLOT_PTR (USBRequestBuffer )[0 ], RD_SLOT_PTR (USBRequestBuffer )[1 ]]);
227231
228232 // 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.
233+ xSemaphoreTake (edpt_spoon , portMAX_DELAY ); // Suspend the scheduler to safely update the write index
229234 if (USBRequestBuffer .wasFull )
230235 {
231- vTaskSuspendAll (); // Suspend the scheduler to safely update the write index
232236 USBRequestBuffer .wptr ++ ;
233237 usbd_edpt_xfer (_rhport , _out_ep_addr , WR_SLOT_PTR (USBRequestBuffer ), DAP_PACKET_SIZE );
234238 USBRequestBuffer .wasFull = false;
235- xTaskResumeAll ();
236239 }
240+ xSemaphoreGive (edpt_spoon );
237241
238- _resp_len = DAP_ExecuteCommand (DAPRequestBuffer , DAPResponseBuffer ) ;
239- probe_info ( "%lu %lu DAP resp %s\n" ,
240- USBResponseBuffer . wptr , USBResponseBuffer . rptr ,
241- dap_cmd_string [ DAPResponseBuffer [ 0 ]]);
242-
242+ resp_len = DAP_ExecuteCommand (RD_SLOT_PTR ( USBRequestBuffer ), WR_SLOT_PTR ( USBResponseBuffer )) & 0xffff ;
243+ USBRequestBuffer . rptr ++ ;
244+ probe_info ( "%lu %lu DAP resp %s len %u\n" ,
245+ USBResponseBuffer . wptr , USBResponseBuffer . rptr ,
246+ dap_cmd_string [ WR_SLOT_PTR ( USBResponseBuffer )[ 0 ], resp_len );
243247
248+ USBResponseBuffer .data_len [WR_IDX (USBResponseBuffer )] = resp_len ;
244249 // Suspend the scheduler to avoid stale values/race conditions between threads
245- vTaskSuspendAll ( );
250+ xSemaphoreTake ( edpt_spoon , portMAX_DELAY );
246251
247252 if (buffer_empty (& USBResponseBuffer ))
248253 {
249- memcpy (WR_SLOT_PTR (USBResponseBuffer ), DAPResponseBuffer , (uint16_t ) _resp_len );
250254 USBResponseBuffer .wptr ++ ;
251255
252- usbd_edpt_xfer (_rhport , _in_ep_addr , RD_SLOT_PTR (USBResponseBuffer ), ( uint16_t ) _resp_len );
256+ usbd_edpt_xfer (_rhport , _in_ep_addr , RD_SLOT_PTR (USBResponseBuffer ), USBResponseBuffer . data_len [ RD_IDX ( USBResponseBuffer )] );
253257 } else {
254258
255- memcpy (WR_SLOT_PTR (USBResponseBuffer ), DAPResponseBuffer , (uint16_t ) _resp_len );
256259 USBResponseBuffer .wptr ++ ;
257260
258261 // The In callback needs to check this flag to know when to queue up the next buffer.
259262 USBResponseBuffer .wasEmpty = false;
260263 }
261- xTaskResumeAll ( );
264+ xSemaphoreGive ( edpt_spoon );
262265 }
263-
264- // Suspend DAP thread until it is awoken by a USB thread callback
265- vTaskSuspend (dap_taskhandle );
266-
267266 } while (1 );
268-
269267}
270268
271269usbd_class_driver_t const _dap_edpt_driver =
0 commit comments