你的浏览器版本过低,可能导致网站不能正常访问!为了你能正常使用网站功能,请使用这些浏览器。
ricklou 发表于 2021-1-25 10:50 / c6 g# ?: Q7 q' E除了mdk和iar能自动复位,其软件他都不行(iar for 8051、keil uv4、keil c166、jltool3、nfc tool、arduin ...
ricklou 发表于 2021-1-27 23:00 ! D7 J T; C8 K7 @& U可以把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发出复位命令。8 [" U* C `; ?: A
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。* H( ~! Z8 h% Z3 J4 s) b' y
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。& ~1 l( `! @5 {
" {1 O: d( N( l- u
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。 * O) C" t3 r7 Z7 N( ` |- e2 @
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。
# v# I, O4 u( u
! ~' R2 @. i* R5 E! C4 V6 D
/**
******************************************************************************% O3 ] @ B8 R8 _4 E5 l% O
* @file usb_endp.c
* @author MCD Application Team
* @version V4.1.0
* @date 26-May-2017
* @brief Endpoint routines }. f" m* A* o) M0 S$ C
******************************************************************************1 g3 {4 `7 i5 D1 r3 A! t. _
* @attention
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>: K$ c1 K9 \: q
*8 d& ~& Y. \. @: \/ F9 L7 Y: j6 E) X
* Redistribution and use in source and binary forms, with or without modification,* W8 L4 V+ W# t' D- {
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,7 M) X5 N3 `+ }8 V0 r, w# c2 A
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,2 g8 J/ K. P9 F" V
* this list of conditions and the following disclaimer in the documentation' x. P' z. T) p5 L% `" R0 o8 w
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors, D5 o2 k; i' E' C
* may be used to endorse or promote products derived from this software
* without specific prior written permission. _ N+ a$ P5 x! B
*8 ^- Q: q# c' _. }2 m" R7 g; G
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"& D/ V1 k' e' `' P+ P7 V5 u
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE( [+ L$ i" Q0 T0 M& p* \2 @6 j6 \* g
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE' N/ {. H+ ~1 ~5 j& P) t ^0 x
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL3 d; |( u6 E! _ p1 }8 P
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER, {( i/ i# B! }" I8 ~; q8 S
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,9 ]1 W* V' }7 b9 i* K
* 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.
*
******************************************************************************
*/. z! D. P; b. S+ O- r% n
/* Includes ------------------------------------------------------------------*/4 a1 E8 u- }+ O/ z$ D2 N
#include "hw_config.h"
#include "usb_lib.h"
#include "usb_istr.h"8 I) P6 U6 r2 S4 Q; {4 k0 T
#include "stepper.h"
#include "string.h"7 }0 k8 a8 i1 O v
#include "DAP_config.h" y# i5 q6 _9 }" i9 m3 k
#include "DAP.h"
& i" a. ^9 c( i) r; K
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static volatile uint16_t USB_RequestIndexI; // Request Index In& \" P$ V; K7 p; Q, t7 p
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' R8 e/ Y! G2 c- W5 h0 r/ O
static volatile uint8_t USB_RequestIdle; // Request Idle Flag
static volatile uint16_t USB_ResponseIndexI; // Response Index In+ H7 Q( n: E$ Z& b
static volatile uint16_t USB_ResponseIndexO; // Response Index Out8 S* S% t6 J& q9 \ U4 Z5 g4 [( l
static volatile uint16_t USB_ResponseCountI; // Response Count In" R) d8 D" V& |- Z4 n* i# |4 l
static volatile uint16_t USB_ResponseCountO; // Response Count Out
static volatile uint8_t USB_ResponseIdle; // Response Idle Flag" I( Y) Y& e, Q4 g6 O# U- C
static volatile uint32_t USB_EventFlags;
static uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Request Buffer3 k* t5 Q; n B) F$ I
static uint8_t USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Response Buffer8 \% g9 L- @, J0 I3 Z, i
static uint16_t USB_RespSize[DAP_PACKET_COUNT];
/* Private function prototypes -----------------------------------------------*/( a6 y2 c. g9 x8 A) K' s/ X
/* Private functions ---------------------------------------------------------*/. N# D% C7 _; ^7 e2 Y. _
/*******************************************************************************
* Function Name : EP1_OUT_Callback.
* Description : EP1 OUT Callback Routine.0 w- j$ T& ~& @' M
* Input : None.5 f6 T5 d- q Q- U) C; E( A
* Output : None.; t: z0 j2 Y7 P6 F# ~+ m
* Return : None.$ D8 Z# P+ c" R2 P C! d
*******************************************************************************/
void EP1_OUT_Callback(void)
{. X5 s m: H$ m' e! t
uint16_t n;, A8 i' V( u- T- S c5 e+ O: l+ z
n = GetEPRxCount(ENDP1);# D8 X3 J5 T" W- k& q
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);
if(n !=0){6 ]1 b2 I6 ]4 _+ I W9 U, D c+ m
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {) W+ g; c3 V: j* c' y7 {
DAP_TransferAbort = 1U;
} else {, y) u+ J( m& U& y- Z
USB_RequestIndexI++;
if (USB_RequestIndexI == DAP_PACKET_COUNT) {# p2 o+ I: Q9 [. D6 k
USB_RequestIndexI = 0U;
}) q( n% h& y9 ~" f
USB_RequestCountI++;+ H& f% }3 n, {! x" C
USB_EventFlags = 0x01;
}
} + X7 j. a; w: N$ `4 t! S# G
// Start reception of next request packet
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
SetEPRxStatus(ENDP1, EP_RX_VALID);) E% }% ]' l: U' k. ^) c
} else {
USB_RequestIdle = 1U; `& `3 ?( f6 T9 T+ u2 }. p/ q
} 9 e& L7 {$ d M6 B
}
/*******************************************************************************
* Function Name : EP2_OUT_Callback.
* Description : EP2 OUT Callback Routine.2 ]) d) P6 m% T R0 ^
* Input : None.% E$ l# k' R/ K: M
* Output : None.1 F% t! ?, s3 i" C
* Return : None.
*******************************************************************************/5 }& ^$ f6 Z/ L9 u
static volatile uint32_t TX_n;
static uint8_t *pbuf;
void EP2_IN_Callback(void)
{
uint32_t a;3 ~8 x w) Y' D8 w% f
if(TX_n>0){* f7 e6 _. e% r$ @% c8 T
pbuf+=64;$ x8 [& ?" O6 [0 B( S9 v7 }& [
if(TX_n>64){3 H. j. @7 |; q$ q
a=64;
TX_n-=64;
' e8 z: J* z5 q
}else{0 l7 P/ o% a) j* i
a=TX_n;
TX_n=0;; v [ M) J- u
}
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);6 c$ F- T. y3 q H0 \' E& W
SetEPTxCount(ENDP2,a);
8 y! }/ B! _4 m1 R
SetEPTxValid(ENDP2);
}else{% D8 T( n! k" v- L" e& V
#if (SWO_STREAM != 0)/ N7 [ d* p+ R9 S0 I
SWO_TransferComplete();
#endif
}
}; U5 o5 U3 G4 m/ G" M A
% q* @: U: c6 C( _" ]8 W8 {, h) N( O
/*******************************************************************************0 g/ T/ }* H6 d
* Function Name : EP1_IN_Callback.
* Description : EP1 IN Callback Routine.0 ? C3 R2 p$ X5 j& u
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void EP1_IN_Callback(void)6 u/ A, H/ U% z2 P; U' u
{' e2 R7 T9 e- i; D% K- g
if (USB_ResponseCountI != USB_ResponseCountO) {9 T( M& F' b) Z# t8 E+ c/ C4 X
// Load data from response buffer to be sent back9 @' I3 Y6 x- s
UserToPMABufferCopy(USB_Response[USB_ResponseIndexO],ENDP1_TXADDR,USB_RespSize[USB_ResponseIndexO]);
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);
SetEPTxValid(ENDP1);
USB_ResponseIndexO++;; t) v {& m t
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;* a; E9 r* s+ X2 X0 D
}1 n5 a9 U! ?2 G% O
USB_ResponseCountO++;
} else {
USB_ResponseIdle = 1U;
}
}
$ S; a( J1 ?2 N7 c5 N+ C$ g
// Called during USBD_Initialize to initialize the USB HID class instance.: l6 ?( z% [, ?7 I, m2 E
void DAP_FIFO_Init(void)
{" p. n% h0 m+ q) {$ Q
// Initialize variables
USB_RequestIndexI = 0U; ]. j2 \0 }+ O2 S9 D5 W
USB_RequestIndexO = 0U;
USB_RequestCountI = 0U;
USB_RequestCountO = 0U;
USB_ResponseIndexI = 0U;- C, H+ Q# m2 ^& [5 w
USB_ResponseIndexO = 0U;- H7 ]/ A, s- Q
USB_ResponseCountI = 0U;
USB_ResponseCountO = 0U;
USB_ResponseIdle = 1U;
USB_EventFlags = 0U;
}8 F; |2 P$ g& j1 e- Q0 K
uint8_t DAP_Thread (void) {
uint32_t flags;
uint32_t n; U* \" ^# ^) |/ U8 |7 I, j1 g3 [
3 J/ W- Q* ~/ K% q- _9 B8 H8 ^& B$ b1 |
//for (;;) {' C% W u F7 H: z
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);# O! T& ^7 K6 k
if((USB_EventFlags & 0x81) == 0)
{
return 0;
}2 b, R) l) l1 C8 Y9 ?2 g, T+ H) w
USB_EventFlags &= (~0X81);
// Process pending requests' f" w- a4 i' k$ _
while (USB_RequestCountI != USB_RequestCountO) {
//if (USB_RequestCountI != USB_RequestCountO) {# b2 h- |/ Q- R
// Handle Queue Commands1 h* w/ e2 C1 q+ ~% y+ K4 h
n = USB_RequestIndexO;' ]/ [: ~! c! W, ^- ?
while (USB_Request[n][0] == ID_DAP_QueueCommands) {# f) D/ Y) ^6 x6 a6 w
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {) a6 ]$ I' o- p
USB_Request[n][0] = ID_DAP_ExecuteCommands;
n++;- T' P C: Q# e; }+ e
if (n == DAP_PACKET_COUNT) {) q1 q k6 i' A! L8 u
n = 0U;- i) e P5 B ^( h( W! R' {, ?
}+ u/ B, q8 l* U. _3 _2 m: v) {6 \
if (n == USB_RequestIndexI) {7 b7 U5 F2 _, n4 V. j
flags = USB_EventFlags;$ b/ y) t2 {; ^ F% z; l
if (flags & 0x80U) {
break;& F; A, m! [% J* `9 u# S
}
}
}" T& B+ C2 b# L( [) _9 k! o& C
: a. R& v; ~! y* `. P. h
// Execute DAP Command (process request and prepare response)9 W; c$ j+ B! m
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;
}, m# P. y3 _5 ^1 z& c! m2 N* U! c
USB_RequestCountO++;
6 K9 R9 d% c7 f6 R0 Q7 }8 j
if (USB_RequestIdle) {
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
USB_RequestIdle = 0U;* `, t4 n" U2 p, X T5 b
SetEPRxStatus(ENDP1, EP_RX_VALID);+ m) j6 W( H1 B8 M
}9 }: F* L8 D2 U+ p4 o, j( {
}
3 d' b/ i+ B. d6 f
// Update Response Index and Count
USB_ResponseIndexI++;
if (USB_ResponseIndexI == DAP_PACKET_COUNT) { J! i R5 _; B$ f% m
USB_ResponseIndexI = 0U;
}, L/ k+ {3 n- s7 [
USB_ResponseCountI++;
5 m4 s- ?0 ^$ x3 U8 ~
if (USB_ResponseIdle) {& [1 L6 P; U, J- S
if (USB_ResponseCountI != USB_ResponseCountO) {$ P0 L ^4 t+ A
// Load data from response buffer to be sent back# F p" _2 i: B7 l; @
n = USB_ResponseIndexO++;+ i2 U4 W: ]1 t& m
if (USB_ResponseIndexO == DAP_PACKET_COUNT) { C( h9 n* \( c9 e: Q" c0 e
USB_ResponseIndexO = 0U;
}
USB_ResponseCountO++;
USB_ResponseIdle = 0U;
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);: v( l( \7 w, @- C, |
UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);
SetEPTxCount(ENDP1,USB_RespSize[n]);
SetEPTxValid(ENDP1);3 ?$ O) r0 \# j. z
}3 D5 e5 c: ?7 x5 C5 z# _
}
}* Q a# f$ O" v9 ?& u+ x# x
return 0;( F# L% |# |, O# P/ L
}
- k1 \( w. H, `& n a: [% a* \2 K% L
// SWO Data Queue Transfer
// buf: pointer to buffer with data# P" |# p O* N$ q E& y' y2 r
// num: number of bytes to transfer9 g2 \1 U5 f. y# u9 X
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);
uint32_t a;
if(num>64)) L. P- M7 P" V
{1 q) {- p) J! e0 X% l! \
a=64;
TX_n=num-64;7 A! y; _% u6 J3 a9 R8 v
pbuf=buf;
4 ?- R) d; g, R' F
}else {
a=num;1 r4 d4 {: U% |# O5 S6 P
TX_n=0;
}5 Y# N/ I; ^0 `# P% j1 [$ D
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);, K: |+ @ O f
} ^$ u5 B+ e# m( i: Y s# U/ `
& T+ f# l! n# {( V
// SWO Data Abort Transfer5 [/ v( i# i2 y$ u' O5 _- ]
void SWO_AbortTransfer (void) {4 U/ e0 `3 n1 X; a% v) i
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));* k) b6 ^1 I) q" s6 J3 Q
//SetEPTxStatus(ENDP2, EP_TX_NAK);! r, r: ?; Y# P4 B, a. r& M( G, E
SetEPTxStatus(ENDP2, EP_TX_DIS);+ C: J% Q, a; E9 C4 \& I1 q
SetEPTxCount(ENDP2,0);
//TX_n=0;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/' }$ Q0 ^& R8 d# q5 z) L
! G1 {0 v$ r. U1 K3 C$ |
移植大概是这样的,利用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里面没声明这个寄存器,只得自己定义一下了8 G$ g4 _; J. H4 F( f( U+ J" _
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {- g* d7 l2 H, q( K+ b! v9 G: J
return (DWT->CYCCNT);
}
void DWT_Init(void)' Z% N f Y6 Z* X3 S( z, K
{
/* 使能DWT外设 */$ C2 ?$ g6 i1 n) V1 b0 j
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; & j/ ^8 q9 z0 n- j0 ^ Z0 w5 Z
/* DWT CYCCNT寄存器计数清0 */4 y* S) Z `+ P% `. G3 r3 W
DWT->CYCCNT = (uint32_t)0u;# a) m$ w K- A" Y* r7 U3 w
/* 使能Cortex-M DWT CYCCNT寄存器 */; { m8 a8 _0 H
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;, ~+ l$ `2 G: a" H. y; z
}; I% Y7 g Q) p7 {3 Q2 \
然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率
) f8 V- r1 s4 y9 z3 U
然后改为使用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不香么?& p, c; a0 {( b
声明这个变量static volatile uint32_t SWO_EventFlags=0;
在SWO里每一处调用osThreadFlagsSet的地方都改为如:0 a, S$ v+ c$ L( e& @% ], Z: s
//osThreadFlagsSet(SWO_ThreadId, 1U);3 m7 `: t9 A4 m
SWO_EventFlags = 1U;
: A/ k- ~! @. ~2 N p0 ^) O/ x
// SWO Thread$ o E( E' _1 [# Y! L
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;7 _8 r, z$ {# @
uint32_t flags;
uint32_t count;3 `4 t# _% T$ J1 @0 j# O
uint32_t index;) y' j' \0 v5 x, N! @ ~
uint32_t i, n;
//(void) argument;8 Q4 J5 _# c8 {
//timeout = osWaitForever; b" w6 c) e% J1 R
, p6 A3 y( T; ?6 J0 i( ~
//for (;;) {* N* T/ h; I4 w- X
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);4 _ K0 d9 Y) i* B1 w
if((SWO_EventFlags & 0x01)==0)return 0;
* c& @' L* H& k4 s) q- X" V2 b; ]
flags = SWO_EventFlags;
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {: x* }, h0 W/ s0 R$ q" Q2 P0 S
//timeout = SWO_STREAM_TIMEOUT; 这里是对于进入了SWO_CAPTURE_ACTIVE状态时就把线程超时设置为50毫秒,大概意思应该是osThreadFlagsWait到达这个超时时间后,不管标志是否切换为1U,都放行SWO_Thread调用一次,timeout = osWaitForever时相当于无限长的超时等待1U标志,对RTX不熟悉,不知道是不是这样子$ [8 ~# @* y: M
;
} else {2 p; z$ C/ l7 M G/ v! W$ R3 ?2 \
//timeout = osWaitForever;$ W$ X% x+ i) G) R; c
flags = osFlagsErrorTimeout;. Q2 q7 [' }$ i1 I+ j
}
if (TransferBusy == 0U) {
count = GetTraceCount();3 u0 j8 G# `8 x
if (count != 0U) {% H( [7 ^6 R$ p, `
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);! [# ^& h% P/ ^6 M( T
n = SWO_BUFFER_SIZE - index;' a1 I6 ^+ d" u: O( t) T. A
if (count > n) {
count = n;" `! u. N4 {( [% I F2 ]
}
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;) a* Q& {4 S; w. t3 q) E
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;9 B% S* q* c& z# A4 R" \
if (count >= n) {
count = n;
} else {* j K; {9 b( R( U: p
count = 0U;
}9 E& s/ w! b, \4 ]
}
}
if (count != 0U) {
TransferSize = count;5 k- F X5 @1 b6 A. F7 O
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);
}; ]( _6 G7 J( b! z# v8 N8 C
}
}2 L# `4 A) \- u: R+ `4 y2 S! s
//}
return 0;
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.2 U# P) d+ h; i, Z$ n4 j
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
static volatile uint32_t SWO_EventFlags=0;! b, D# ^) T+ S$ x+ h/ |
static volatile uint32_t timeout=osWaitForever;! D! l; _. x& P! X: l" L/ m/ `
static volatile uint32_t timeWait;
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;5 V' x' c2 {5 `4 i
uint32_t flags;0 h* o+ i' C* w* N$ c
uint32_t count;
uint32_t index;# |& B9 S# X- v1 p1 g
uint32_t i, n;0 _8 K) n/ g! i! N* u- A& u7 {
//(void) argument;# i r& f2 s c' c7 S) r# g4 ^
' Z. p5 v0 L9 _# g, U
//timeout = osWaitForever;
' M! i# f# ?+ z5 d1 O2 v
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if((SWO_EventFlags & 0x01)==0)) \5 P u: P* A
{" w' S" M( t- \+ k) \
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了
return 0;( o. Z5 |7 F- k5 x) w. A
}% E- U( \4 ?/ ~- L3 I) g7 B
) l+ Y& C* ?# o e5 J
flags = SWO_EventFlags;
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
timeout = SWO_STREAM_TIMEOUT;
timeWait=DWT->CYCCNT;
} else {
timeout = osWaitForever;; k. [, b! i" ~3 j# c c1 m
flags = osFlagsErrorTimeout;' Q3 W2 p4 @7 @* ~2 J
}5 \" H, q' d! G. W `7 Q/ j
if (TransferBusy == 0U) {+ j! G( v, q1 [# g/ x* b. V" v) x
count = GetTraceCount();. u: T: T: _ P" _
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;
}" K( W0 O/ ~7 r- p, J6 M3 {4 ^7 t* }
if(count>USB_BLOCK_SIZE)4 j1 V7 W# T2 ?/ b0 G
count=USB_BLOCK_SIZE;
if (flags != osFlagsErrorTimeout) {8 c E- H5 s {" p' M
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);
} else {" L3 q" n8 c/ L g! o* A3 n
n = USB_BLOCK_SIZE - i;" E: B5 Y8 Y0 c* `- F& R
if (count >= n) {% Q- E1 }" ]" i. E
count = n;& u3 w" B3 m0 z
} else {: \8 W4 r& q0 F c
count = 0U;
}
}* `3 t, r/ m# L
}
if (count != 0U) {# h, G! w. v' _- X
TransferSize = count;
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);
}
}
}& O- s/ L1 P M
//}
return 0;, l' P7 E3 D( ?1 u
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了# a- H- v3 h% u: B. z
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,少了这个等待时间,能增加端点的传输速率/ D4 z4 P4 t) u
4 n- ]8 C! t7 _5 Q/ B% V
% a# y& Z- M+ Z5 A3 V
int main(void)8 _3 }. h$ a( v& y
{
DWT_Init();
DAP_Setup();
USB_Interrupts_Config();
Set_USBClock(); ]$ }) m% a+ w0 @$ U6 a2 @
USB_Init();& E) T2 W: n" L/ m6 E
//TIM3_Init(35999,0);% ]. U& w% }# c& X/ b
//TIM_Cmd(TIM3,ENABLE);
5 m4 F/ s; @! E) M* R
while (1)( V2 G# ?* H( i7 s
{
DAP_Thread();
#if (SWO_STREAM != 0)
SWO_Thread();
#endif5 p1 e) Q8 G+ N1 g0 l
}( E# D: W+ t9 t- L1 L3 l! z
}
7 @( ~$ ?( \ I
对于DAP_config.h的IO配置我是这样弄的. H) ?+ j; n2 l3 m: K7 T$ S# P
///@}2 s, m$ a* K2 E4 i- m& q- S
// Debug Port I/O Pins
// SWCLK/TCK Pin GPIOA[6]" }$ y% c3 M% b3 k: w! a& ~
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198
#define SWCLK_TCK_IN *( uint32_t*)0x42210118
0 m; a6 b( ?: T' k
// SWDIO/TMS Pin GPIOA[7]0 p4 ^( o: h7 }$ b" S! @( a. I6 |
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C# r9 Q: Q/ M( ]( {5 K8 T% w9 c
// SWDIO Output Enable Pin GPIOA[7]& i! ^+ J: p: O
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \3 [2 _! [) g! c; s2 k( V* a
*(uint32_t*)0x42210070 = 1; \
*(uint32_t*)0x42210074 = 1; \- g: Y5 A) w: J
*(uint32_t*)0x42210078 = 0; \+ J6 D! ^ U- ]( [4 i6 c9 E4 \
*(uint32_t*)0x4221007C = 0;} p+ X1 z/ T9 I% f8 f
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \; O7 x K9 y) ]: H9 f
*(uint32_t*)0x42210070 = 0; \' i5 B7 _* u9 O4 P2 B9 x V3 U a
*(uint32_t*)0x42210074 = 0; \) ^0 p; u/ [8 Q# m4 `
*(uint32_t*)0x42210078 = 0; \
*(uint32_t*)0x4221007C = 1; }& s* \7 q3 p- r [, @; w
// TDI Pin GPIOA[8]) X) N t! z- B
#define TDI_OUT *(volatile uint32_t*)0x422101A0& u( k. Z5 O. y% P
#define TDI_IN *(volatile uint32_t*)0x422101204 F" j3 s- Q3 m$ R1 I9 W
' r! H( e7 d1 a+ B( L7 n. d
// TDO Pin GPIOA[10]1 ]+ @2 ]6 g# F7 i1 [
#define TDO_OUT *(volatile uint32_t*)0x422101A8 S1 N* \9 K1 G- X5 a- A: d
#define TDO_IN *(volatile uint32_t*)0x422101283 f9 C$ b/ G L; ? ?4 A
. s2 c$ ?# Z9 C+ K( I+ W8 H
// nTRST Pin GPIOB[3]
#define nTRST_OUT *(volatile uint32_t*)0x4221818C
#define nTRST_IN *(volatile uint32_t*)0x4221010C
1 j5 j" M& E& [8 k- e
// 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; \ Z% N0 K7 G6 g0 {7 ^4 I* l
*(uint32_t*)0x42218044 = 1; \
*(uint32_t*)0x42218048 = 0; \- v- z9 K% h! J$ K8 u) ^
*(uint32_t*)0x4221804C = 0; } & G% V, U3 s7 b4 f
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 0; \) ?$ v7 _0 P, O3 E
*(uint32_t*)0x42218044 = 0; \
*(uint32_t*)0x42218048 = 0;\
*(uint32_t*)0x4221804C = 1; }
$ l$ B$ n+ r' k4 T+ Y
$ m$ W9 w& x9 U. m; N8 r" n
// Debug Unit LEDs8 t) |0 O2 g' W
// Connected LED GPIOC[13]
#define LED_OUT *(volatile uint32_t*)0x422201B4
#define LED_IN *(volatile uint32_t*)0x42220134
: U- H0 q0 C/ Q2 i1 A
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \
*(uint32_t*)0x422200D0 = 0; \. u0 M& n. e7 {: U
*(uint32_t*)0x422200D4 = 0; \0 u% c/ _$ M4 _$ _4 c
*(uint32_t*)0x422200D8 = 0; \8 m% T" J! g X$ F* j8 t
*(uint32_t*)0x422200DC = 1; }" o! f! J& ` l, o6 W6 h! y( ~
// Target Running LED Not available7 c6 \4 m+ B! p
// SWCLK/TCK I/O pin -------------------------------------
/** SWCLK/TCK I/O pin: Get Input.* M) m- D" T, f. G* Q" z1 k
\return Current status of the SWCLK/TCK DAP hardware I/O pin.5 J1 f+ L% a( u* l" |
*// U5 N* h# v, |
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return (SWCLK_TCK_IN);
}; U9 \" [* V3 T
4 E6 C2 U4 d- \4 S
/** SWCLK/TCK I/O pin: Set Output to High.! M) e: K2 A0 |' C
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {6 T. w' N, x/ p2 ]! \
SWCLK_TCK_OUT = 1;
}, T5 W" `& P# r* ]/ V* w0 C! b) h
% ?# X4 G( j$ A! Z% D
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.0 o' D, _& L8 l0 m9 O8 n' P
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
SWCLK_TCK_OUT = 0;6 r% k& p" G g
}
) z# g, p$ z0 R( [6 W
4 B, s) ^5 O% ]2 i5 j
// SWDIO/TMS Pin I/O --------------------------------------4 U% E4 X3 a: n' R& O3 A
" {. q6 ~6 K" H3 C3 K% X
/** SWDIO/TMS I/O pin: Get Input.( w1 B4 Y1 Z8 c; s7 Q
\return Current status of the SWDIO/TMS DAP hardware I/O pin.( M! F9 T2 C; w9 Y
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (SWDIO_TMS_IN);$ ?1 S0 N0 E% ^+ H5 v
}* P: ^; w+ u5 }( e2 `
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level., r0 U* x8 \) g9 j3 L
*/$ u7 B+ E( ]; H6 B3 s& l
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {
SWDIO_TMS_OUT = 1;/ ^9 q2 s# p5 g& c. P9 n" ?& T
}
/** SWDIO/TMS I/O pin: Set Output to Low." x: {- x9 Y/ x9 J7 w1 o
Set the SWDIO/TMS DAP hardware I/O pin to low level.$ N& Y+ N: A% N+ H6 ~$ X3 K7 E: D
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {8 j+ A: A9 z+ v( A) x
SWDIO_TMS_OUT = 0;* e* ~! @4 P ?, G
}7 x; v' r# k- Q. M9 r( D- L- o) ?* s: y
/** 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);) H* O' \! W% \9 y* z' E
}. P# f+ A1 I, ]- k0 T
' }) j5 P3 p. k6 p, M# \
/** SWDIO I/O pin: Set Output (used in SWD mode only).+ p7 O5 X3 S2 }& D
\param bit Output value for the SWDIO DAP hardware I/O pin./ [; t/ O) D% O9 X
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
SWDIO_TMS_OUT = bit;' q8 t( U* l6 {; c0 E+ B0 l: i
}5 U- M' z6 t' g% w
3 `- L( k2 ^. i* l8 o! W
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).3 H, o0 O5 q9 e o; m, Q
Configure the SWDIO DAP hardware I/O pin to output mode. This function is) Q: y8 r* T U2 G/ Y
called prior \ref PIN_SWDIO_OUT function calls.6 G1 c) c/ M- Q0 `# x
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {
SWDIO_Output();& A+ k+ _( S7 A8 y7 l
}
: g$ V' u: _. n& A2 j+ W* Z
/** 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.9 x) B# g, k+ s# H
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {: Y0 _; k9 v+ U9 E
SWDIO_Input(); _8 q1 v( i, g
}
楼上有的说弄无线,其实无线也就是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工程,但是编译下载后无法使用。