你的浏览器版本过低,可能导致网站不能正常访问!为了你能正常使用网站功能,请使用这些浏览器。
ricklou 发表于 2021-1-25 10:50 / n8 M5 S+ U% x5 U除了mdk和iar能自动复位,其软件他都不行(iar for 8051、keil uv4、keil c166、jltool3、nfc tool、arduin ...
ricklou 发表于 2021-1-27 23:00 $ Y* A0 H: `0 A5 Y5 f! 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发出复位命令。
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。
5 E+ s% S/ l; s, ^9 Q# L m6 H. Y
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。% U) O) Y2 Q( ?1 h' N* l
0 o/ i U% P1 j5 P( K) Z* V8 e8 N
/**. A3 ~+ E% h- E3 k. ^2 a
******************************************************************************
* @file usb_endp.c7 F* {+ `1 T s# U& K5 U3 n
* @author MCD Application Team3 a5 O- o5 G/ |
* @version V4.1.09 P# C; J* F! |$ L
* @date 26-May-2017# i+ r- p- e e9 ^
* @brief Endpoint routines
******************************************************************************
* @attention5 Y6 k; C5 T# A3 y6 ~& i c% ], g
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2># R( q; p* v* A- A
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:* j7 e T% a, s" Y2 f) O
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.& J+ y# T. L8 d9 C
* 2. Redistributions in binary form must reproduce the above copyright notice,7 `7 m* i2 e# Z
* 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( ~( i1 k. y1 o. {" f
* may be used to endorse or promote products derived from this software" k6 I# V" X7 f/ n O I
* without specific prior written permission.5 ^9 A5 P7 C! V3 ~' _* [
*) W/ @# l7 r! G- c
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"/ g7 D* c, W- Z
* 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' F4 w; h8 X+ R# x q. ?# }" q* y }
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR, P- h9 C S: P3 Y5 J2 O
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, @/ R4 C/ T1 |( T" o
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE/ c2 B- S; v. E5 ]8 [' f3 I
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*0 b8 f5 p6 ~+ T0 u
******************************************************************************$ E; s4 P4 ]; d g, E; [. p
*/0 A7 ]: `# x/ K! e
/* Includes ------------------------------------------------------------------*/ E% M6 w* u8 G8 e, L. W: T r
#include "hw_config.h"
#include "usb_lib.h"0 @% K* e) d/ Y& W
#include "usb_istr.h"
#include "stepper.h"
#include "string.h"
#include "DAP_config.h"
#include "DAP.h") d$ A( {9 d& g; @, {
2 p2 O6 M: A* A; D
/* Private typedef -----------------------------------------------------------*/ E$ }/ t, x& I! l
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/5 V6 c# r: U. ^9 `' i* R
/* Private variables ---------------------------------------------------------*/" a5 g- {. O" E( z( H. |
static volatile uint16_t USB_RequestIndexI; // Request Index In
static volatile uint16_t USB_RequestIndexO; // Request Index Out) p5 ?% a8 j$ F6 C- U- {
static volatile uint16_t USB_RequestCountI; // Request Count In- H' W! C. _' x& w) Z& H; q
static volatile uint16_t USB_RequestCountO; // Request Count Out
static volatile uint8_t USB_RequestIdle; // Request Idle Flag1 K$ W) [ \, S' } t
+ u, F3 M! {1 {
static volatile uint16_t USB_ResponseIndexI; // Response Index In2 N$ C) X2 p' `' b8 D) @
static volatile uint16_t USB_ResponseIndexO; // Response Index Out e. V6 g) H6 V1 u% R9 v8 }
static volatile uint16_t USB_ResponseCountI; // Response Count In& ?, r' l% a5 S
static volatile uint16_t USB_ResponseCountO; // Response Count Out
static volatile uint8_t USB_ResponseIdle; // Response Idle Flag. n3 W- k9 D2 C2 A
static volatile uint32_t USB_EventFlags;
9 j; k7 ~) v' h- [" @
static uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Request Buffer2 g) F9 L$ [$ K8 F2 O/ n/ }
static uint8_t USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Response Buffer* f" ]: n5 Z) g
static uint16_t USB_RespSize[DAP_PACKET_COUNT];4 \7 M6 Q, }! I D
1 @8 X# i/ i8 N0 Y! I8 H, U
/* Private function prototypes -----------------------------------------------*/9 F, w- u8 r4 {1 V9 t
/* Private functions ---------------------------------------------------------*/1 o; I' ~$ W/ x9 ] y$ @9 {" m( N
/*******************************************************************************/ a( p X' [6 a
* Function Name : EP1_OUT_Callback.
* Description : EP1 OUT Callback Routine.
* Input : None.
* Output : None.& G+ o" Y& l$ T9 [ e
* Return : None.
*******************************************************************************/
void EP1_OUT_Callback(void)" Q" H" B, B# t4 E7 K5 {7 e( c
{
uint16_t n;; G' T, X6 \+ U8 I4 r
7 }, U3 D- V5 l
n = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);
if(n !=0){; y2 T3 ]" r# j
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {
DAP_TransferAbort = 1U;
} else {: n. t7 X! p7 t4 Z; z: m; M9 G, l1 _
USB_RequestIndexI++;
if (USB_RequestIndexI == DAP_PACKET_COUNT) {
USB_RequestIndexI = 0U;7 _6 G5 u- t" u/ s! M* G9 N
}
USB_RequestCountI++;
USB_EventFlags = 0x01;
}$ g5 M' A8 C, T# [, w5 J$ m9 ]
}
// Start reception of next request packet' u/ K" e+ x, I1 H# m# { _" G R
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
SetEPRxStatus(ENDP1, EP_RX_VALID);
} else {
USB_RequestIdle = 1U;" A9 n! U+ r" z$ \9 _* l A
} " J. a! X2 |. F7 U
}: d5 ~' z+ s @
1 w6 W& @: U0 Y! ^8 O
/*******************************************************************************
* Function Name : EP2_OUT_Callback.( ]6 m6 A9 t1 F2 x! A; g) b
* Description : EP2 OUT Callback Routine.: |8 `2 G! B5 f
* Input : None.9 h; O' O; }# N. d# F s# Y; h
* Output : None.
* Return : None.; O8 X% L8 p& y% d& c2 g
*******************************************************************************/( ~: T. _/ Z' g! e4 g. Y; Z
static volatile uint32_t TX_n;
static uint8_t *pbuf;. J6 _; h! I( u& \' p2 T
void EP2_IN_Callback(void)
{
uint32_t a;; h# Q. o+ u( D. n- Q* w
if(TX_n>0){
pbuf+=64;
if(TX_n>64){! e) N2 F8 o! z' d. _' T7 W
a=64;
TX_n-=64;- T" i3 B; \6 |4 _1 u6 {) q6 ~: A0 O n
}else{
a=TX_n;
TX_n=0;* e2 k' w* [5 `" r& }6 L
}
: ?$ u, S& G! [3 u1 u$ y2 K
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);2 @2 ^3 u% N% E1 D* s7 \! W
SetEPTxCount(ENDP2,a);) ?+ ]5 T; P% n$ `! y
SetEPTxValid(ENDP2);0 O9 C" v% R9 E0 I8 J& F
}else{# H& y0 g/ A/ }1 J
#if (SWO_STREAM != 0)% K9 L2 \& b4 D2 r- ~
SWO_TransferComplete();
#endif
}; Q: q4 ]% t0 P5 k
}
8 Z+ l1 b$ S+ d0 J. A' |7 x4 ^
/*******************************************************************************
* Function Name : EP1_IN_Callback.
* Description : EP1 IN Callback Routine.6 J9 }! T2 [2 \5 a% Q2 B2 h
* Input : None.6 |4 D L. S z9 f2 O1 Z) @, r
* Output : None.+ U3 @2 Q1 q u7 l3 W! ~
* Return : None.
*******************************************************************************/
void EP1_IN_Callback(void)
{$ X6 h" Q7 h' R
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]);# I! }, @5 [, }! a' k3 K- U- H
SetEPTxValid(ENDP1); 8 E' h0 i: |; ] Z9 u2 A
USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {2 ?% W" ^0 L4 [) _
USB_ResponseIndexO = 0U;. D% V; X% \9 T& Z& i- {3 ^
}! I) B+ a/ _' x- E. ?
USB_ResponseCountO++;
} else {
USB_ResponseIdle = 1U;
} 0 R/ a# b5 t' s& h' s
}
( i+ P$ k* u' B. i; M8 s) L# x
// Called during USBD_Initialize to initialize the USB HID class instance.
void DAP_FIFO_Init(void)6 {1 j+ e l* Y- l8 f1 u
{) @$ Q M+ c) g5 {" }
// Initialize variables
USB_RequestIndexI = 0U;
USB_RequestIndexO = 0U;2 M% H; t* b' T
USB_RequestCountI = 0U;
USB_RequestCountO = 0U;
USB_ResponseIndexI = 0U;
USB_ResponseIndexO = 0U;
USB_ResponseCountI = 0U;8 y# B5 d, @, u& Q1 b6 v
USB_ResponseCountO = 0U;' m. U8 t' a* `
USB_ResponseIdle = 1U;" U1 C+ }9 C. r( m, a
USB_EventFlags = 0U;' i- w5 F0 p; e& {; Q( h
}
! v/ N; \/ u( x# {3 x N
uint8_t DAP_Thread (void) {+ K t$ z) o5 n- f K$ v
uint32_t flags;
uint32_t n;
//for (;;) {2 w, D2 H% M) F6 {
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);0 ?5 m5 R2 D0 R+ ~& P5 s4 `0 I8 R
if((USB_EventFlags & 0x81) == 0)
{& r7 V6 g4 H- \
return 0;
}7 z: {" x0 q9 g) Q
USB_EventFlags &= (~0X81);( m$ y/ D7 g r! h9 s! o
9 r! }- w* h" Z( w
// Process pending requests$ n+ z5 L$ x1 G8 A8 C! c
while (USB_RequestCountI != USB_RequestCountO) {# `- Q: C* L G( U
//if (USB_RequestCountI != USB_RequestCountO) {( a6 j+ Y$ B, j
// Handle Queue Commands) W G% E: s2 Y
n = USB_RequestIndexO;
while (USB_Request[n][0] == ID_DAP_QueueCommands) {4 q0 ?; n9 t, q, s# ^& @
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {
USB_Request[n][0] = ID_DAP_ExecuteCommands;2 n9 V( N I" t( D) e b }6 Z
n++; |) {8 S1 X s9 O( G! M
if (n == DAP_PACKET_COUNT) {. z* S& c: @* n6 r9 p
n = 0U;8 k8 t) ~0 n' `2 v
}
if (n == USB_RequestIndexI) {" X. H1 g1 I9 n1 \) X
flags = USB_EventFlags;
if (flags & 0x80U) {9 P5 O" r& u: i1 x; q5 @
break;
}
}7 r w& ?4 z I/ |
}( f4 E! j$ u2 L2 c% ^' Y
// Execute DAP Command (process request and prepare response)
USB_RespSize[USB_ResponseIndexI] = Y7 q* a0 P) G0 G2 D$ _* Q1 F& k6 K
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);4 f2 J/ P! P0 i" V V" O
// Update Request Index and Count1 X- y0 s+ o- {% g7 i" Y3 S
USB_RequestIndexO++;& O1 s& x7 E" q2 P7 H6 g9 L* `
if (USB_RequestIndexO == DAP_PACKET_COUNT) {! b0 A- `6 y! y* j& J* E
USB_RequestIndexO = 0U;4 o3 V I8 n) p8 L( }3 M; n
}# ~2 M% j) b0 i H7 D! ]% @6 k0 B- I7 T
USB_RequestCountO++;
9 @, k% N, A# l4 `
if (USB_RequestIdle) {/ b! U. v) N$ _9 A' X
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {" e) a9 _# k4 v- d2 u' d
USB_RequestIdle = 0U;2 T: x/ ] o. d
SetEPRxStatus(ENDP1, EP_RX_VALID);
}4 P& `+ E t- z7 c
}! w+ _; h& U2 Y5 d9 R# f5 m
; \' t3 v n4 `' k+ ]; v F) y
// Update Response Index and Count
USB_ResponseIndexI++;, A! ^; L- z2 c
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {
USB_ResponseIndexI = 0U;6 I/ @ F2 U# z O
}" e' F! I0 s E& z' I
USB_ResponseCountI++;
if (USB_ResponseIdle) {
if (USB_ResponseCountI != USB_ResponseCountO) {! O4 D* b' @8 x
// Load data from response buffer to be sent back! t& A: v: u$ S0 J. p+ ?
n = USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {, K+ w6 M% B1 k# x
USB_ResponseIndexO = 0U;
}; k, p6 | K3 ^% Q* m) I7 q
USB_ResponseCountO++;( A9 N$ M0 y+ q. f
USB_ResponseIdle = 0U;
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);7 R$ l- t+ F/ ]. |
UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);$ ^$ J: |, E6 w( w& n% r( M
SetEPTxCount(ENDP1,USB_RespSize[n]);
SetEPTxValid(ENDP1);& h9 C, ?, n* l+ U3 V% {# Z- q
}
}; n# `* p: s4 Y- F
}
return 0;
}
2 u( V) v# c8 X& Y1 y
// 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;
$ o- t. t! D% e9 _1 C
if(num>64)
{
a=64; j2 |0 c& p: r, X
TX_n=num-64;( T* j& D( N% F4 Q% {7 B' g
pbuf=buf;2 Q, [3 L. ^: ?4 D! K, M; `
}else {
a=num;$ R* Y: A1 y" {0 n
TX_n=0;
} ~ `; C, Q. b* G3 [& t
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);: n; |& ]7 S# a% n/ x! i
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);
}7 k) U1 x" p; W3 e( J- g5 n) Z
// SWO Data Abort Transfer$ M( U' o+ f+ @- A. t2 P# i# s, a
void SWO_AbortTransfer (void) {
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));" V# D. {9 @; a- P- ^
//SetEPTxStatus(ENDP2, EP_TX_NAK);" \. W2 h: I% O3 T$ U% W. d
SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxCount(ENDP2,0);
//TX_n=0;
}. A* g: N6 B1 i* [ G1 i9 n
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
% k8 T/ r9 }* z+ f! L
移植大概是这样的,利用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里面没声明这个寄存器,只得自己定义一下了/ R! n* r ^+ k
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {: a+ a. S; Z* Y6 S! \: p1 e
return (DWT->CYCCNT);9 D# b2 e N. X/ ~: u6 h8 {
}
8 W0 }" X5 \/ L
void DWT_Init(void)4 h$ {) p6 q6 j% s
{- [# g$ _" s7 u: e+ h L
/* 使能DWT外设 */- t% T! w& V' v
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
, H+ q+ O# u9 h/ l: R! \1 u
/* DWT CYCCNT寄存器计数清0 */: G5 f% N& s0 ?
DWT->CYCCNT = (uint32_t)0u;% Z0 a# n( ~0 U8 N
/* 使能Cortex-M DWT CYCCNT寄存器 */1 t/ ~/ D3 R8 e1 t2 E4 r% ^- Q' `
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 频率: z/ f/ Z; E3 ~- K ?6 a; d
8 q1 j# Y9 _1 O# F9 T. x" P
然后改为使用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;( l0 o1 T/ \2 B/ ^
在SWO里每一处调用osThreadFlagsSet的地方都改为如:0 V4 _7 J! _2 ]5 ^1 g
//osThreadFlagsSet(SWO_ThreadId, 1U);
SWO_EventFlags = 1U;0 O& k+ G- {) E/ _% p7 w$ n
8 b, t6 H, B1 c/ f4 D* I) x
// SWO Thread
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;
uint32_t flags;1 G D$ [0 w( k( R% H% O
uint32_t count;
uint32_t index;# g2 p1 M- Y: p9 l
uint32_t i, n;
//(void) argument;6 D7 N N M. A2 z6 `+ D$ a
//timeout = osWaitForever;) g5 D3 P5 G `, m1 O& L! i
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);, R- U. H: c4 F; X: q1 V" X+ z# G
if((SWO_EventFlags & 0x01)==0)return 0;2 s- y! L. m; s' L
9 ^' ]( y$ L. w5 O6 U& D. j# B. X( t
flags = SWO_EventFlags;
SWO_EventFlags = 0U; - o( L$ T5 @9 q) s3 T8 F, j& R, C* g
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {5 r8 f. [- B; H; c1 ~, o
//timeout = SWO_STREAM_TIMEOUT; 这里是对于进入了SWO_CAPTURE_ACTIVE状态时就把线程超时设置为50毫秒,大概意思应该是osThreadFlagsWait到达这个超时时间后,不管标志是否切换为1U,都放行SWO_Thread调用一次,timeout = osWaitForever时相当于无限长的超时等待1U标志,对RTX不熟悉,不知道是不是这样子) T5 M8 m; G( _3 X9 n& A
; P: l) l' c ~% e m/ u
} else {
//timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}; w( Z7 y+ G5 P( \" N
if (TransferBusy == 0U) {
count = GetTraceCount(); G4 L9 J+ h. ?
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;9 @+ i% ], M, O( F% ?
9 D8 s+ G; @' t" z5 R
}! A; ^) P9 S7 \9 {) S) j; K V0 J
if(count>USB_BLOCK_SIZE). `% T$ n3 I8 J% }
count=USB_BLOCK_SIZE;
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {$ ]& p2 H3 J4 V# I/ A
count &= ~(USB_BLOCK_SIZE - 1U);9 O0 g. {) h! G! n: m- C( f; n
} else {
n = USB_BLOCK_SIZE - i;& |6 m8 M* U" X8 P8 o
if (count >= n) {0 W3 ?% @9 J( e9 \# B! W, V( t
count = n;& C, D% V5 x& u' b* B
} else {
count = 0U;2 ^& c7 p8 U. K* W% V9 D; L
}" P; ?! E3 E- T: A1 P5 j
}
}
if (count != 0U) {
TransferSize = count;+ d, h- Z! @( [( ]9 {
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);
}
}
}
//}
return 0;
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).5 \; s2 v* K4 ^) w# n
static volatile uint32_t SWO_EventFlags=0;+ ^0 j& a" M; i* R
static volatile uint32_t timeout=osWaitForever;" B* K" t; `7 M2 o$ ^! ?* |" Q3 A+ U
static volatile uint32_t timeWait;
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {2 q% w$ w4 a$ B3 i7 f7 c9 V5 i- X' r
//uint32_t timeout;
uint32_t flags;2 h8 ]+ T5 |4 ?9 ~- I
uint32_t count;; m; U8 j5 ?, _5 f
uint32_t index;7 y$ S; A% P, |1 l& w
uint32_t i, n;
//(void) argument;5 k# f" [3 o8 @! ]2 Y! z" x5 n/ i) g
j" ~( r1 H4 P4 A5 Y6 K
//timeout = osWaitForever;
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);' b2 T; m% p A$ Z0 f% S: A6 r
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;2 A, V6 l+ O, F& B4 ?
; R$ f U* N/ F1 ^( a) ?) G. B
}
flags = SWO_EventFlags;
SWO_EventFlags = 0U; 5 D( W. M( Z/ d4 _* E- O' I6 x0 l) S
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
timeout = SWO_STREAM_TIMEOUT;
timeWait=DWT->CYCCNT;
} else {/ ]! m& Z! N) Q; @: W& ]
timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}
if (TransferBusy == 0U) {
count = GetTraceCount();1 P/ H6 D9 Z. M0 ]* o
if (count != 0U) {" H/ W) L4 b& N5 z% U. l& U- ]; m
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U); ~% d" Z: y* |' N
n = SWO_BUFFER_SIZE - index;
if (count > n) {) T8 e+ K& p0 C- ]
count = n;4 k% x% S/ J+ r2 W, U
}
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;
if (flags != osFlagsErrorTimeout) {0 p9 ^ {/ U+ R( x, o5 m" T2 b7 `# I
i = index & (USB_BLOCK_SIZE - 1U);; |: {9 [" _9 L9 o9 T$ L3 z
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);6 j3 I, e+ B0 O5 I7 Q2 l: v
} else {
n = USB_BLOCK_SIZE - i;
if (count >= n) {9 `& I9 K3 x0 [' b4 @
count = n;/ O8 m+ n+ D. [( ?
} else {$ f1 L/ C1 W$ K" m9 L* z
count = 0U;7 b E, ^' ~, G2 E
}
}
}6 c$ q1 m+ H# w6 m9 {& p
if (count != 0U) {3 R* ~8 t8 n: J: S: @, ^
TransferSize = count;* r& d& ?, ^5 ^7 J5 f! `
TransferBusy = 1U;. ?5 F( u, o# |3 D, t1 s1 j
SWO_QueueTransfer(&TraceBuf[index], count);
}
}
}) w- N( i+ Z# _, R: [
//}
return 0;9 N" e2 Q2 }" C. ]/ E. G
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了! o% {3 e9 A: o- f, G' I
1 m7 f( Q+ x% X: H6 `
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)7 k6 ]% q( H5 w' N4 e7 x$ s4 p
{
DWT_Init();5 @/ r& c, V# ^ T( o
DAP_Setup();
USB_Interrupts_Config();
Set_USBClock();
USB_Init();
//TIM3_Init(35999,0);
//TIM_Cmd(TIM3,ENABLE);
# _% }) h0 [% }) D
while (1). P" G3 Y( h5 i) T' j
{* R" {! q- S) ~( e% k7 Q9 ?+ {
DAP_Thread();
#if (SWO_STREAM != 0)
SWO_Thread();
#endif; t7 ^/ `7 } b- {/ B
}
}- x# w" H8 m& \/ @, v
6 G" t3 o/ r3 L. x
对于DAP_config.h的IO配置我是这样弄的. G4 f% f# g; G) B0 ?
///@}7 U2 T7 y0 F% }2 K2 V% h
// Debug Port I/O Pins
4 A O* E% B5 ]+ D
// SWCLK/TCK Pin GPIOA[6]/ e) K H5 Q( s, U6 L
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198* }4 [4 v2 C0 \ n% C' x$ \3 v
#define SWCLK_TCK_IN *( uint32_t*)0x42210118! p3 T( ?# A/ E+ E6 G: K' A) N
# x7 V2 q1 w Y7 p# T1 L6 |
// SWDIO/TMS Pin GPIOA[7]
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C
x) @4 s7 `1 x( O' k
// SWDIO Output Enable Pin GPIOA[7]
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 1; \9 w% _' ^! |& m% }$ Z5 Z
*(uint32_t*)0x42210074 = 1; \
*(uint32_t*)0x42210078 = 0; \
*(uint32_t*)0x4221007C = 0;}
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 0; \' e2 W5 {1 ^, D* R; ~. V! u6 R$ X
*(uint32_t*)0x42210074 = 0; \ o( Y4 j& \! ?4 F- @
*(uint32_t*)0x42210078 = 0; \! D& _9 [* x( ]9 Y+ z
*(uint32_t*)0x4221007C = 1; }
6 |! C2 z9 r% Y; r; k
// TDI Pin GPIOA[8]
#define TDI_OUT *(volatile uint32_t*)0x422101A0
#define TDI_IN *(volatile uint32_t*)0x42210120; a% V( x% o p: K) J' n( l
// TDO Pin GPIOA[10]
#define TDO_OUT *(volatile uint32_t*)0x422101A89 F( e }! X2 O ~
#define TDO_IN *(volatile uint32_t*)0x42210128
// nTRST Pin GPIOB[3]2 h: A6 c* S/ B; H9 W$ V
#define nTRST_OUT *(volatile uint32_t*)0x4221818C
#define nTRST_IN *(volatile uint32_t*)0x4221010C. E* p( A% @3 S" a) ?7 z. _& Y
// nRESET Pin GPIOB[4]
#define nRESET_OUT *(volatile uint32_t*)0x42218190& B! M- X( f7 ]" o) R
#define nRESET_IN *(volatile uint32_t*)0x42218110
/ L4 ]1 h) u% T2 }0 g
// nRESET Output Enable Pin GPIOB[4]1 v8 p2 F9 N( j* }9 h8 U( x
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 1; \/ n1 \1 Q# O3 y* c1 r- N9 _. q
*(uint32_t*)0x42218044 = 1; \0 h4 y; h% z9 V% C# `/ Z
*(uint32_t*)0x42218048 = 0; \& Q2 j3 ]4 F) \: r6 C
*(uint32_t*)0x4221804C = 0; }
' ^9 }; C* w$ _* S) N# Q/ J
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 0; \4 M2 X* k& f. Y5 U# L" \: v& ^
*(uint32_t*)0x42218044 = 0; \, [ @- ?& Q( }. B, c: r
*(uint32_t*)0x42218048 = 0;\/ A* [ Z; d# Q# D! r# K
*(uint32_t*)0x4221804C = 1; }$ ~2 y0 m$ ^+ O( g4 P
! _0 Y* L3 B! S4 c, s1 U0 U3 u6 g
// Debug Unit LEDs
( w" o) m" ^% ^
// Connected LED GPIOC[13]
#define LED_OUT *(volatile uint32_t*)0x422201B4
#define LED_IN *(volatile uint32_t*)0x42220134 p# t' F& A/ |6 w' G3 T/ e) A2 M4 `
' U9 n( ^( q1 x: U, X9 w
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \7 o) k, l |5 K( ~) n
*(uint32_t*)0x422200D0 = 0; \
*(uint32_t*)0x422200D4 = 0; \7 x4 c8 k- [/ _$ r9 O6 {3 M
*(uint32_t*)0x422200D8 = 0; \
*(uint32_t*)0x422200DC = 1; }( _' R0 t3 B0 k
// Target Running LED Not available
* t- Z- A5 t4 s; m" f
// SWCLK/TCK I/O pin -------------------------------------! D7 X% ]) t- M. n8 V
/** SWCLK/TCK I/O pin: Get Input.0 E( s! \0 c8 W1 @6 Q+ \
\return Current status of the SWCLK/TCK DAP hardware I/O pin." }0 Z. i" U3 D" u
*/
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {: C% {* R. W4 G6 h
return (SWCLK_TCK_IN);
}2 M6 t# @ X. F x% G! W
/** SWCLK/TCK I/O pin: Set Output to High., q: Q, _6 r. w) O. I
Set the SWCLK/TCK DAP hardware I/O pin to high level.% Q5 w" ^ o5 L4 m" X
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {+ H9 s6 N! K c( g' u- G
SWCLK_TCK_OUT = 1;
}2 q; ~+ n4 Y' }" R6 r
/ \* p) R9 B: ^& H
/** SWCLK/TCK I/O pin: Set Output to Low.8 j1 Y5 Q$ w U$ k1 j" g- W
Set the SWCLK/TCK DAP hardware I/O pin to low level.1 P Y" }0 p: X& [' [
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
SWCLK_TCK_OUT = 0;1 Q# H8 w3 T7 ?9 v6 C5 A
}
; Z- ~& m+ Z! e4 ?
// SWDIO/TMS Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input.5 b; r. U+ z& c" o" O( Z& B1 p
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {) G. ~ \2 S2 o$ M. b, X
return (SWDIO_TMS_IN);
}
h$ {$ S4 ^( f; [) c
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.: t5 E; X$ ~1 ^: F& N8 Y% y4 ~
*/) V1 l; K1 n( O6 O, s
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {
SWDIO_TMS_OUT = 1;9 H" C# S' [- r+ l$ s+ e. `
}" v) k" Z8 v8 |- u' ~
3 X! g8 l. W( \7 ~6 M2 B
/** 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;( p9 G8 M5 U1 R* B) u- Y) k" J
}0 _/ I w" o$ }8 ^3 T
0 o) o4 U: h( [ v1 X
/** SWDIO I/O pin: Get Input (used in SWD mode only).' z1 |4 k, H0 N1 s# g8 d
\return Current status of the SWDIO DAP hardware I/O pin.
*/5 K! R4 @% \* K. o# s
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return (SWDIO_TMS_IN);5 W* p+ H& H; O
}1 S0 m9 J3 e& Q
/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin.3 a9 Q: s$ k1 ?8 i/ v9 P8 ~& d5 P6 N# c
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {, E: f* R0 X. u S
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." v" e5 a9 [, k7 b/ P9 U
*/& h+ v% r: ?! @; \, b* c
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {3 G/ V% @! k5 d; _# H
SWDIO_Output();; r5 E. b, o# I+ }/ x2 O
}
3 F' n* k; V% T4 [4 }% I
/** 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) R8 \; K( \ o* H
called prior \ref PIN_SWDIO_IN function calls.3 [# f- ^: r$ Z( b9 d7 z" {6 E
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
SWDIO_Input();
}, y$ l9 y4 A5 @/ C3 [
楼上有的说弄无线,其实无线也就是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驱动的大佬可以尝试一下- T5 }5 x1 a w+ `: {
有人将这个工程移植到stm32f4上吗,我在网上找了一个f4的dap工程,但是编译下载后无法使用。