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

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

[复制链接]
radio2radio 发布时间:2018-5-31 15:47
阅读主题, 点击返回1楼
1 收藏 45 评论418 发布时间:2018-5-31 15:47
418个回答
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驱动的大佬可以尝试一下
半-- 回答时间:2024-6-28 11:27:16

有人将这个工程移植到stm32f4上吗,我在网上找了一个f4的dap工程,但是编译下载后无法使用。

所属标签

相似分享

官网相关资源

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