你的浏览器版本过低,可能导致网站不能正常访问!为了你能正常使用网站功能,请使用这些浏览器。
ricklou 发表于 2021-1-25 10:50 / \; ]. F3 }; ^5 r$ R! {除了mdk和iar能自动复位,其软件他都不行(iar for 8051、keil uv4、keil c166、jltool3、nfc tool、arduin ...
ricklou 发表于 2021-1-27 23:00& t1 O a5 b/ p6 A; I& n* F 可以把nreset映射为dtr或rts吗,很多软件走的是com协议,或者告诉我如何触发复位信号 ...
有人将这个工程移植到stm32f4上吗,我在网上找了一个f4的dap工程,但是编译下载后无法使用。
小马哥STM32F103开源小四轴RoboFly全部资料大放送
【MCU实战经验】+STM32F103的uCOSII详细移植
STM32中BOOT的作用
STM32如何分配原理图IO
STM32的I2S外设
STM32电路知识学习
基于STM32F1的CAN通信之DMA
STM32怎么选型
简单分析STM32和51的区别
简单聊聊STM32的SPI外设
我这个是有复位信号输出线nRESET的,不过IDE要懂得向DAP发出复位命令。* S5 F0 q) z+ e) Q/ _5 Y8 H
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。) W w$ I2 R- ?7 ~1 h; W$ b+ y: {
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。 E. g) ` t& P5 p' i8 I
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。 " T# y$ q1 E/ p3 a9 C
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。
7 t) B& L( i' x! G; P4 i1 \9 x
$ U5 |! V+ V$ Y& z$ s0 q* ^' K3 Y
/**
******************************************************************************- K9 x/ L c6 t$ L, W/ d
* @file usb_endp.c6 {6 o M: i O" S
* @author MCD Application Team
* @version V4.1.0
* @date 26-May-2017
* @brief Endpoint routines
******************************************************************************
* @attention# w, j. |3 H. V* h! u2 A. c
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>$ W: t7 U, ?% {3 R- c3 _2 i, O
*9 O4 |1 {, \) Q
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:3 I! P: H- N8 Y( D D
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.& L: Y, N% @5 H$ e) q7 t
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation2 o+ j' l4 c0 r1 e
* and/or other materials provided with the distribution.% G/ F8 s: I# |: K7 H2 d$ r8 \& A
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software4 Q6 h0 t# T8 l: `. [
* without specific prior written permission.7 c4 }. H6 h7 Q* N5 M" Y
*
* 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 ARE4 d" q! g/ G. X$ e4 g7 e
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL1 N, K i, c/ M6 \( \
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER) O8 m# ?& }3 S! Q& E
* 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.
*2 w/ t, F: @4 D% ?# [5 a
******************************************************************************- }" M2 [ _: C/ p5 q. A$ l; e
*/8 F3 ]0 J- G8 z [/ d d
7 g/ g6 ]( y" ~3 e/ N s
4 g* Q' c7 U4 z9 b- o+ {0 p
/* Includes ------------------------------------------------------------------*/+ z+ C b# b" u5 a* C
#include "hw_config.h"0 G; V% `* o$ C7 o/ X3 M; I
#include "usb_lib.h"
#include "usb_istr.h"
#include "stepper.h"" H9 K* w* f2 g, g/ E+ r; X$ R
#include "string.h"5 Q. U' W7 T6 z3 y
, ]7 X' U* I! j w0 ~
#include "DAP_config.h"
#include "DAP.h"
) a6 A7 J( ?( j& ~1 E6 ?4 s" Z
' m5 { q& t$ X# ]5 }8 S3 n
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/, C6 v3 N3 @1 i7 {6 V: ]
static volatile uint16_t USB_RequestIndexI; // Request Index In
static volatile uint16_t USB_RequestIndexO; // Request Index Out8 w' z5 P; V4 {
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 Out4 B* @9 H' |- D' Q
static volatile uint16_t USB_ResponseCountI; // Response Count In, @. B3 [8 H; \, ^
static volatile uint16_t USB_ResponseCountO; // Response Count Out
static volatile uint8_t USB_ResponseIdle; // Response Idle Flag
static volatile uint32_t USB_EventFlags;
- S" {( m* B( V0 g$ c# v
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]; q: g& e9 R$ [
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : EP1_OUT_Callback. _5 g q+ e1 o t
* Description : EP1 OUT Callback Routine.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/. ]* h' T( D+ }' y; i
void EP1_OUT_Callback(void)
{
uint16_t n;9 E, x# _ H$ V" f6 }
n = GetEPRxCount(ENDP1);; }' n7 L" Q" R9 ~! Z# S; ?
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);! |5 w$ z: [6 |& b" m! U
if(n !=0){ q7 r, C3 J' T! F! J. W) w
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {
DAP_TransferAbort = 1U;
} else {9 A3 g! q9 ^6 ^- Z6 ~8 U1 c) U- S
USB_RequestIndexI++;
if (USB_RequestIndexI == DAP_PACKET_COUNT) {0 g4 \& j" _/ l5 c/ P$ r
USB_RequestIndexI = 0U;
}
USB_RequestCountI++;: o7 Y- ]* Q+ |, X( o- @
USB_EventFlags = 0x01;
}6 s. W$ K. n+ C1 d2 ~
}
// Start reception of next request packet# U% n& Z: l9 r: u5 A7 ~
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
SetEPRxStatus(ENDP1, EP_RX_VALID);
} else {
USB_RequestIdle = 1U;
} - N5 l3 ]2 U B; h+ d
}
; F, W, x d4 q# l: K
/*******************************************************************************4 Q2 q' U$ H) q' |8 m0 V S
* Function Name : EP2_OUT_Callback.8 i' i2 ^7 z7 V. v4 U
* Description : EP2 OUT Callback Routine.
* Input : None.) S( J5 Q+ A9 ~4 C
* Output : None.
* Return : None.
*******************************************************************************/
static volatile uint32_t TX_n;0 J6 b2 X- i7 C( e" I& x7 {/ O
static uint8_t *pbuf;
void EP2_IN_Callback(void)
{
uint32_t a; s# X8 W8 H4 t, ~0 T9 m* N
if(TX_n>0){
pbuf+=64;
if(TX_n>64){6 I$ _% H" c' i
a=64;# y" H m# U! B
TX_n-=64;$ q& E; j0 v: c# _' @
$ c5 a4 F0 E! |6 a6 ]4 _
}else{5 f# }! m& ~' k( T- `( M! T+ o& y& H# m
a=TX_n;/ f( J: b* A9 n3 {' f
TX_n=0;
}
( F" i1 d5 u2 }% b: ^
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);* H8 X6 \3 c, R7 p( `4 p
SetEPTxCount(ENDP2,a);
' X0 V y3 j" v3 q5 T W8 m
SetEPTxValid(ENDP2);
}else{
#if (SWO_STREAM != 0)
SWO_TransferComplete();6 o5 C+ t( m- s
#endif
}3 W' k! W4 T- A7 D# Y" r
}8 }, F$ j1 Q" H9 l+ Q! O5 h2 p
, {. g* |, u1 g# {* k* k B) X
/*******************************************************************************
* Function Name : EP1_IN_Callback.5 v, g1 r8 d! t5 G; S
* Description : EP1 IN Callback Routine.
* Input : None.. Z `# O. z* S0 _% F: m" x
* Output : None.
* Return : None.
*******************************************************************************/6 S8 b% b, f( z, W+ W
void EP1_IN_Callback(void)7 S. {; n8 j4 w, c+ f% {" o: v
{
if (USB_ResponseCountI != USB_ResponseCountO) {; U" d" ^6 ?8 G; s
// 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]);- `$ g( r6 t+ ~
SetEPTxValid(ENDP1);
USB_ResponseIndexO++;2 i$ L, y# I9 u% u" l. W1 C
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {, v+ y+ N1 G' }% d
USB_ResponseIndexO = 0U;( a7 W: T9 W2 G
}$ s' S5 }# E3 h& |; B1 a
USB_ResponseCountO++;4 @& h; ?0 q: H6 p& ~$ `
} else {
USB_ResponseIdle = 1U;$ H6 I* _1 s: J* z5 J
}
}
// Called during USBD_Initialize to initialize the USB HID class instance.+ \6 l3 W4 A, j7 r& Z# M
void DAP_FIFO_Init(void)
{0 L( K) `* W& h1 s. I1 n
// Initialize variables$ l) E- T5 \& h9 e
USB_RequestIndexI = 0U;
USB_RequestIndexO = 0U;
USB_RequestCountI = 0U;) X; ? D/ l& G( i/ W
USB_RequestCountO = 0U;4 _, V1 O3 ], H" ^8 q
USB_ResponseIndexI = 0U;1 B" ^/ I4 f- M3 t% Y; y
USB_ResponseIndexO = 0U;
USB_ResponseCountI = 0U;; N8 P5 g$ y+ u5 J7 t
USB_ResponseCountO = 0U;7 ~" | a |1 z( O( a! d
USB_ResponseIdle = 1U;+ U- _2 p* S, ~
USB_EventFlags = 0U;
}
uint8_t DAP_Thread (void) {
uint32_t flags;7 F" L4 T0 k* m1 R+ q+ t
uint32_t n;0 r9 O4 C. y; m* i) c* V) {8 K
//for (;;) {
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);& y$ X6 _$ ?) D) ~; i& p, N
if((USB_EventFlags & 0x81) == 0)2 J, T3 C0 {7 \2 x# w
{5 e4 D# J# R. U' ?
return 0;
}
USB_EventFlags &= (~0X81);
~3 i3 [) A- b6 C8 T! s+ E
( }7 g/ o& ~2 b5 P. x% H# F
// Process pending requests4 H* L$ K0 t0 Q" b: S, y( d
while (USB_RequestCountI != USB_RequestCountO) {: o2 C4 A n1 d
//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;' o! b! I( `- P& e+ s% n0 u4 z+ M
if (flags & 0x80U) {
break;
}
}5 T! {( W) T8 @) L1 H- R
}
( A$ L$ z: ^* N3 P. u+ q
// Execute DAP Command (process request and prepare response)
USB_RespSize[USB_ResponseIndexI] =8 ]6 G5 T+ C! ]) P" ?
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);- X: b7 ]! ]* C* `$ N0 c
6 @$ x7 H9 O' K: u4 V2 M
// Update Request Index and Count' [# [) F0 O0 u) E! {! x& s9 ]
USB_RequestIndexO++;/ `( U1 S, L& V& d
if (USB_RequestIndexO == DAP_PACKET_COUNT) {' S' [$ E4 D& c9 K# Q8 b+ v* ?
USB_RequestIndexO = 0U;
}
USB_RequestCountO++;
if (USB_RequestIdle) {6 p& R* R h# o: ~! J9 r
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
USB_RequestIdle = 0U;
SetEPRxStatus(ENDP1, EP_RX_VALID);
}
}
+ F8 d2 _& M" d. i6 p" ^) h
// Update Response Index and Count7 e. t3 W$ c- h' M" {% ?
USB_ResponseIndexI++;
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {; a# g' }; B$ f. l+ B
USB_ResponseIndexI = 0U;; D! E% F+ d, T# a) ~
}
USB_ResponseCountI++;$ y8 [2 c# |4 u6 b2 p6 S
if (USB_ResponseIdle) {1 q% y. Y8 H6 B1 Y
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back: N8 i- g5 G8 \. M/ K
n = USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;/ ^+ H8 Y6 x% t, Q6 |
}: B' T7 V$ F$ Z1 u- K, y! j
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);
}
} n; ^; R7 |+ }' @7 h
}
return 0;
}8 p* I! o4 K; { U; k% R
// SWO Data Queue Transfer
// buf: pointer to buffer with data" ]; V5 T; H; e+ s8 {, s8 O7 R/ g
// 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;+ k/ O8 T2 B6 F; c, S, T# n$ V
if(num>64)
{1 g4 y& h$ J. L6 _ R' }) N
a=64;3 ^% o: B# Z r6 b. W
TX_n=num-64;* a9 f3 q; F' c
pbuf=buf;5 r$ d. _) }) z
3 F8 ^) m7 z* q1 k
}else {4 [& h9 ?% t- H M, E( a
a=num;
TX_n=0;2 l% b, C1 m" E
}
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);- \/ f: F, ^: \7 e
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);6 E: I+ M# i+ k4 K+ |7 X, @9 a( g
} m+ p ^: z6 J3 E" g% w9 y
& B9 N& N% I' M0 g
// SWO Data Abort Transfer
void SWO_AbortTransfer (void) {
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));
//SetEPTxStatus(ENDP2, EP_TX_NAK);$ q8 c% G8 S) {2 n7 J
SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxCount(ENDP2,0);% i0 u! |- Y' ^& F @
//TX_n=0;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/9 b! a% u/ G- f
移植大概是这样的,利用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时感觉速度还是可以的,这能体现批量端点的好处 q! O6 a- G8 z3 H9 e
DWT部分即TIMESTAMP的时间参考,由于没使用Keil的核心库,得自己对相应的寄存器进行开启,而且3.5库的core_cm3.h里面没声明这个寄存器,只得自己定义一下了 `6 o3 z% P- r/ Y& Z
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {8 j* R/ N4 `+ L0 y. Y; K/ M; ^
return (DWT->CYCCNT);
}: x* U3 H, ~" l6 t% N) e
1 ?9 s9 l& o: X6 N$ G% f
void DWT_Init(void)
{
/* 使能DWT外设 */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; 4 U, B7 x% |6 a& k& I
/* DWT CYCCNT寄存器计数清0 */
DWT->CYCCNT = (uint32_t)0u;3 W6 H( g ?& G* l0 Y1 E. P8 n
# j& P# D7 T1 b% X
/* 使能Cortex-M DWT CYCCNT寄存器 */
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
) ^- B0 H$ G3 T1 q; l/ ~. {4 p3 d z
然后加入了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不香么?0 g0 d3 C6 C d- O# h, x# a; ~
声明这个变量static volatile uint32_t SWO_EventFlags=0;% ?' ]! i# c7 @7 k+ Y
在SWO里每一处调用osThreadFlagsSet的地方都改为如:: B; P* o& B% ?5 u
//osThreadFlagsSet(SWO_ThreadId, 1U);" [7 s) L. }6 \ `: F7 K) b
SWO_EventFlags = 1U;
8 j) {$ t, e) @% G$ I4 a4 J
! [2 l9 z& d. r6 `0 q8 {
// SWO Thread% H% ^$ f* X$ @5 o% ^5 Y3 S
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;. m) G' ?0 i8 g6 d% T, E/ [
uint32_t flags; x9 n' Z. G; H
uint32_t count;
uint32_t index;$ y+ G" v) a) i! F- u! y
uint32_t i, n;2 E" \' \% M: Q4 |$ t4 u5 E
//(void) argument;# \, Y* x. @+ ^8 p6 S
//timeout = osWaitForever;, f+ q& A( d( F3 e) _1 H
9 m q: ]2 G5 q7 V
//for (;;) {5 h+ D! \" g0 j* l' [
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);2 ^( Q) r- c4 w& c( E- C
if((SWO_EventFlags & 0x01)==0)return 0;
: G% }. P1 e0 C7 v7 L
flags = SWO_EventFlags;7 R7 Z8 w5 `/ ?9 j* s* s
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不熟悉,不知道是不是这样子. e: Z2 J0 d& l7 y6 v! h% k
;8 x$ e$ g6 G$ l0 f8 {2 e) ~
} else {! M n8 _% P* R3 w9 f5 F
//timeout = osWaitForever;
flags = osFlagsErrorTimeout;9 \4 s1 V4 X. D4 q
}* ^, I0 m/ ?. O0 R6 G) \. x
if (TransferBusy == 0U) {
count = GetTraceCount();! ^) F: l/ T7 _! t7 |
if (count != 0U) {+ D5 }& e: f9 D$ i- q" C5 k3 H
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n) {. l( M% w5 N% S: ^7 F
count = n;
}. M4 a- R$ r3 Q2 [ Z# g M
if(count>USB_BLOCK_SIZE)- d& |; I" m6 J1 E- `, K
count=USB_BLOCK_SIZE;- {5 e2 z& ?( ] _& n
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);
} else {% [, l' @# s# p B0 R
n = USB_BLOCK_SIZE - i;- \' m) q. x6 g
if (count >= n) {7 I. G# o O a* M
count = n;
} else {' n* j/ ^) D& e
count = 0U;
}
}
}$ i( y0 r. y$ i l
if (count != 0U) {8 u! T3 \4 \9 @- D5 L
TransferSize = count;; ]( C2 f9 a- q% e$ a F
TransferBusy = 1U;0 g! C1 O# z5 }, T
SWO_QueueTransfer(&TraceBuf[index], count);
}2 {% S) E3 g" M
} @& Q, p5 A( m5 ~
}2 l6 ]8 ^: Q! T: A8 j8 T
//}/ m9 f4 i0 _% J4 g. [+ S
return 0;
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.- W; X+ b8 _( |1 w
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
static volatile uint32_t SWO_EventFlags=0;! r7 Y! k1 b+ Z" i: M* _
static volatile uint32_t timeout=osWaitForever;
static volatile uint32_t timeWait;
函数改为这样. p. g' u' z3 D) h. x, Z
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {; O0 e- ]5 \6 |5 m* h: [% I4 L# T( r
//uint32_t timeout;3 }4 D- A& S. s0 O
uint32_t flags;
uint32_t count;
uint32_t index;
uint32_t i, n;6 I; q! c1 I1 f) {3 M
//(void) argument;
//timeout = osWaitForever;8 l o, y9 _8 P5 B
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if((SWO_EventFlags & 0x01)==0)9 o. F* ^3 H, |
{
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了
return 0;
}3 U. ~+ q, u: u. |7 \7 U
flags = SWO_EventFlags;
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
timeout = SWO_STREAM_TIMEOUT;
timeWait=DWT->CYCCNT;
} else {
timeout = osWaitForever;' h' @1 G7 y9 Z! J; d# v
flags = osFlagsErrorTimeout;
}* O- }* [* B5 e C. x$ [
if (TransferBusy == 0U) {
count = GetTraceCount();
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;' N3 p2 t' d2 f6 {
# A0 z3 p! D( R; ?- S2 W) O8 L
}
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) { P% h' E' i% s* ?" T, M! E
count &= ~(USB_BLOCK_SIZE - 1U);( M0 x1 N& |2 @9 p% ]: p
} else {
n = USB_BLOCK_SIZE - i;
if (count >= n) {! ?% P5 E* u! P; ]
count = n;
} else {
count = 0U;, x4 a1 m- o+ a$ k6 f$ ?+ |
} a4 k! t0 |5 B
}
}
if (count != 0U) {. f5 i2 Z# p' G) S
TransferSize = count;
TransferBusy = 1U;( m8 _/ [; S: l! S
SWO_QueueTransfer(&TraceBuf[index], count);# ]. b; C0 v) J/ [: H5 |$ ~
}
}
}
//}
return 0;2 Z/ z3 T- Q& D G( ~
}这样修改后也不知道能否解决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,少了这个等待时间,能增加端点的传输速率 K: z p3 F6 d6 p
' a Z( ], b; i" r/ _
int main(void)
{# c5 z3 R! `; ?& Q
DWT_Init();
DAP_Setup();1 I. a3 `/ A x+ \
USB_Interrupts_Config();5 R2 u, G4 n: e2 x+ l
Set_USBClock();% y6 m' f5 a% p. O% U3 m* v$ V
USB_Init();
//TIM3_Init(35999,0);
//TIM_Cmd(TIM3,ENABLE);
. G8 Y. u$ B) J! n+ z2 B: m; n
while (1)8 W1 T6 Z9 I0 Z
{9 U" X- P" c, ?
DAP_Thread();
#if (SWO_STREAM != 0)
SWO_Thread();4 n6 b8 r, y E5 c: }) K7 C3 j8 N
#endif% y$ X) y; G3 b( ~$ a& w& }
}: y1 z o3 z4 P" G D( i! u
}6 \3 D8 D! Y9 ^
' U8 Q/ _: Y) d
对于DAP_config.h的IO配置我是这样弄的2 J; C3 F: f+ ]9 n2 s, G
///@}
// Debug Port I/O Pins
0 Q+ e+ {: c1 T+ ]
// SWCLK/TCK Pin GPIOA[6]
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198" w1 F( R3 t* @4 {) H
#define SWCLK_TCK_IN *( uint32_t*)0x42210118
// SWDIO/TMS Pin GPIOA[7]- x" W6 N5 W) i7 `- ]
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C2 h3 A+ A+ e. @% [( d5 X/ b
/ P+ K; C2 j1 C- M; M- }: \0 l
// 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; \3 o1 f4 ]' M; q4 |& r
*(uint32_t*)0x4221007C = 0;}
, I; W% G0 J5 C; t
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \+ \ l. Q; E* f' q3 I, M2 J: g
*(uint32_t*)0x42210070 = 0; \1 W6 m3 X% c3 ~/ r0 E0 y
*(uint32_t*)0x42210074 = 0; \
*(uint32_t*)0x42210078 = 0; \) s8 j0 f3 b( K2 ^& a ?
*(uint32_t*)0x4221007C = 1; }8 _2 ` q% @2 i9 _4 X: u( P
// TDI Pin GPIOA[8]* ~3 P( f5 m) N3 a1 {' C: ]! F- @
#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$ R3 Y6 R: X; I+ ~- s
// nTRST Pin GPIOB[3]+ d+ {2 Q$ _2 b) _- N2 g3 G* P" G
#define nTRST_OUT *(volatile uint32_t*)0x4221818C8 x; c# E5 e7 h
#define nTRST_IN *(volatile uint32_t*)0x4221010C6 C6 D* G8 K: l. U$ e
// nRESET Pin GPIOB[4]( R' b7 m' v% y7 N! R
#define nRESET_OUT *(volatile uint32_t*)0x42218190+ m5 M* s l6 \! t5 v$ E
#define nRESET_IN *(volatile uint32_t*)0x42218110
' b- V/ S& v( }* b r$ k
// nRESET Output Enable Pin GPIOB[4]; e9 D ~: p' ]# o
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 1; \
*(uint32_t*)0x42218044 = 1; \5 h' }& l# G+ i) c9 Z
*(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;\5 C( ], N) C4 d; f" O( a6 {1 y
*(uint32_t*)0x4221804C = 1; }
' ~/ f# Q8 h5 I( k2 D& H) A
// Debug Unit LEDs
) q. m4 X; e, S" r
// Connected LED GPIOC[13], _& l8 u% v. s6 i5 N
#define LED_OUT *(volatile uint32_t*)0x422201B4
#define LED_IN *(volatile uint32_t*)0x42220134
& p% J. S) y* g7 o) P5 x9 `
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \
*(uint32_t*)0x422200D0 = 0; \
*(uint32_t*)0x422200D4 = 0; \# ~ }/ b9 H( K' w1 y6 ?
*(uint32_t*)0x422200D8 = 0; \
*(uint32_t*)0x422200DC = 1; }6 |* q9 K* \! s2 H+ K, v# z
// Target Running LED Not available+ Q' N: E6 Y) K: i C9 U
+ u* ^- x% s) y" v7 a
// SWCLK/TCK I/O pin -------------------------------------" _' f N7 W! I& W7 [/ ~4 s
# A. b7 v' b! I$ S6 i
/** 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) {" t( ?' y/ _: e1 Y8 ]
return (SWCLK_TCK_IN);& }2 ^; q+ y& m, S
}
; J6 U8 i0 `3 M4 l, m
/** SWCLK/TCK I/O pin: Set Output to High.; [0 E. y9 d \4 s: `( T7 b- P
Set the SWCLK/TCK DAP hardware I/O pin to high level.# d: {# b% J4 U$ X) |$ z' H& ]: m+ X. _
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {1 l8 Z0 O1 h; Q/ I) U9 i
SWCLK_TCK_OUT = 1;
}; z" J% w# u9 Z+ y N
. S/ R) N9 c6 |$ R! ]: {4 o& D, ?! I
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/- k( Z ~% g# ?! [
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
SWCLK_TCK_OUT = 0;2 V7 d4 Z6 p! d- ]
}6 E } M0 q2 i; {
* M5 t: C% X, w. j1 |0 V# W7 a3 `& ^
// SWDIO/TMS Pin I/O --------------------------------------/ t( u: B2 e) k; q; G9 l* f* T
* f- r. A3 @: C" D& M/ q
/** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin.% S; @/ c* s0 \3 I5 o" C# x
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (SWDIO_TMS_IN);
}
/** SWDIO/TMS I/O pin: Set Output to High.! W" x1 \* F$ Z9 L) _1 Q/ R6 T( t) h
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/4 v' {4 l$ N4 k9 ~
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {9 v- \+ L9 [) M" F8 Y) I4 y3 d6 [
SWDIO_TMS_OUT = 1;$ F* S* K2 X* i. |' F& d) L
}
( ]3 ~* A" z8 P; X; d- t
/** 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) {. ~' Q, S3 |. F$ p# O# k
SWDIO_TMS_OUT = 0;- d- l0 a8 j+ [" z
}8 \( C2 m2 w4 _5 q8 W; ~. O" ?- S4 m
3 n3 A) A% g8 H& j
/** SWDIO I/O pin: Get Input (used in SWD mode only).: b8 x# P8 }6 b- h3 O% W% Q3 Q
\return Current status of the SWDIO DAP hardware I/O pin.% N" I" p5 a1 U4 d# ]' m
*/1 B( N n' j8 m% ]3 H$ e1 E: I m) H
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {* q% V: F' [( Q
return (SWDIO_TMS_IN);5 @: u7 ?0 ]5 M% M$ z
}# ]' i3 I7 V5 p/ q
/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin." d0 f$ R/ ] r
*/: y; p8 ~5 s" q( v
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {' {! l, u9 t ^' N! C% o# ?8 b
SWDIO_TMS_OUT = bit;
}
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).5 `7 M) q7 w* U i
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();# R: V0 _+ T* [5 d9 T+ T
}# g1 U$ E5 u. s3 i# T' K U
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).5 A' M5 q# p* N
Configure the SWDIO DAP hardware I/O pin to input mode. This function is2 V/ N# j/ i7 z/ |
called prior \ref PIN_SWDIO_IN function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
SWDIO_Input();
}2 [5 L0 {" l+ _; v& p
* j6 A: ^$ i* F1 `6 Q$ [+ a
楼上有的说弄无线,其实无线也就是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驱动的大佬可以尝试一下
有人将这个工程移植到stm32f4上吗,我在网上找了一个f4的dap工程,但是编译下载后无法使用。