你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【源代码】STM32F103C8T6最小板搞定CMSIS-DAP和SWO功能  

[复制链接]
radio2radio 发布时间:2018-5-31 15:47
阅读主题, 点击返回1楼
1 收藏 45 评论418 发布时间:2018-5-31 15:47
418个回答
radio2radio 回答时间:2020-11-23 10:44:07
wth_arm 发表于 2020-11-23 10:00
再请教一下楼主,我编译时永远都是BLUEPILL,想改成STLINK_V20,#define  STLINK_V20  1,这样定义没成功, ...

更换不同的板子,在这个下拉菜单里选择:
Boards.jpg

wth_arm 回答时间:2020-11-23 10:51:57
radio2radio 发表于 2020-11-23 10:44
更换不同的板子,在这个下拉菜单里选择:

OK了,终于搞定,感谢!!!
ljlt 回答时间:2020-12-7 10:03:45
太好了,感谢分享。
ljlt 回答时间:2020-12-7 10:04:09
感谢分享,不错。
冬天ア之釜 回答时间:2021-1-8 14:10:55
看起来真的很不错
huawuqiu 回答时间:2021-1-11 17:04:57
感谢LZ分享~~~
ricklou 回答时间:2021-1-25 10:50:25
除了mdk和iar能自动复位,其软件他都不行(iar for 8051、keil uv4、keil c166、jltool3、nfc tool、arduino ide),stm32好像有联络信号pa0和pa1,希望做一个,让复位时给一个低电平复位信号。
ricklou 回答时间:2021-1-25 10:59:32
网上搜了一下,2011年就有人讨论流控信号的问题了,现在还没有解决
radio2radio 回答时间:2021-1-25 11:31:13
ricklou 发表于 2021-1-25 10:50
除了mdk和iar能自动复位,其软件他都不行(iar for 8051、keil uv4、keil c166、jltool3、nfc tool、arduin ...

我这个是有复位信号输出线nRESET的,不过IDE要懂得向DAP发出复位命令。

软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
ricklou 回答时间:2021-1-27 23:00:25
可以把nreset映射为dtr或rts吗,很多软件走的是com协议,或者告诉我如何触发复位信号
radio2radio 回答时间:2021-1-28 18:01:27
ricklou 发表于 2021-1-27 23:00
可以把nreset映射为dtr或rts吗,很多软件走的是com协议,或者告诉我如何触发复位信号 ...

nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。

你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。


abcd44 回答时间:2021-7-18 22:32:37
楼主好!一年前路过此帖现如今又回来路过了,最近痴迷于无线下载,不知楼主在此方面有没有研究或者相关的建议呢?
AYANAMI_S 回答时间:2021-9-23 13:39:40
楼主 为什么我烧录您build文件夹下的hex( F103-DAP-SWO-CDC-BLUEPILL-SWD_PB8PB9.hex) 将核心板与电脑连接会显示未知usb设备呢  keil也识别不出cmsis dap
起点VS 回答时间:2022-8-12 09:23:24
正需要,这是好东西
KEVIN.Z 回答时间:2023-9-7 22:41:22
我也自己用ST官方标准库STM32_USB-FS-Device_Lib_V4.1.0移植了DAP V2.11版本的,即CMSIS 5.9.0里带的DAP,芯片型号用的STM32F103C8T6核心小板子,实际上我还有一块板子装上了APM32F103CBT6的,程序能通用,没跑RTX系统,轮询执行
/**
  ******************************************************************************
  * @file    usb_endp.c
  * @author  MCD Application Team
  * @version V4.1.0
  * @date    26-May-2017
  * @brief   Endpoint routines
  ******************************************************************************
  * @attention
  *
  * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"
#include "usb_lib.h"
#include "usb_istr.h"
#include "stepper.h"
#include "string.h"

#include "DAP_config.h"
#include "DAP.h"


/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static volatile uint16_t USB_RequestIndexI;     // Request  Index In
static volatile uint16_t USB_RequestIndexO;     // Request  Index Out
static volatile uint16_t USB_RequestCountI;     // Request  Count In
static volatile uint16_t USB_RequestCountO;     // Request  Count Out
static volatile uint8_t  USB_RequestIdle;       // Request  Idle  Flag

static volatile uint16_t USB_ResponseIndexI;    // Response Index In
static volatile uint16_t USB_ResponseIndexO;    // Response Index Out
static volatile uint16_t USB_ResponseCountI;    // Response Count In
static volatile uint16_t USB_ResponseCountO;    // Response Count Out
static volatile uint8_t  USB_ResponseIdle;      // Response Idle  Flag
static volatile uint32_t USB_EventFlags;

static uint8_t  USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO")));  // Request  Buffer
static uint8_t  USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO")));  // Response Buffer
static uint16_t USB_RespSize[DAP_PACKET_COUNT];

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name  : EP1_OUT_Callback.
* Description    : EP1 OUT Callback Routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void EP1_OUT_Callback(void)
{
        uint16_t n;

        n = GetEPRxCount(ENDP1);
        PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);
        if(n !=0){
                if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {
                        DAP_TransferAbort = 1U;
                } else {
                        USB_RequestIndexI++;
      if (USB_RequestIndexI == DAP_PACKET_COUNT) {
                                USB_RequestIndexI = 0U;
      }
      USB_RequestCountI++;
        USB_EventFlags = 0x01;
    }
        }        
        // Start reception of next request packet
        if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
                SetEPRxStatus(ENDP1, EP_RX_VALID);
        } else {
                USB_RequestIdle = 1U;
        }                        
}

/*******************************************************************************
* Function Name  : EP2_OUT_Callback.
* Description    : EP2 OUT Callback Routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
static volatile uint32_t TX_n;
static uint8_t *pbuf;
void EP2_IN_Callback(void)
{
        uint32_t a;
        if(TX_n>0){
                pbuf+=64;
                if(TX_n>64){
                        a=64;
                        TX_n-=64;
                        
                }else{
                        a=TX_n;
                        TX_n=0;
                }
               
        UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);
        SetEPTxCount(ENDP2,a);
               
        SetEPTxValid(ENDP2);
        }else{
                #if (SWO_STREAM != 0)
                SWO_TransferComplete();
                #endif
        }
}

/*******************************************************************************
* Function Name  : EP1_IN_Callback.
* Description    : EP1 IN Callback Routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void EP1_IN_Callback(void)
{
    if (USB_ResponseCountI != USB_ResponseCountO) {
      // Load data from response buffer to be sent back
                        UserToPMABufferCopy(USB_Response[USB_ResponseIndexO],ENDP1_TXADDR,USB_RespSize[USB_ResponseIndexO]);
                        SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);
                        SetEPTxValid(ENDP1);                        
      USB_ResponseIndexO++;
      if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
        USB_ResponseIndexO = 0U;
      }
      USB_ResponseCountO++;
    } else {
      USB_ResponseIdle = 1U;
    }  
}

// Called during USBD_Initialize to initialize the USB HID class instance.
void DAP_FIFO_Init(void)
{
    // Initialize variables
    USB_RequestIndexI  = 0U;
    USB_RequestIndexO  = 0U;
    USB_RequestCountI  = 0U;
    USB_RequestCountO  = 0U;
    USB_ResponseIndexI = 0U;
    USB_ResponseIndexO = 0U;
    USB_ResponseCountI = 0U;
    USB_ResponseCountO = 0U;
    USB_ResponseIdle   = 1U;
    USB_EventFlags     = 0U;
}

uint8_t DAP_Thread (void) {
  uint32_t flags;
  uint32_t n;

  //for (;;) {
  //  osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);
                if((USB_EventFlags & 0x81) == 0)
                {
                        return 0;
                }
                USB_EventFlags &= (~0X81);
               
                                       
    // Process pending requests
    while (USB_RequestCountI != USB_RequestCountO) {
                //if (USB_RequestCountI != USB_RequestCountO) {
      // Handle Queue Commands
      n = USB_RequestIndexO;
      while (USB_Request[n][0] == ID_DAP_QueueCommands) {
                                //if (USB_Request[n][0] == ID_DAP_QueueCommands) {
        USB_Request[n][0] = ID_DAP_ExecuteCommands;
        n++;
        if (n == DAP_PACKET_COUNT) {
          n = 0U;
        }
        if (n == USB_RequestIndexI) {
          flags = USB_EventFlags;
          if (flags & 0x80U) {
            break;
          }
        }
      }

      // Execute DAP Command (process request and prepare response)
      USB_RespSize[USB_ResponseIndexI] =
        (uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);

      // Update Request Index and Count
      USB_RequestIndexO++;
      if (USB_RequestIndexO == DAP_PACKET_COUNT) {
        USB_RequestIndexO = 0U;
      }
      USB_RequestCountO++;

      if (USB_RequestIdle) {
        if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
          USB_RequestIdle = 0U;
          SetEPRxStatus(ENDP1, EP_RX_VALID);
        }
      }

      // Update Response Index and Count
      USB_ResponseIndexI++;
      if (USB_ResponseIndexI == DAP_PACKET_COUNT) {
        USB_ResponseIndexI = 0U;
      }
      USB_ResponseCountI++;

      if (USB_ResponseIdle) {
        if (USB_ResponseCountI != USB_ResponseCountO) {
          // Load data from response buffer to be sent back
          n = USB_ResponseIndexO++;
          if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
            USB_ResponseIndexO = 0U;
          }
          USB_ResponseCountO++;
          USB_ResponseIdle = 0U;
          //USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);
                                        UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);
                                        SetEPTxCount(ENDP1,USB_RespSize[n]);
                                        SetEPTxValid(ENDP1);
        }
      }
    }
        return 0;
}

// SWO Data Queue Transfer
//   buf:    pointer to buffer with data
//   num:    number of bytes to transfer
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {
  //USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);
        uint32_t a;
        
        if(num>64)
        {
                a=64;
                TX_n=num-64;
                pbuf=buf;

        }else {
                a=num;
                TX_n=0;
        }
        UserToPMABufferCopy(buf,ENDP2_TXADDR,a);
        SetEPTxCount(ENDP2,a);
        SetEPTxValid(ENDP2);
}

// SWO Data Abort Transfer
void SWO_AbortTransfer (void) {
  //USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));
        //SetEPTxStatus(ENDP2, EP_TX_NAK);
        SetEPTxStatus(ENDP2, EP_TX_DIS);
        SetEPTxCount(ENDP2,0);
        //TX_n=0;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

移植大概是这样的,利用STM32_USB-FS-Device_Lib_V4.1.0里面的例程Custom_HID修改为自定义USB设备,3个批量端点,OUT,IN,IN,由于批量端点不像HID哪样要使用报告描述符号,但要让WIN识别出驱动,添加了WINUSB相关的描述符号,在端点回调里实现DAP的FIFO处理,然后把DAP_Thread里面的线程调度修改为标志通过,放MAIN主循环里调用,测试SWD下载程序,调试都完全没问题,时钟设置为10M时感觉速度还是可以的,这能体现批量端点的好处
DWT部分即TIMESTAMP的时间参考,由于没使用Keil的核心库,得自己对相应的寄存器进行开启,而且3.5库的core_cm3.h里面没声明这个寄存器,只得自己定义一下了
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {
  return (DWT->CYCCNT);
}

void DWT_Init(void)
{
    /* 使能DWT外设 */
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;               

    /* DWT CYCCNT寄存器计数清0 */
    DWT->CYCCNT = (uint32_t)0u;

    /* 使能Cortex-M DWT CYCCNT寄存器 */
    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
        

然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率

然后改为使用SWO_STREAM传输方式,这种方式是单独使用另一个IN端点进行传输,即DAP的命令调用SWO_Data时只取走了SWO的状态,没取走SWO读到的数据信息,数据信息通过SWO_Thread通过另一个IN端点发送出去,SWO_Thread也是把线程调度修改为标志式让行的方式,对于50毫秒超时处理部分没弄,就这样放到MAIN里的主循环轮询调用,换了这种方式后,SWO单步调试,全速下也能打印信息了,而且全速下不会是卡住了,响应速度就与没开SWO时一样的效果,即没了被阻塞的感觉了,非常爽快,所下的断点,按一个F5马上能停止,非常快的响应速度,但有时候Keil底部状态条会提示Trace:dataOVERFLOW,查了一下这提示说是SWO端口读取太多的数据,导致被截断,具体也弄不明白哪里问题,另外手上使用的自制JLINK V9,开启SWO时,SWO时钟是6.XMHZ时钟频率的,而且连接上芯片后,打印信息啥的都正常的,而且不会有报错等待问题,在想这会不会JLINK的SWO接口是使用SPI做的,毕竟串口这个时钟频率能正常工作吗?DAP里的SWO能否改为SPI接收,因为不使用SWO_STREAM传输时会被阻塞住,很大原因是串口时钟频率太慢了,这估计得研究一个SWO的接收协议才行,个人来说SWO方式还是比较实用的,有人会说会占用一根IO,但要说使用串口进行调试不也是占了一个串口,但又会有人说JLINK的RTT不香么?
声明这个变量static volatile uint32_t SWO_EventFlags=0;
在SWO里每一处调用osThreadFlagsSet的地方都改为如:
//osThreadFlagsSet(SWO_ThreadId, 1U);
SWO_EventFlags = 1U;


// SWO Thread
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
  //uint32_t timeout;
  uint32_t flags;
  uint32_t count;
  uint32_t index;
  uint32_t i, n;
  //(void)   argument;

  //timeout = osWaitForever;

  //for (;;) {
    //flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
                if((SWO_EventFlags & 0x01)==0)return 0;
         
                flags = SWO_EventFlags;
                SWO_EventFlags = 0U;
    if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
      //timeout = SWO_STREAM_TIMEOUT; 这里是对于进入了SWO_CAPTURE_ACTIVE状态时就把线程超时设置为50毫秒,大概意思应该是osThreadFlagsWait到达这个超时时间后,不管标志是否切换为1U,都放行SWO_Thread调用一次,timeout = osWaitForever时相当于无限长的超时等待1U标志,对RTX不熟悉,不知道是不是这样子
                        ;
    } else {
      //timeout = osWaitForever;
      flags   = osFlagsErrorTimeout;
    }
    if (TransferBusy == 0U) {
      count = GetTraceCount();
      if (count != 0U) {
        index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
        n = SWO_BUFFER_SIZE - index;
        if (count > n) {
          count = n;
                                       
        }
                                if(count>USB_BLOCK_SIZE)
                                        count=USB_BLOCK_SIZE;
        if (flags != osFlagsErrorTimeout) {
          i = index & (USB_BLOCK_SIZE - 1U);
          if (i == 0U) {
            count &= ~(USB_BLOCK_SIZE - 1U);
          } else {
            n = USB_BLOCK_SIZE - i;
            if (count >= n) {
              count = n;
            } else {
              count = 0U;
            }
          }
        }
        if (count != 0U) {
          TransferSize = count;
          TransferBusy = 1U;
          SWO_QueueTransfer(&TraceBuf[index], count);
        }
      }
    }
  //}
                return 0;
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever         0xFFFFFFFFU ///< Wait forever timeout value.
#define osFlagsErrorTimeout   0xFFFFFFFEU ///< osErrorTimeout (-2).
static volatile uint32_t SWO_EventFlags=0;
static volatile uint32_t timeout=osWaitForever;
static volatile uint32_t timeWait;
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
  //uint32_t timeout;
  uint32_t flags;
  uint32_t count;
  uint32_t index;
  uint32_t i, n;
  //(void)   argument;

  //timeout = osWaitForever;

  //for (;;) {
    //flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
                if((SWO_EventFlags & 0x01)==0)
                {
                        if((timeWait-=DWT->CYCCNT)/72000 < timeout)  //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了
                        return 0;
                        
                }
         
                flags = SWO_EventFlags;
                SWO_EventFlags = 0U;
    if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
      timeout = SWO_STREAM_TIMEOUT;
      timeWait=DWT->CYCCNT;
    } else {
      timeout = osWaitForever;
      flags   = osFlagsErrorTimeout;
    }
    if (TransferBusy == 0U) {
      count = GetTraceCount();
      if (count != 0U) {
        index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
        n = SWO_BUFFER_SIZE - index;
        if (count > n) {
          count = n;
                                       
        }
                                if(count>USB_BLOCK_SIZE)
                                        count=USB_BLOCK_SIZE;
        if (flags != osFlagsErrorTimeout) {
          i = index & (USB_BLOCK_SIZE - 1U);
          if (i == 0U) {
            count &= ~(USB_BLOCK_SIZE - 1U);
          } else {
            n = USB_BLOCK_SIZE - i;
            if (count >= n) {
              count = n;
            } else {
              count = 0U;
            }
          }
        }
        if (count != 0U) {
          TransferSize = count;
          TransferBusy = 1U;
          SWO_QueueTransfer(&TraceBuf[index], count);
        }
      }
    }
  //}
                return 0;
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了

CDC部分暂时还没加入,SWD现在是非常稳定的,而且速度感觉也是不差,就是SWO的问题不知道如何弄,另外看到其它人弄DAP,把SWD读写部分改为SPI,看了一些SWD读写协议,它好像有一个8位一组和32位一组的部分,如果换为SPI是不是就可以更快的速度读写了,另外DAP与USB之间的FIFO部分它有一个队列等待,看意思就是当有标志着队列的包时,就等待接收更多的包缓存后再执行处理,对于批量端点,连续的传输大量数据确实是批量端点的长处,因为批量数据时,端点接收完一包后不会NAK,端点会接着接收下一包,少了一些中间商的处理,也尝试过这个队列等待修改为不等待,即接收一个包,执行一次DAP处理,它同样是能正常运行的,对于批量传输来来说,感觉应该队列等待会提高USB传输的速度,比如下载程序时,Keil 一次性下发多个命令包,比如达到1K或者2K字节或者更多,DAP先全部利用批量端点的优势一次性接收下来缓存,然后DAP才执行一个个命令包的响应处理,对于读写部分构成字节为一组的就使用SPI读写数据,零散的位部分像ACK,SWD复位等待部分用IO模拟来处理,SWO部分感觉如果能修改为SPI接收估计时钟频率可以更高,这样响应速度更快,另外STM32_USB-FS-Device_Lib_V4.1.0固件库的USB端点没有FIFO,不像OTG USB FS 库哪样端点都带有FIFO,但是提供双缓存端点,准备把端点修改为双缓存的,这样当连续多包传输时,端点就不会NAK,少了这个等待时间,能增加端点的传输速率


int main(void)
{
  DWT_Init();
        DAP_Setup();
  USB_Interrupts_Config();
  Set_USBClock();
  USB_Init();
        //TIM3_Init(35999,0);
        //TIM_Cmd(TIM3,ENABLE);
        
        
  while (1)
  {
                DAP_Thread();
                #if (SWO_STREAM != 0)
                SWO_Thread();
                #endif
  }
}

对于DAP_config.h的IO配置我是这样弄的
///@}
// Debug Port I/O Pins

// SWCLK/TCK Pin                GPIOA[6]
#define SWCLK_TCK_OUT                       *( uint32_t*)0x42210198
#define SWCLK_TCK_IN                               *( uint32_t*)0x42210118

// SWDIO/TMS Pin                GPIOA[7]
#define SWDIO_TMS_OUT                              *( uint32_t*)0x4221019C
#define SWDIO_TMS_IN                               *( uint32_t*)0x4221011C

// SWDIO Output Enable Pin      GPIOA[7]
#define SWDIO_Output()         {*(uint32_t*)0x4221021C = 1; \
                                                                                                                                *(uint32_t*)0x42210070 = 1; \
                                                                                                                                *(uint32_t*)0x42210074 = 1; \
                                                                                                                                *(uint32_t*)0x42210078 = 0; \
                                                                                                                                *(uint32_t*)0x4221007C = 0;}

#define SWDIO_Input()                 {*(uint32_t*)0x4221021C = 1; \
                                                                                                                                *(uint32_t*)0x42210070 = 0; \
                                                                                                                                *(uint32_t*)0x42210074 = 0; \
                                                                                                                                *(uint32_t*)0x42210078 = 0; \
                                                                                                                                *(uint32_t*)0x4221007C = 1; }

// TDI Pin                      GPIOA[8]
#define TDI_OUT                                    *(volatile uint32_t*)0x422101A0
#define TDI_IN                                     *(volatile uint32_t*)0x42210120

// TDO Pin                      GPIOA[10]
#define TDO_OUT                                    *(volatile uint32_t*)0x422101A8
#define TDO_IN                                     *(volatile uint32_t*)0x42210128

// nTRST Pin                    GPIOB[3]
#define nTRST_OUT                                                                *(volatile uint32_t*)0x4221818C
#define nTRST_IN                                                                *(volatile uint32_t*)0x4221010C

// nRESET Pin                   GPIOB[4]
#define nRESET_OUT                                 *(volatile uint32_t*)0x42218190
#define nRESET_IN                                  *(volatile uint32_t*)0x42218110

// nRESET Output Enable Pin     GPIOB[4]
#define nRESET_Output()               {*(uint32_t*)0x42218210 = 1; \
                                                                                                                                *(uint32_t*)0x42218040 = 1; \
                                                                                                                                *(uint32_t*)0x42218044 = 1; \
                                                                                                                                *(uint32_t*)0x42218048 = 0; \
                                                                                                                                *(uint32_t*)0x4221804C = 0; }

#define nRESET_Intput()        {*(uint32_t*)0x42218210 = 1; \
                                                                                                                                *(uint32_t*)0x42218040 = 0; \
                                                                                                                                *(uint32_t*)0x42218044 = 0; \
                                                                                                                                *(uint32_t*)0x42218048 = 0;\
                                                                                                                                *(uint32_t*)0x4221804C = 1; }


// Debug Unit LEDs

// Connected LED                GPIOC[13]
#define LED_OUT                                                      *(volatile uint32_t*)0x422201B4
#define LED_IN                                                       *(volatile uint32_t*)0x42220134

#define LED_Intput()                        {*(uint32_t*)0x42220234 = 1; \
                                                                                                                                *(uint32_t*)0x422200D0 = 0; \
                                                                                                                                *(uint32_t*)0x422200D4 = 0; \
                                                                                                                                *(uint32_t*)0x422200D8 = 0; \
                                                                                                                                *(uint32_t*)0x422200DC = 1; }
// Target Running LED           Not available

// SWCLK/TCK I/O pin -------------------------------------

/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN  (void) {
  return (SWCLK_TCK_IN);
}

/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void     PIN_SWCLK_TCK_SET (void) {
  SWCLK_TCK_OUT = 1;
}

/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void     PIN_SWCLK_TCK_CLR (void) {
  SWCLK_TCK_OUT = 0;
}


// SWDIO/TMS Pin I/O --------------------------------------

/** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN  (void) {
  return (SWDIO_TMS_IN);
}

/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void     PIN_SWDIO_TMS_SET (void) {
  SWDIO_TMS_OUT = 1;
}

/** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void     PIN_SWDIO_TMS_CLR (void) {
  SWDIO_TMS_OUT = 0;
}

/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN      (void) {
  return (SWDIO_TMS_IN);
}

/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void     PIN_SWDIO_OUT     (uint32_t bit) {
  SWDIO_TMS_OUT = bit;
}

/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls.
*/
__STATIC_FORCEINLINE void     PIN_SWDIO_OUT_ENABLE  (void) {
  SWDIO_Output();
}

/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls.
*/
__STATIC_FORCEINLINE void     PIN_SWDIO_OUT_DISABLE (void) {
  SWDIO_Input();
}

楼上有的说弄无线,其实无线也就是PC<->USB<->无线模块A<->无线模块B-DAP,数据传输的速率主要是无线模块之间的速率限制了,也是非常简单的
即单片机先做好USB接口部分,OUT端点收到的数据发送到无线模块A,无线模块B接收到数据后,推给DAP处理,DAP响应的数据再让无线模块B发送回无线模块A,再通过USB发送回PC,也就是说USB与DAP之间也就多了两个无线模块作为数据的交换,要是会写USB驱动,写个虚拟WINUSB设备的驱动,让Keil的DAP驱动能识别到这个虚拟USB设备,通过ESP32利用WIFI通信应该比使用这种无线模块更快,而且ESP32主频更高,即使IO模拟 SWD接口,都会更快,会写USB驱动的大佬可以尝试一下

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版