你的浏览器版本过低,可能导致网站不能正常访问!为了你能正常使用网站功能,请使用这些浏览器。
wth_arm 发表于 2020-11-23 10:000 M0 ]: b& p0 s+ N/ l 再请教一下楼主,我编译时永远都是BLUEPILL,想改成STLINK_V20,#define STLINK_V20 1,这样定义没成功, ...
radio2radio 发表于 2020-11-23 10:44 5 X, I7 A5 e4 h8 }更换不同的板子,在这个下拉菜单里选择:
ricklou 发表于 2021-1-25 10:50 : A. k2 E. s k8 G; A0 V除了mdk和iar能自动复位,其软件他都不行(iar for 8051、keil uv4、keil c166、jltool3、nfc tool、arduin ...
ricklou 发表于 2021-1-27 23:00 1 o+ e$ ~% D& H可以把nreset映射为dtr或rts吗,很多软件走的是com协议,或者告诉我如何触发复位信号 ...
小马哥STM32F103开源小四轴RoboFly全部资料大放送
【MCU实战经验】+STM32F103的uCOSII详细移植
STM32中BOOT的作用
STM32如何分配原理图IO
STM32的I2S外设
STM32电路知识学习
基于STM32F1的CAN通信之DMA
STM32怎么选型
简单分析STM32和51的区别
简单聊聊STM32的SPI外设
更换不同的板子,在这个下拉菜单里选择:
! @: v' r0 p( J0 q6 y4 y" r' \
OK了,终于搞定,感谢!!!
我这个是有复位信号输出线nRESET的,不过IDE要懂得向DAP发出复位命令。
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。/ } j+ {" I) ?. w. _- E' o( j4 Z) N
, ?+ k" Y) a6 \
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。/ I2 Z2 O; b- C7 J V, f
0 A& G' e" L( T) m( g
/**
******************************************************************************
* @file usb_endp.c+ U& ~) W" \; p/ f9 M) B* ]8 g. f
* @author MCD Application Team
* @version V4.1.0
* @date 26-May-20175 W6 O( c' m3 o: ?
* @brief Endpoint routines
******************************************************************************
* @attention+ f+ Q3 p: y: I+ N! D7 i4 F. x
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,/ ?! U. b X, ?4 M: H( B
* are permitted provided that the following conditions are met:; D3 [- n) Y' ?
* 1. Redistributions of source code must retain the above copyright notice,* L% f" D' K9 a7 `' {0 i
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.0 P. J* _, j: l- X5 [% p# u3 ]
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software4 ^) r$ _0 r& G# F" B' e2 `
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"8 F2 r; ~9 Q! |: v4 f. E$ F
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE! U3 R4 G8 j( ]/ J% G2 [
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE7 X. B* [$ {2 s( S' b
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL; t7 m1 b: {& x1 @* Y; w$ J Z
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.( t( D/ Y; b5 x. `4 r0 ]
*8 }+ l4 p0 X6 J1 A: g
******************************************************************************
*/$ Z" O3 l' W+ n/ u/ }5 } ?
% ?* T% b* h6 o: I0 }" V/ r
/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"' l5 V y- n3 Q8 U- }7 d+ j
#include "usb_lib.h"& v' H0 t7 q+ x8 T
#include "usb_istr.h". [! M* _. C( r# {& h
#include "stepper.h"
#include "string.h"
n, |3 b$ W5 _+ q. X( |6 t* f
#include "DAP_config.h"0 k% r2 h! \: E5 r! _
#include "DAP.h"4 m* N7 D( m6 g8 [, G: D: S
: M& X9 m$ n2 p1 h
3 ?" j8 ]2 D) V7 N7 x
/* Private typedef -----------------------------------------------------------*/7 f6 D5 b! R% o
/* Private define ------------------------------------------------------------*/; l: I9 T$ e5 W1 \8 {
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static volatile uint16_t USB_RequestIndexI; // Request Index In- f/ `0 c5 N9 i8 g
static volatile uint16_t USB_RequestIndexO; // Request Index Out3 a; ?# h @# ], B7 d+ z2 t1 s' h2 |' l
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. t. Z. m K6 P
static volatile uint16_t USB_ResponseIndexI; // Response Index In+ G% i$ O! B) U7 H7 x' ^* u" x2 A
static volatile uint16_t USB_ResponseIndexO; // Response Index Out
static volatile uint16_t USB_ResponseCountI; // Response Count In ~) k' f# B d# O0 \8 j6 x
static volatile uint16_t USB_ResponseCountO; // Response Count Out R# {' g! O' O' Y0 k0 M0 z
static volatile uint8_t USB_ResponseIdle; // Response Idle Flag
static volatile uint32_t USB_EventFlags;: Q; ~! A" D8 P3 [" a( M
4 J3 W5 L$ y( B% k( f/ p
static uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Request Buffer3 b3 C; I& h4 W
static uint8_t USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Response Buffer' c0 z- r. V* a! Z+ F& q! j
static uint16_t USB_RespSize[DAP_PACKET_COUNT];
/* Private function prototypes -----------------------------------------------*/! h9 L! A+ @. a" d
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************9 _( A7 _/ n& V
* Function Name : EP1_OUT_Callback.
* Description : EP1 OUT Callback Routine.
* Input : None.
* Output : None.& r" Z- |0 N/ J4 @) v( B$ {
* Return : None.; Z8 f4 l' t+ n$ W( e
*******************************************************************************/
void EP1_OUT_Callback(void), F& _1 N/ M* K5 A; ]1 k- J
{( W* R X4 z7 t5 ]3 ]
uint16_t n;
) Z1 ^: i& t( l4 e
n = GetEPRxCount(ENDP1);1 j0 Y0 O# A0 `) T3 i5 n$ [. ]
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);
if(n !=0){
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {8 Y$ w& {5 j0 Z( E$ @, p# a8 u
DAP_TransferAbort = 1U;7 r9 s/ {8 ~" U7 I! N" @' o0 v0 W7 q
} else {* U5 I- x7 ?) u+ w
USB_RequestIndexI++;
if (USB_RequestIndexI == DAP_PACKET_COUNT) {
USB_RequestIndexI = 0U;7 ~( F, a8 ^6 C
}* `5 B W) E: K8 B& N" N0 x
USB_RequestCountI++;& r v% X2 q" p& q* L
USB_EventFlags = 0x01;' X- @9 {& x0 C! z
}5 r# b1 J: J# b
} 5 O7 }4 u, |. V3 o1 c3 F+ }
// Start reception of next request packet+ f2 c; L, R7 u% J; w- s
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {# `) o+ [! S* {9 R2 h3 I$ D
SetEPRxStatus(ENDP1, EP_RX_VALID);; r0 [9 K% Z' L# s8 n
} else {
USB_RequestIdle = 1U;
} " @) p+ l+ V8 [ X3 V0 z5 {& j& i
}
1 q2 t) B9 Q2 _: e
/*******************************************************************************3 E- S+ l m1 ^+ V# ]; l+ v) `7 i
* Function Name : EP2_OUT_Callback.; C8 K* ] l5 b6 v( k
* Description : EP2 OUT Callback Routine. u6 v6 @& ]7 e4 }
* Input : None.
* Output : None. D: }; P! h) X4 a. H |
* Return : None.; j/ I0 G3 n% T$ ~! w
*******************************************************************************// u ?" M7 k9 J0 X r* [' ^" v
static volatile uint32_t TX_n;: m$ e8 H% C t; l8 r3 E- {) C
static uint8_t *pbuf;& n( L5 n* Z m* J/ t7 D
void EP2_IN_Callback(void)1 { j9 q! U" j; Z4 @' u
{* T* _ t) G5 s
uint32_t a;2 H& \( x. [" i' a9 I9 z
if(TX_n>0){
pbuf+=64;7 f' T" z3 U% ]' M1 b4 {
if(TX_n>64){7 K) d; R9 P2 O) b
a=64;5 l' e* W0 d1 u( a
TX_n-=64;
}else{
a=TX_n;
TX_n=0;- Q* S% p3 ~+ u( k$ k9 g
}& N1 m. G& t' A% P9 D
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);
' o0 e4 E/ @# Z
SetEPTxValid(ENDP2);, v0 b# v) L+ R& L7 o
}else{! T4 H; V+ F" x/ x. {" g
#if (SWO_STREAM != 0)
SWO_TransferComplete();2 S1 Z0 v1 m- p' J5 }- |8 r
#endif. E- Z' l+ g2 ~' c7 O+ X/ ]
}
}, s6 E5 w5 }& H# r+ W0 a! z% L
+ t7 o. j( B0 G! A) N
/*******************************************************************************
* Function Name : EP1_IN_Callback.
* Description : EP1 IN Callback Routine.2 E, X4 c0 D6 N* {
* Input : None.! c: Z; G6 ]2 x5 T8 p* h9 W# B4 Q
* Output : None.; @6 n, z" ]$ B& d
* Return : None.3 ?& u- B( O4 m+ R3 A
*******************************************************************************/; K5 F# r, J6 I9 M% @
void EP1_IN_Callback(void). j% E s+ a% V3 s- f z
{8 \/ Z i; w* ~
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back5 I$ y6 r3 d+ T2 I
UserToPMABufferCopy(USB_Response[USB_ResponseIndexO],ENDP1_TXADDR,USB_RespSize[USB_ResponseIndexO]);
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);2 }% t. t" b4 n
SetEPTxValid(ENDP1); 1 }0 V5 A4 c9 S$ {
USB_ResponseIndexO++;6 n. t; f+ k3 [4 I, q+ Q G# i
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {% |( [9 J2 ?4 O1 I. ^
USB_ResponseIndexO = 0U;* s0 x' H; Q E3 A$ d& P, Y2 V( ~3 u
}1 _" ^; R1 n2 n* O+ q& t# v
USB_ResponseCountO++;
} else {
USB_ResponseIdle = 1U;
}
}
+ `/ N4 F5 V( V
// Called during USBD_Initialize to initialize the USB HID class instance.7 }; x8 l5 g1 i8 ?2 z+ q; e
void DAP_FIFO_Init(void)
{
// Initialize variables) H' u ?/ n( b8 n( w3 r# p
USB_RequestIndexI = 0U;
USB_RequestIndexO = 0U;
USB_RequestCountI = 0U;
USB_RequestCountO = 0U;; a3 y$ i/ m) j% B, j/ E. M2 ~3 X5 w
USB_ResponseIndexI = 0U;. B1 i! W6 p U. T0 Z) a
USB_ResponseIndexO = 0U;
USB_ResponseCountI = 0U;
USB_ResponseCountO = 0U;
USB_ResponseIdle = 1U;
USB_EventFlags = 0U;% T) [: L! S# ]/ G. ?2 m+ r
}
7 a! R/ X. w8 h$ e7 r
uint8_t DAP_Thread (void) {% u* ?* x- e4 {) F# f
uint32_t flags;
uint32_t n;) [4 E7 W* d# _
//for (;;) {
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);
if((USB_EventFlags & 0x81) == 0)6 y: g P2 X$ n9 T2 e9 B% U
{
return 0;. [, b) Z: s! Z$ `* b; N& P! {
}
USB_EventFlags &= (~0X81);: `' O6 K$ k, Y1 e9 X# F. ~" W1 O
4 B& Q& i6 P7 D' D1 w) n
// Process pending requests
while (USB_RequestCountI != USB_RequestCountO) {/ c. X3 n( }( o) ?/ S& Q5 C
//if (USB_RequestCountI != USB_RequestCountO) {- }1 e! j: q: A; K( |( q! E
// Handle Queue Commands
n = USB_RequestIndexO;
while (USB_Request[n][0] == ID_DAP_QueueCommands) {$ W7 z0 S& o2 W' `- p7 S
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {6 b( j: o* P9 u, C( J, f0 p% q
USB_Request[n][0] = ID_DAP_ExecuteCommands;3 w5 W. {) i* h$ k/ C
n++;) N- A2 E; I7 S8 l7 P+ h. h- z) Q l
if (n == DAP_PACKET_COUNT) {* [: }3 q2 ?/ D; K6 o/ h, r, }' d0 |
n = 0U;9 K. n0 p2 m* o/ R2 l2 z6 r
}
if (n == USB_RequestIndexI) {. [7 i+ v8 `2 D, N* D
flags = USB_EventFlags;. I; S2 W4 z1 u' [3 [1 d
if (flags & 0x80U) {
break;
}
}
}/ O8 t# P8 A$ E% i7 L: p' }" [
* @- h. K; Q4 p3 c6 [; y( ~
// Execute DAP Command (process request and prepare response)
USB_RespSize[USB_ResponseIndexI] =
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);* B" z" b; W* O, E1 I) {
// Update Request Index and Count
USB_RequestIndexO++;
if (USB_RequestIndexO == DAP_PACKET_COUNT) {* S# _9 U# T2 n- `- C6 b
USB_RequestIndexO = 0U;
}1 d' H( I# Y# Y; w
USB_RequestCountO++;
# m. v. w% K' T7 X
if (USB_RequestIdle) {
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {3 i: Z9 z: y" w" Q
USB_RequestIdle = 0U;
SetEPRxStatus(ENDP1, EP_RX_VALID);0 S% c8 X F6 Q+ w' u9 s
}! |2 N% K( h4 [) H9 e* }& ~$ x
}
// Update Response Index and Count
USB_ResponseIndexI++;: V* J, q O B1 e' _0 R
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {
USB_ResponseIndexI = 0U;! C; r- P8 P' F. {/ _7 q7 G
}
USB_ResponseCountI++;+ |( L0 {2 O X1 m2 A1 G; y
/ {1 p2 s) c+ b: ?5 i4 D( W# s
if (USB_ResponseIdle) {) M, n6 l+ N# ?" o: R8 G
if (USB_ResponseCountI != USB_ResponseCountO) {7 m0 s5 j2 I6 w. h3 m/ P2 J
// Load data from response buffer to be sent back
n = USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;
}
USB_ResponseCountO++;
USB_ResponseIdle = 0U;
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);% Y" L' w2 V! Z
UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);
SetEPTxCount(ENDP1,USB_RespSize[n]);
SetEPTxValid(ENDP1);
}
}
}
return 0;
}
// SWO Data Queue Transfer* P; c: U' j. N
// buf: pointer to buffer with data( Z$ P* f- I2 y% e# Y' k$ m% q- I
// num: number of bytes to transfer& [% F* d+ r1 n) A% L9 A2 P
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {3 B8 `" A5 N, Z2 l1 {
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);
uint32_t a;
if(num>64)
{
a=64;
TX_n=num-64;
pbuf=buf;2 H9 \* I: Y+ K2 F8 Z0 p% w% U
% L+ J' O' d6 J& P. N0 Z: R7 u# Y
}else {: J; ~- C" C% f& n& u
a=num;
TX_n=0;& O: L0 ~- A& s+ [$ {( c; n
}$ ], `. X; \4 U) w0 I* t
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);& ]0 u8 V4 B% X/ u; C8 I
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);7 e1 S5 _! L# b* k4 ~' a6 V+ I
}- I9 \1 c& Q \, z' z/ ]3 G
// SWO Data Abort Transfer9 s* X( L. O S: _
void SWO_AbortTransfer (void) {, ^- \, b) ]3 f
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));
//SetEPTxStatus(ENDP2, EP_TX_NAK);4 [( k% i9 M o( d; C- [8 p
SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxCount(ENDP2,0);
//TX_n=0;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/. l& T6 f9 Q: v, n8 Q* Y b I
- L9 f8 A; }/ X4 u+ C- U3 E* {4 I0 N
移植大概是这样的,利用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里面没声明这个寄存器,只得自己定义一下了* a# q/ X$ k; u+ p4 s
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {' ?3 Q% g$ n; r0 L2 w
return (DWT->CYCCNT);
}# E, r7 B q$ C" [$ _
void DWT_Init(void)
{
/* 使能DWT外设 */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
6 h2 m3 W2 k- ~# g
/* DWT CYCCNT寄存器计数清0 */
DWT->CYCCNT = (uint32_t)0u;/ M& @7 t9 V1 Q5 [2 F7 B
/ e7 W3 `+ B3 m7 l( ?* A
/* 使能Cortex-M DWT CYCCNT寄存器 */
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}' W3 ]8 d( l9 t2 o
" k% D4 |1 P! v1 h
然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率+ O# Y4 V! N9 {. x, ?) Q c) Y7 q4 Z
3 A$ p, ~, n( v$ [
然后改为使用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的地方都改为如:7 O4 O# q7 M! r$ j3 i& K, Z
//osThreadFlagsSet(SWO_ThreadId, 1U);2 n U6 }6 r! ~- k3 I
SWO_EventFlags = 1U;
+ _% Y) \. I$ F3 ^# J9 p( c
// SWO Thread
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {: l; z( i& q$ R9 m
//uint32_t timeout;7 z3 }% A( b3 P7 {( n5 z
uint32_t flags;' {9 R9 H. r; v+ Q# S- x5 ?
uint32_t count;
uint32_t index;8 g! \- G& Y8 I4 J9 K9 ~
uint32_t i, n;
//(void) argument;
9 j/ J" \$ ~/ F9 V/ D B0 u+ Z- n8 y
//timeout = osWaitForever;
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if((SWO_EventFlags & 0x01)==0)return 0;
flags = SWO_EventFlags;$ u& @! e/ d3 H
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不熟悉,不知道是不是这样子
;4 p! ]+ ^7 F3 _6 j8 X4 l$ s- n4 }/ P( q; ^
} else {% X0 Z5 ~6 h' y; p$ c
//timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}9 H5 j9 {+ W8 D Q. l
if (TransferBusy == 0U) {
count = GetTraceCount();
if (count != 0U) {& i: N$ T5 ]: u( M7 k$ p; r
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);; r; O: X7 U$ K$ I; f
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;3 I8 e1 {0 B3 F! ~& b0 w' X
}% F2 i" o4 G% Z7 n# q% ]: U
if(count>USB_BLOCK_SIZE)9 N" |: G1 m! g! v
count=USB_BLOCK_SIZE;3 j3 A/ d2 d/ s; r; A8 U2 \2 N- v
if (flags != osFlagsErrorTimeout) {2 g' {/ j2 O; R; t5 a
i = index & (USB_BLOCK_SIZE - 1U);5 B+ |/ n5 c5 N3 w
if (i == 0U) {1 n4 _, ?* [' v! C7 ?$ X! p9 G
count &= ~(USB_BLOCK_SIZE - 1U);2 C2 W Y1 g) A, @7 M4 m: B
} else {0 P$ O! {* z5 i( s3 W
n = USB_BLOCK_SIZE - i;( ~( z( p+ Z8 r9 ]0 \. ^
if (count >= n) {
count = n;& K% c A3 A1 P) h) c2 \
} else {
count = 0U;8 j- u* f, p- S* P
}1 b" E( R: v4 g. J! [* {
}4 l0 K8 p3 I" O- f8 u
}/ O/ _- ]+ G; R1 E
if (count != 0U) {
TransferSize = count;9 ^9 o& G$ c: V
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);
}
}& v, P% Q( C$ Y' A3 T" ?
}, {6 a6 q7 }. R; d0 L) l
//}
return 0;. J5 Q9 U6 @8 v
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value./ C& _1 F5 E! F0 W: ~
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
static volatile uint32_t SWO_EventFlags=0;
static volatile uint32_t timeout=osWaitForever;
static volatile uint32_t timeWait;
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {5 M- ?3 |! I! O# Y
//uint32_t timeout;1 J7 L$ Z5 p- p
uint32_t flags;
uint32_t count;
uint32_t index;
uint32_t i, n;
//(void) argument;1 x( V( _/ B# u7 g
* y/ C- g/ n4 Y% Y4 o1 z- R& |, C
//timeout = osWaitForever;
//for (;;) {% o. M6 G7 R9 B. E. k
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if((SWO_EventFlags & 0x01)==0)
{
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了
return 0;: x, U* l) j4 q7 t
}
flags = SWO_EventFlags;
SWO_EventFlags = 0U; & _2 ^% i/ m# i- w ?1 w
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
timeout = SWO_STREAM_TIMEOUT;
timeWait=DWT->CYCCNT;
} else {& t! F% J6 k1 ]% K6 o m( p* j
timeout = osWaitForever;: m( i) r5 w+ S& T; [/ p: Z
flags = osFlagsErrorTimeout;
}
if (TransferBusy == 0U) {7 J k$ c$ U; k; i8 g0 c. x
count = GetTraceCount();+ Y4 l* O$ k( _& y/ p
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);8 f' X/ S- T+ r: J5 n! W& C
n = SWO_BUFFER_SIZE - index;
if (count > n) {' `" N5 w/ g9 ?1 y: P8 e
count = n;1 a! D$ R3 z! Y
}
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;" c* z8 `2 G( l ~. D3 f6 I
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);/ X9 f) a7 q. ], c+ K* S) `9 B% h: S
if (i == 0U) {# w# ?3 U7 d# K2 _: V
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;" I$ r8 q9 i# e5 e. k% p/ V
if (count >= n) {
count = n;6 J7 T) D! ~; s$ n
} else {, H6 r+ B; q: u1 e# R. r
count = 0U;
}( O% W* L" ]9 G7 u+ h) |
}
}" I4 @& A: \$ Z7 {6 w8 n5 L* T
if (count != 0U) {$ L2 d2 n. R+ I: E0 {' x
TransferSize = count;
TransferBusy = 1U;7 Y+ ?+ j0 b. B! I- r' F& e
SWO_QueueTransfer(&TraceBuf[index], count);* H& \" |4 I. _5 t% M
}; L: s- Z/ H% v! s
}
}2 S4 R7 d1 G+ t( _9 H1 u0 }; g- _6 l
//}
return 0;
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了4 x( Q3 o) u4 G
) e& e) r6 R# S) b! |5 E
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,少了这个等待时间,能增加端点的传输速率) U& \% g6 v1 k& ^5 Z
* K/ o1 v' H7 o# W
int main(void)
{
DWT_Init();$ {4 F+ P) ~1 l8 b/ e( x6 f
DAP_Setup();
USB_Interrupts_Config();
Set_USBClock();, M# m+ W N+ y0 p% _4 K! {$ X
USB_Init();
//TIM3_Init(35999,0);; ]8 K1 [, [3 `8 R1 a3 p
//TIM_Cmd(TIM3,ENABLE);
" |) w6 n+ D* x" ?, S3 V- T. y
while (1)
{
DAP_Thread();
#if (SWO_STREAM != 0)
SWO_Thread();6 t+ q+ `) a: R2 `- J* h
#endif) g: J' ?; \/ X! M7 Q6 w d" O+ g
} Y2 G; m' E/ C3 G5 S. [
}8 H$ w+ `# @ T' L5 N2 y# h# m
对于DAP_config.h的IO配置我是这样弄的
///@}, [& n, S3 k) d
// Debug Port I/O Pins
// SWCLK/TCK Pin GPIOA[6]# B! j& e! W7 T4 e4 _5 U* \5 _
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198
#define SWCLK_TCK_IN *( uint32_t*)0x422101185 w; M/ L7 f4 }( G6 W
3 N1 q# F4 W5 P6 m3 ?! `( S5 B
// SWDIO/TMS Pin GPIOA[7]
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C6 Z7 C$ N; D9 G4 M; X
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C" i0 U+ L6 o; ?. f3 d
# i. {* C! f( H+ H4 g; @
// SWDIO Output Enable Pin GPIOA[7]/ G. J+ [ E/ h" ?0 ?# g( H
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 1; \
*(uint32_t*)0x42210074 = 1; \
*(uint32_t*)0x42210078 = 0; \
*(uint32_t*)0x4221007C = 0;}
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \* B* I, d7 v) @% V7 N, O
*(uint32_t*)0x42210070 = 0; \
*(uint32_t*)0x42210074 = 0; \
*(uint32_t*)0x42210078 = 0; \6 n& r. R6 ? |% l' ^5 t
*(uint32_t*)0x4221007C = 1; }
// TDI Pin GPIOA[8]5 Z- S5 v0 a3 h1 r8 B5 n6 L
#define TDI_OUT *(volatile uint32_t*)0x422101A0& E& `2 }2 {( w( f+ N" K- P
#define TDI_IN *(volatile uint32_t*)0x42210120
// TDO Pin GPIOA[10]
#define TDO_OUT *(volatile uint32_t*)0x422101A8) _9 ]3 W( w0 ^
#define TDO_IN *(volatile uint32_t*)0x42210128
2 u9 m" Y7 h% T/ A2 h% j/ |9 o4 Q, [
// nTRST Pin GPIOB[3]
#define nTRST_OUT *(volatile uint32_t*)0x4221818C
#define nTRST_IN *(volatile uint32_t*)0x4221010C: S' i! D* T" [% K* [" D" w; j) X
) @0 p- A2 M: l
// nRESET Pin GPIOB[4]; `$ [9 U: g v
#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; \1 c* N/ b+ o0 G$ X6 d* `
*(uint32_t*)0x42218040 = 1; \ }8 O. Z" u7 ?
*(uint32_t*)0x42218044 = 1; \
*(uint32_t*)0x42218048 = 0; \1 ]9 d& ~/ Y% m6 q' _" |
*(uint32_t*)0x4221804C = 0; } ( C2 I) V8 v/ X* }+ k& r' q$ L
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \2 k5 G$ o: [1 e0 R7 ~* z1 {
*(uint32_t*)0x42218040 = 0; \, T- Y2 U6 s& r8 y# P2 v' K
*(uint32_t*)0x42218044 = 0; \& v! D! y' w4 }. j/ W0 V# J
*(uint32_t*)0x42218048 = 0;\% H* w9 x1 `! T w
*(uint32_t*)0x4221804C = 1; }6 ^1 v' x# S% s& ?
// Debug Unit LEDs
& f+ S" a+ o5 E1 y% C! q3 c
// Connected LED GPIOC[13]
#define LED_OUT *(volatile uint32_t*)0x422201B44 T: J Z; p' W
#define LED_IN *(volatile uint32_t*)0x42220134
/ p% l% s* x" n2 s4 n* ]# [- V( v
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \
*(uint32_t*)0x422200D0 = 0; \
*(uint32_t*)0x422200D4 = 0; \: X$ w, n/ b, D
*(uint32_t*)0x422200D8 = 0; \6 c& {# `7 F: q: l; v1 X* p6 i% g
*(uint32_t*)0x422200DC = 1; }/ J% ?" J( W2 N+ u# Y, v
// Target Running LED Not available1 Y( ]4 u- Z: A6 |8 D2 p
$ K* T6 |! I+ I" R& ^5 p
// SWCLK/TCK I/O pin -------------------------------------6 q6 f: t. k$ o
- Y6 p9 b4 z5 p
/** SWCLK/TCK I/O pin: Get Input.% ^9 l2 I7 J( a- m l0 o" O
\return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return (SWCLK_TCK_IN);7 |9 G( r$ X- r: X$ i
}
- y1 y: R# Z( ]' @
/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/+ o# Q3 O: d$ O0 v/ v) v h
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {
SWCLK_TCK_OUT = 1;. s* ~. u$ J6 x3 g
}
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
SWCLK_TCK_OUT = 0;& ^7 C$ E1 D0 C2 J# @5 E0 l
}8 f+ W* O+ _+ ]: _5 @) ?
+ n: Y/ @! E' m
* N0 G, j0 L0 p
// SWDIO/TMS Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input., l" s0 f: Y5 w
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (SWDIO_TMS_IN);
}
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.. a3 T! A' \; A I( _( E
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {
SWDIO_TMS_OUT = 1; x- c* A: |6 Z7 ]/ X) a
}
/** SWDIO/TMS I/O pin: Set Output to Low.) z' ^% e2 Y/ ^
Set the SWDIO/TMS DAP hardware I/O pin to low level.9 C2 x/ u- V7 V9 j4 k9 ~' @
*/+ B0 G6 K! {" ?- U- A3 g9 t
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {6 \% _0 u; O' ^& G( v
SWDIO_TMS_OUT = 0;0 y1 Y' @5 X- Y) O/ b& d
} G* b5 ?8 w9 b* T
& X( R9 G( F0 V8 P6 {
/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin.1 K f. M- S8 t( m! Y8 r
*/5 w& n; O" r) F' ?3 i+ ]& a
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return (SWDIO_TMS_IN);
}( |, M2 \9 Y: {& v. t6 [
/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin.) c# u, E7 _! O1 s1 i* t; d5 k/ g
*/1 ^3 m4 T9 j+ J
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
SWDIO_TMS_OUT = bit;
}( B1 C5 e( P# Z' ~! q6 r
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).4 [: x1 s- R1 Y7 K$ h0 {
Configure the SWDIO DAP hardware I/O pin to output mode. This function is9 `" s3 c% g9 x' r# t. c
called prior \ref PIN_SWDIO_OUT function calls.
*/, W* G8 @0 N2 H1 g1 v1 A
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {- x* Q$ r7 x% w1 l5 |+ m' v
SWDIO_Output();4 [& f, c# x c5 W, Z
}
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).8 I6 k$ z1 r1 |7 Y: u( R# H* S
Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls.
*/6 R1 f, M9 E6 Y
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
SWDIO_Input();
}
! T/ Q0 q2 Q" P' N
楼上有的说弄无线,其实无线也就是PC<->USB<->无线模块A<->无线模块B-DAP,数据传输的速率主要是无线模块之间的速率限制了,也是非常简单的, H- N' l. n. f9 C6 ] N- y
即单片机先做好USB接口部分,OUT端点收到的数据发送到无线模块A,无线模块B接收到数据后,推给DAP处理,DAP响应的数据再让无线模块B发送回无线模块A,再通过USB发送回PC,也就是说USB与DAP之间也就多了两个无线模块作为数据的交换,要是会写USB驱动,写个虚拟WINUSB设备的驱动,让Keil的DAP驱动能识别到这个虚拟USB设备,通过ESP32利用WIFI通信应该比使用这种无线模块更快,而且ESP32主频更高,即使IO模拟 SWD接口,都会更快,会写USB驱动的大佬可以尝试一下; |4 j8 K8 l4 P; b. P