你的浏览器版本过低,可能导致网站不能正常访问!为了你能正常使用网站功能,请使用这些浏览器。
ricklou 发表于 2021-1-25 10:50 4 V% c" C$ A: k5 S4 N. i7 X1 J, R除了mdk和iar能自动复位,其软件他都不行(iar for 8051、keil uv4、keil c166、jltool3、nfc tool、arduin ...
ricklou 发表于 2021-1-27 23:00 ) ]: \& t% k% r+ x8 Z可以把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发出复位命令。' O1 J! T! \% P0 i0 x
+ |" F! U: T+ k, s5 k
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。( j$ d" d$ x$ D' E+ M p
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。6 v: @& v' B/ X) k
! }; ~; p" ~; s$ Y" @
/**
******************************************************************************
* @file usb_endp.c2 P; Z' C/ @' O' k
* @author MCD Application Team9 D% j$ {$ @- F" z4 D! V! [
* @version V4.1.08 a8 b) K$ e; s0 d/ K% b( S% R
* @date 26-May-2017+ A3 T0 }5 R( d1 w$ v
* @brief Endpoint routines
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>$ M- ] \ B# k, e4 ]- x3 \9 Y1 q3 \( W
*
* Redistribution and use in source and binary forms, with or without modification,! Z! x: s3 T+ H4 [. {" A5 v: ]
* are permitted provided that the following conditions are met:2 d- Z w1 ?) o4 _' E6 e) s
* 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" L% R7 x" O+ F( h) E6 `" \
* and/or other materials provided with the distribution.( M& K1 c! q* E! M% ?- }% k) c. V
* 3. Neither the name of STMicroelectronics nor the names of its contributors" O' \; C+ c t! T5 ~
* may be used to endorse or promote products derived from this software
* without specific prior written permission.; Z4 N4 d( F" l8 k
** ^# d4 o- q9 T: g( m
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"7 y" ~3 u% S5 N5 L+ ?
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE) l: ]2 t7 a; `: b8 _4 F
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL7 L3 _; l4 C; O& m: d8 A: q) Q
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR) g$ W: e2 {9 R' B4 \
* 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 USE9 Z& \% Z/ I1 G0 ~3 h' q& p$ G& c) s/ Z
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*8 u1 s# ]; I9 {
******************************************************************************( _, q* T8 j/ r! ~* A4 W2 C
*/0 J( v% f, b* T
/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"
#include "usb_lib.h", Y/ `9 v1 B5 l8 d5 B+ J, `. n
#include "usb_istr.h", K. X X; F7 V& q; {4 Y& }
#include "stepper.h"
#include "string.h". A7 s6 @. c/ O; l7 l: p
#include "DAP_config.h"
#include "DAP.h"( t: q p4 `3 r( I0 F; Z
3 R# h" f$ s0 H/ ?: p5 Y; l R- S
/* 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( O! P$ M( c. Y
static volatile uint16_t USB_RequestCountI; // Request Count In1 n* e8 ^' [% c# r8 f, p
static volatile uint16_t USB_RequestCountO; // Request Count Out
static volatile uint8_t USB_RequestIdle; // Request Idle Flag7 w+ V4 D7 X% \9 V2 L3 n
static volatile uint16_t USB_ResponseIndexI; // Response Index In5 a7 i, c" i" w$ R
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 Flag0 V" [. P9 |: x; ^- ~' E
static volatile uint32_t USB_EventFlags;5 w7 D) C J5 f- x( m" g l3 T
' u& w, i% L7 ? N9 `- _& a
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];- g( e) @0 z8 a m- G; k0 c8 x$ Y
$ G# i1 N0 ^, y5 R4 V: g
/* Private function prototypes -----------------------------------------------*/. R4 d3 Q ?) Z5 u
/* Private functions ---------------------------------------------------------*/) b% ~1 y$ E" @0 O- m+ I
/*******************************************************************************2 {4 A4 t! ^/ R$ [
* Function Name : EP1_OUT_Callback.
* Description : EP1 OUT Callback Routine.
* Input : None.
* Output : None.& k9 {. Q6 F: h$ A$ a
* Return : None./ O% B# a. o3 r' R7 q$ ?* h4 ?! M8 O
*******************************************************************************/% o* ]! c/ F, U) c n8 R% G6 a& W! B
void EP1_OUT_Callback(void)6 {* i" I" |6 u( e
{" J$ J% I$ m/ R
uint16_t n;
n = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);
if(n !=0){/ A6 c) V$ f( A$ r; R- j& y
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {
DAP_TransferAbort = 1U;0 h1 i) M+ K3 ?, k, p: Z
} else {
USB_RequestIndexI++;
if (USB_RequestIndexI == DAP_PACKET_COUNT) {
USB_RequestIndexI = 0U;: g3 l. y8 r5 _/ a/ j
}, J& ?; v0 q# g
USB_RequestCountI++;
USB_EventFlags = 0x01;
}. r& F. t, }: n J
} 8 a9 n8 F& B% ?* Y/ C2 N
// Start reception of next request packet/ @: l/ G" R0 {5 ?4 d
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
SetEPRxStatus(ENDP1, EP_RX_VALID);% j4 N8 J, j2 |' p+ V& |( X ^
} else {( i5 t6 u3 ^( y) z
USB_RequestIdle = 1U;
}
}8 z- v5 d7 g5 b, S; j
, V8 c$ C" E. N* n
/*******************************************************************************
* Function Name : EP2_OUT_Callback.
* Description : EP2 OUT Callback Routine.
* Input : None.
* Output : None.( b6 f) s. i8 _ L3 E; w
* Return : None.8 _2 C- _9 Y- M9 N7 S
*******************************************************************************/
static volatile uint32_t TX_n;3 S1 g7 Z( ^8 p3 O
static uint8_t *pbuf;# H c" C/ v( F0 p* Y4 g$ Y
void EP2_IN_Callback(void)
{8 X2 A) `, Y9 l0 G, q9 ?1 r
uint32_t a;
if(TX_n>0){
pbuf+=64;6 w$ `3 V* _* _* v9 T$ K
if(TX_n>64){
a=64;
TX_n-=64;
}else{
a=TX_n;
TX_n=0;4 r+ |* m5 C; _; j" R
}
+ v/ ]' l8 q4 r _/ a/ N% B
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);- V7 M; v$ K) }( B
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);- {. Y# G# G% ?# N" o' y% p
}else{8 }( m$ i' @6 @
#if (SWO_STREAM != 0) s# \) i7 V- ~) Q; C, _9 F
SWO_TransferComplete();
#endif
}
}
4 u+ ?/ L; h9 f; a) i
/*******************************************************************************
* Function Name : EP1_IN_Callback.; c& h9 |* t1 d& ~ z0 p# ?
* Description : EP1 IN Callback Routine.! W+ [4 b( \) d6 i
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/) G( y: s' }' z7 k
void EP1_IN_Callback(void)
{& c- r7 h& l N/ N5 D
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]);: h3 O4 v' k9 |, z1 |& Y
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);
SetEPTxValid(ENDP1);
USB_ResponseIndexO++;0 A; ]5 T! J4 T' g
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;
}
USB_ResponseCountO++;
} else {6 \ r- E+ |: n8 a" E
USB_ResponseIdle = 1U;
} : R {" j# w4 g6 u2 r7 V
}
// Called during USBD_Initialize to initialize the USB HID class instance.. f s3 u$ ?& v: ?
void DAP_FIFO_Init(void)
{
// Initialize variables
USB_RequestIndexI = 0U;
USB_RequestIndexO = 0U;
USB_RequestCountI = 0U;) b" M2 X% I% n8 I$ X9 s$ {$ Y
USB_RequestCountO = 0U;
USB_ResponseIndexI = 0U;6 o5 I: t9 Q% O
USB_ResponseIndexO = 0U;
USB_ResponseCountI = 0U;
USB_ResponseCountO = 0U;
USB_ResponseIdle = 1U;
USB_EventFlags = 0U;9 w4 P* ?7 d. Y( }3 Y
}; D- e3 n% h3 K# [( r0 x
9 m+ Q6 p8 r& |- T! k+ {
uint8_t DAP_Thread (void) {
uint32_t flags;# D$ V2 x- Z1 E% X; k4 [
uint32_t n;
//for (;;) {- }) H8 H! G6 L3 u$ Q3 ~$ ~4 l
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);
if((USB_EventFlags & 0x81) == 0)
{ Z3 H' X4 r4 b1 f4 R
return 0;
}
USB_EventFlags &= (~0X81);( E( `- r( d# `2 b- _3 Y& f7 I) b
! n; \7 n" t8 Y4 m$ l9 |% l7 u% S
// Process pending requests
while (USB_RequestCountI != USB_RequestCountO) {* O5 ^' N8 e' c( n H" j
//if (USB_RequestCountI != USB_RequestCountO) {0 R* v. T/ o3 C2 m) V" T' n
// Handle Queue Commands
n = USB_RequestIndexO;: k3 {0 Q; E+ V# i w% I h
while (USB_Request[n][0] == ID_DAP_QueueCommands) {% u4 u/ M$ k+ r3 G
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {
USB_Request[n][0] = ID_DAP_ExecuteCommands;
n++;
if (n == DAP_PACKET_COUNT) {0 {5 k- Z* j) A6 [3 N* {# b+ D; A' U
n = 0U;3 {- y. p: [2 B8 g2 t5 F2 h& }
}
if (n == USB_RequestIndexI) {# y% a# u I2 o# {1 t O o
flags = USB_EventFlags;' M5 \0 [ q# i; t, s
if (flags & 0x80U) {5 V, O; _7 c: f( c1 L
break;4 ]2 j0 f0 |' A6 z/ Z5 o7 H
}
}3 K! y" E& S, R& t8 i2 @+ }$ J0 B
}
// Execute DAP Command (process request and prepare response)
USB_RespSize[USB_ResponseIndexI] =! j# W+ l1 R6 A0 ?1 s6 M
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);
3 c8 d+ u5 t, g0 V( _
// Update Request Index and Count
USB_RequestIndexO++;
if (USB_RequestIndexO == DAP_PACKET_COUNT) {' i9 A- I# l6 h( R% @8 v
USB_RequestIndexO = 0U;7 U6 Y) `) B r; ?, ]5 b- h/ @
}- K3 q$ {. ]' z7 c6 \( Z
USB_RequestCountO++;* R+ j+ M; }- o" f6 U- x( M% C
A: r' }6 R& F/ w
if (USB_RequestIdle) {
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
USB_RequestIdle = 0U;
SetEPRxStatus(ENDP1, EP_RX_VALID);9 }! `# m4 `& O) n
}) p1 R' ]( X9 s. K+ N( z. ]
}
// Update Response Index and Count8 t6 \ F' m8 B/ ], X; L
USB_ResponseIndexI++;
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {
USB_ResponseIndexI = 0U;! ?' e! w& ]+ I0 x
}
USB_ResponseCountI++;% X3 W8 D! ^1 v6 a
' Y8 t$ N2 p+ ~$ h% p/ |- m# p- {
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) {% X/ o8 U* t0 m; h% _8 o3 S
USB_ResponseIndexO = 0U;3 O8 `! n* p- a. @4 k. a/ e! {' m
}
USB_ResponseCountO++;; J: ~. M3 C* k- j: q$ G
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]);8 ^4 W3 f7 e1 H0 X( s& {3 i1 R, p
SetEPTxCount(ENDP1,USB_RespSize[n]);
SetEPTxValid(ENDP1);
}
}
}. \% t' N9 s5 z9 m' _
return 0;
}/ q% m. _$ f1 u, B' q5 E
// SWO Data Queue Transfer
// buf: pointer to buffer with data+ Y! G- p2 J. r) ?& D; w
// 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;
. l2 D" `& M v' U* J
if(num>64)
{
a=64;1 o* X6 L/ o) C& E- x! u5 }
TX_n=num-64;; G" j/ u! a, i+ R L( M, E7 H- j* R- f
pbuf=buf;
}else {
a=num;
TX_n=0;
}; V* }) w; l* `( y+ }
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);( i+ Q! F4 F; [5 X4 b
SetEPTxValid(ENDP2);
}
6 k6 T5 ^9 P7 j7 C6 Q
// SWO Data Abort Transfer
void SWO_AbortTransfer (void) {: g: {/ @. R- |- E f& `. z
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));
//SetEPTxStatus(ENDP2, EP_TX_NAK);
SetEPTxStatus(ENDP2, EP_TX_DIS);& O8 L! v* n* z: P) {8 x- B
SetEPTxCount(ENDP2,0);
//TX_n=0;" m3 U* b# n( z7 @
} m& a, [% m$ ^9 u- r
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
) \* b0 }" q6 m7 {% l% L- [1 }
移植大概是这样的,利用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时感觉速度还是可以的,这能体现批量端点的好处, e9 b9 m. W( T4 I" l( w
DWT部分即TIMESTAMP的时间参考,由于没使用Keil的核心库,得自己对相应的寄存器进行开启,而且3.5库的core_cm3.h里面没声明这个寄存器,只得自己定义一下了& f' R# S7 S! m
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {: e7 C1 r3 x, J$ W* G5 U
return (DWT->CYCCNT);
}0 j0 m; N3 h- b+ v1 `) {1 O# _
void DWT_Init(void)
{
/* 使能DWT外设 */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
: ]/ V: J$ g) U4 u3 b; @
/* DWT CYCCNT寄存器计数清0 */
DWT->CYCCNT = (uint32_t)0u;
* K" w/ `& j6 y" s
/* 使能Cortex-M DWT CYCCNT寄存器 */
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
% a# Z$ O' l( Y! f
然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率
) w! |# b( z" |; p' B% h3 X R
然后改为使用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);/ p) A, H$ p8 u5 n& f4 T( x
SWO_EventFlags = 1U;
: N: ~2 ~& |7 @
; x/ ?, e2 f8 U0 |; o4 C
// SWO Thread! {* Y$ l+ x" ?3 A: h3 L
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {! ^/ e$ }0 L, {/ t! {' n) m
//uint32_t timeout;
uint32_t flags;
uint32_t count;
uint32_t index;
uint32_t i, n;
//(void) argument;+ i( s4 q% \; |1 z+ M0 H) k4 v9 \' `
' o* \: F r+ R; [* a* V$ ^5 U K# \
//timeout = osWaitForever;
/ J9 A% E3 q% b x0 Q& n
//for (;;) {, _5 b: ?; [3 V6 l' z- w* O k
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);$ S5 o6 p1 {) {- B6 M) X; F
if((SWO_EventFlags & 0x01)==0)return 0;+ i8 X0 m4 ^6 W3 C7 Q r
; |# j9 L! }( y! u/ w
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不熟悉,不知道是不是这样子
;. M* G+ `4 ?: s/ l, e
} else {; h) e5 O2 n2 ?& J! a. P
//timeout = osWaitForever;+ K3 G0 n7 G3 \' i. B c
flags = osFlagsErrorTimeout;
}8 C: V5 C9 q8 t G6 [5 h
if (TransferBusy == 0U) {; x: R0 }5 Y- a8 S* Y* m3 |1 K
count = GetTraceCount();% V1 G# h* v* F. D$ o4 i9 T
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;) S/ V$ `1 y1 D9 M
if (count > n) {$ E7 L! G( S5 f5 ~- B" }
count = n;
3 o9 D; t* t; \/ q) m/ I
}: |+ ^6 U* p2 D, R- f2 M, D
if(count>USB_BLOCK_SIZE)# k) H% X2 E/ w9 i$ [
count=USB_BLOCK_SIZE;5 [$ V$ R P! y; T- y7 ~
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {2 {8 b" v9 i7 C9 Z
count &= ~(USB_BLOCK_SIZE - 1U);
} else {1 }0 u; o) ^3 p
n = USB_BLOCK_SIZE - i;
if (count >= n) {5 G" P/ E% f D
count = n;% } N6 W: s8 @0 |* O R/ |2 x
} else {2 \) q. Z6 R# \/ D5 a
count = 0U;6 w: B9 u0 m' W
}' Q, u1 O, N& _/ I( P
}
} \2 w# C6 T: W1 i9 _. T; q7 S
if (count != 0U) {
TransferSize = count;
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count); f. _: @- l. l. X7 S+ K
}8 ?0 b- G5 [$ e- J2 o% C
}
}, S1 V. }! p2 W$ d* t
//}0 a( u4 l* [$ I0 p: r! Q* y
return 0;7 t7 s) \. D* u1 x- p& Q3 \( B5 ^
}8 B. N# H6 \! y
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
static volatile uint32_t SWO_EventFlags=0;; J, E' W& H' r& Z% |
static volatile uint32_t timeout=osWaitForever;
static volatile uint32_t timeWait;
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {9 P8 N4 e2 n& N& J# R
//uint32_t timeout;
uint32_t flags;* n2 P5 ]) b9 h$ v" e+ i' y7 q
uint32_t count;
uint32_t index;
uint32_t i, n;
//(void) argument;3 R9 {8 k1 I% E; C+ L. M
: X) E+ m3 C) M6 D5 Y$ y) q
//timeout = osWaitForever;
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);+ x1 }2 A7 a" }4 {- E4 j( }
if((SWO_EventFlags & 0x01)==0), O; }9 k; O4 j$ W5 f) Y
{
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了, G+ s# ?* [ S! y
return 0;+ W) J9 w" g9 k7 D
4 a; Q( f9 n& y5 s: l/ P
}
flags = SWO_EventFlags;2 i* X2 G# Y8 P, c/ l/ z
SWO_EventFlags = 0U; : N" S5 M; m/ b& _7 F" o
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
timeout = SWO_STREAM_TIMEOUT;! e: u4 H3 R2 D$ m" V8 p
timeWait=DWT->CYCCNT;
} else {
timeout = osWaitForever;
flags = osFlagsErrorTimeout;; k5 K, X9 h5 T4 H
}2 E3 N6 c' e% ~- v
if (TransferBusy == 0U) {
count = GetTraceCount();1 A. H8 d4 L7 b- {
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);7 x' v9 A' g; C$ g; e% C
n = SWO_BUFFER_SIZE - index;4 Z3 v! t' S7 H1 f# ]0 |
if (count > n) {
count = n;
}
if(count>USB_BLOCK_SIZE)1 r& i3 s. G" e/ U8 b% U. `
count=USB_BLOCK_SIZE;: H5 A+ l9 i o" j2 m
if (flags != osFlagsErrorTimeout) {' |* C8 z% o! d! H, q) E" P3 u
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);
} else {" o8 ]4 }* z3 a" |" r# W: J
n = USB_BLOCK_SIZE - i;
if (count >= n) {+ \2 Q! J2 M! ?: J# ~
count = n;; I d4 m4 N7 n/ x- ]9 K
} else {
count = 0U;9 g7 J+ q) A4 [8 C
}
}. J. A* m& o* w- y( Y
}
if (count != 0U) {
TransferSize = count;5 D L% o: m0 W, n$ }$ I
TransferBusy = 1U;; H1 H1 t& Q9 F
SWO_QueueTransfer(&TraceBuf[index], count);
}: @. c# n( T2 B1 j3 p' M
}, w: G& c* _" T+ D1 X* o
}! c( T) l% E2 ]
//}& @- l% q5 Y& _- C" v& E
return 0;6 |; ?2 U+ M( B0 A" t; a) @
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了& M& P. ~1 q5 ]3 u
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,少了这个等待时间,能增加端点的传输速率
. V9 ~7 \6 S! F$ \
int main(void)2 \. }, N2 I: l' K4 [
{
DWT_Init();; U' z' z$ ?" U7 R9 ]
DAP_Setup();
USB_Interrupts_Config();6 i& r7 O G' n
Set_USBClock();
USB_Init();
//TIM3_Init(35999,0);. h1 Z0 T9 }; W& v3 X! z
//TIM_Cmd(TIM3,ENABLE);+ I* Q% R0 _4 F5 f
8 s* p/ K. P, H0 ^2 D1 K% X$ G% W3 x
" J& i6 c/ f8 c0 d0 ?; Q8 X" s
while (1)
{6 {$ H/ v$ C; d& s/ ^
DAP_Thread();
#if (SWO_STREAM != 0)
SWO_Thread();; O5 N, C1 |5 P6 n9 W/ j) B
#endif
}
}
7 Q: \; k- |4 K; \; J
对于DAP_config.h的IO配置我是这样弄的0 K% M4 ^, j) c) e% d t: x
///@}1 [- v2 X4 }$ e8 X
// Debug Port I/O Pins3 H) K, T k$ ^5 z) n
) s8 Z3 d1 N3 L4 K. N. k
// SWCLK/TCK Pin GPIOA[6]" ?2 A! L0 n7 R
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198
#define SWCLK_TCK_IN *( uint32_t*)0x42210118
0 X8 n% `( h& o9 R1 X
// SWDIO/TMS Pin GPIOA[7], e4 H, Z, a5 s" t1 [
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C* D" `- }- P) W& ?
// SWDIO Output Enable Pin GPIOA[7]7 B9 V6 c0 D5 a$ j. s
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 1; \: [$ l2 G3 O7 ?8 Z* u' t2 M! r
*(uint32_t*)0x42210074 = 1; \
*(uint32_t*)0x42210078 = 0; \* C* ~6 v4 Z" ?1 p0 p$ ]/ y
*(uint32_t*)0x4221007C = 0;}
1 T/ \1 s% w I4 b, P: i7 p
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \6 ^, l1 @9 I' V
*(uint32_t*)0x42210070 = 0; \
*(uint32_t*)0x42210074 = 0; \
*(uint32_t*)0x42210078 = 0; \' M$ n7 K1 {: P# A
*(uint32_t*)0x4221007C = 1; }: ]& N* @: U- F" E2 L6 y6 C% M
3 z4 v m+ a) E9 k! j3 O% d
// TDI Pin GPIOA[8]
#define TDI_OUT *(volatile uint32_t*)0x422101A0/ v4 V. Y. M& M
#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
" G2 ]$ X- X `0 K; ?4 E
// nTRST Pin GPIOB[3]; r; ~$ M' D0 y0 P! ~' k% n
#define nTRST_OUT *(volatile uint32_t*)0x4221818C
#define nTRST_IN *(volatile uint32_t*)0x4221010C* N; |) w3 h1 W4 u j7 T4 P
// nRESET Pin GPIOB[4]
#define nRESET_OUT *(volatile uint32_t*)0x42218190, n; J `+ H- u. l
#define nRESET_IN *(volatile uint32_t*)0x42218110
5 m" t. V0 |0 u2 b) V
// nRESET Output Enable Pin GPIOB[4]& Z* v: T/ s" \4 d* |( M# \" |( [
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 1; \
*(uint32_t*)0x42218044 = 1; \
*(uint32_t*)0x42218048 = 0; \. J* D( @+ \7 Q4 ?/ I3 y$ X
*(uint32_t*)0x4221804C = 0; } 5 y. y% G* I" z/ d6 l
+ F3 U# g7 e" W- A( I$ K
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 0; \2 S/ }/ O6 }) z# s: } {
*(uint32_t*)0x42218044 = 0; \* _+ N3 q9 t6 `* D6 U
*(uint32_t*)0x42218048 = 0;\1 @/ g4 \, T3 p& I' r3 X
*(uint32_t*)0x4221804C = 1; }6 u0 C/ E) ]7 b5 R
3 A; b$ I: M. C# Y$ ]( a9 N0 Y/ r
' M$ A! [, h) P) i
// Debug Unit LEDs
- j; X6 g+ B! `5 z, b) u
// Connected LED GPIOC[13]
#define LED_OUT *(volatile uint32_t*)0x422201B43 |# P; Y. ~0 R$ n, V% x
#define LED_IN *(volatile uint32_t*)0x42220134
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \" h) k; ]& [5 P1 _/ E" |6 p5 _9 f% Q
*(uint32_t*)0x422200D0 = 0; \. S) H# v3 L8 ]# H8 \$ s/ Y0 O) g
*(uint32_t*)0x422200D4 = 0; \% F" L6 w( { _$ V0 _% w2 E
*(uint32_t*)0x422200D8 = 0; \+ }! N Q' ~" R) A) c/ O8 S
*(uint32_t*)0x422200DC = 1; }
// Target Running LED Not available
4 `' U. x) n. I4 Y2 S
// SWCLK/TCK I/O pin -------------------------------------5 N1 M- @* X3 A% r( S. ~
/** SWCLK/TCK I/O pin: Get Input.( |6 K; r/ ?+ b8 ]
\return Current status of the SWCLK/TCK DAP hardware I/O pin., Z8 L. Z; O: O
*/
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {" X4 E% G! e0 ~% a2 U
return (SWCLK_TCK_IN);
}/ a4 W% N- r! B: [$ B
/** SWCLK/TCK I/O pin: Set Output to High.& p+ u, m0 |% v6 L+ \/ p0 t
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {" ]2 Y1 D, _1 x
SWCLK_TCK_OUT = 1;: D$ u3 e) \3 l0 {3 \% U" R3 k
}
, c" T b9 B* s* {
/** SWCLK/TCK I/O pin: Set Output to Low. Q6 H" A7 V4 e: t
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
SWCLK_TCK_OUT = 0;* k& v! H8 _# Z; s. A9 j7 i2 O
}4 f8 G+ f0 U/ M2 p! }) b
+ P3 |. q3 o9 A$ ?/ Y' R; e3 a
+ d* ]) H% V$ N6 ]' q% F' H
// SWDIO/TMS Pin I/O --------------------------------------
( m0 i4 S8 y* c# }9 S
/** 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);% a5 j0 p5 c5 U6 f* h9 m' Q
}% {& o* R- R. c' @& R
! S- M4 ^! Z0 x# o8 W
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/4 E0 V# u/ @4 k9 I4 E# `6 q& v4 j# N
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {! g6 J' I$ T7 X# u! J" q' C
SWDIO_TMS_OUT = 1;
}
/** SWDIO/TMS I/O pin: Set Output to Low.1 k I) C6 A7 ?) N; z
Set the SWDIO/TMS DAP hardware I/O pin to low level.( z+ l/ U& E1 T' ~1 H& N8 L% U
*/5 T5 F" t0 K L3 O
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {5 S1 g( h( d5 l
SWDIO_TMS_OUT = 0;" p: G! A" ]' G& f" _; f
}" p0 C$ B8 }( p2 x; j
& z [7 G0 w T: e% |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);
}
# p7 N9 }7 y+ e+ x, M; _4 z+ l( }, `7 ]
/** SWDIO I/O pin: Set Output (used in SWD mode only).5 g* W5 x- |, q$ S. W0 `) j
\param bit Output value for the SWDIO DAP hardware I/O pin.
*/ g* t6 u' R( o: _ G; e! Y6 `
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
SWDIO_TMS_OUT = bit;
}( _. g6 k" M& Z$ b' y3 y) Q
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).2 M- J: T8 |: p5 t$ y- E
Configure the SWDIO DAP hardware I/O pin to output mode. This function is/ y m" c* K% S- Z
called prior \ref PIN_SWDIO_OUT function calls.0 @# |( l% F' |6 V' }/ ?/ i
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {: ~7 X2 m5 ^2 E, @9 ^
SWDIO_Output();' @& m6 K9 s1 w, o
}
/** 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.& F4 ~" J0 Y& I
*/, F) G) c0 A, i) q& D
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {; b% w# E4 u2 \3 n1 N: V" j
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驱动的大佬可以尝试一下
有人将这个工程移植到stm32f4上吗,我在网上找了一个f4的dap工程,但是编译下载后无法使用。