DMA 原理从 0 到 1:为什么它能解放 CPU?一文讲透 DMA 的工作流程
【福利三:雨露均沾·逢7狂欢】之五:STM32系统时钟PLL故障排除1例
【福利三:雨露均沾·逢7狂欢】之三:AI帮我查BUG
福利三:雨露均沾·逢7狂欢】之二:STM32F407VG串口通信乱码故障的排除
基于STM32F103的I2C主从机通信
OpenBLT移植到STM32F103战舰开发板上适用于所有STM32F103系列的Bootloader
TFT LCD 与 FSMC 的硬件连接大容量 STM32F10xxx FSMC 接口
单片机:初学者该了解的STM32F103基础知识
2025软件工具兔哥知道
STM32之继电器模块
微信公众号
手机版
我这个是有复位信号输出线nRESET的,不过IDE要懂得向DAP发出复位命令。! E: N5 N! m" v
0 L" w+ U2 O T% n
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。
9 R; M3 @. w+ s0 r
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。 ; d4 a/ E+ g o# ~ K; N6 F. e1 |
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。% {1 R" q9 t% V* A- X7 E
2 W1 V K% ?$ o; Z' h2 A2 h# ^
! o+ J( k( n! G. C% M6 F
/**
******************************************************************************
* @file usb_endp.c
* @author MCD Application Team
* @version V4.1.0/ S( _: m" i( v5 U' V
* @date 26-May-20179 P# u' ?, a/ f
* @brief Endpoint routines
******************************************************************************
* @attention1 s6 e" ~, P2 T$ }$ W2 N
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,1 x( m9 m% E3 ~8 {
* are permitted provided that the following conditions are met:
* 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,: C5 x7 ~& n& A2 p* F% \9 O
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.2 ~8 }( ~" B/ s1 j+ B7 ~; V5 G2 B
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software) M6 L" B" r# ~& T" E8 T! R
* without specific prior written permission.$ R2 p3 E2 _$ P- k/ Z5 ?0 \( U
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"5 n* _) `5 L h1 k
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE' @: g9 A( x; F1 `' b9 ]
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE1 S) O1 j5 [* y6 H1 Z+ r8 S
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL) n4 S/ h L& e
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR9 q5 W! B9 F( \
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER7 T" i7 Y5 s d
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,* i1 C( f9 w5 w" G$ Q8 o
* 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.
*3 w4 T( U \* A' V
******************************************************************************
*/4 r' L6 |7 W# s7 ], e0 z
+ N& I; l( ?5 ?! \: W- m
5 Z9 P+ q* o5 U5 W
/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"
#include "usb_lib.h"5 k' z& }' x- t! C. W8 i
#include "usb_istr.h"
#include "stepper.h"
#include "string.h"& `6 [5 F' S6 O! c. O1 A4 U9 H {
#include "DAP_config.h"$ k' F. I% F" C
#include "DAP.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static volatile uint16_t USB_RequestIndexI; // Request Index In9 }& v. m8 h. m
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 Out8 R% E6 k% B7 y( a3 J7 E# k
static volatile uint8_t USB_RequestIdle; // Request Idle Flag8 F$ \/ m) E9 l5 w5 m
: M- o4 z' ?2 U* } d, q
static volatile uint16_t USB_ResponseIndexI; // Response Index In
static volatile uint16_t USB_ResponseIndexO; // Response Index Out
static volatile uint16_t USB_ResponseCountI; // Response Count In+ M( O3 H% u9 f& A! c, M; m
static volatile uint16_t USB_ResponseCountO; // Response Count Out! M0 M8 P G) R7 f/ g+ ^$ w- p
static volatile uint8_t USB_ResponseIdle; // Response Idle Flag
static volatile uint32_t USB_EventFlags;/ v8 f0 X; q" k4 j8 z
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$ B2 m, {7 G) q, b7 ^1 L
static uint16_t USB_RespSize[DAP_PACKET_COUNT];
- G3 Z+ V- T- T6 e8 q7 a& _
/* Private function prototypes -----------------------------------------------*/6 j( o/ f( ]5 D- f) k
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************2 n* X6 N) u+ h K8 M' N
* Function Name : EP1_OUT_Callback.
* Description : EP1 OUT Callback Routine.# C0 J# Q$ x! Z" I
* Input : None.
* Output : None.& z; q3 C; a; s3 z
* Return : None.
*******************************************************************************/
void EP1_OUT_Callback(void)5 ?* M. s+ Q4 n' u* X
{4 V5 ?! ^ p( L
uint16_t n;
n = GetEPRxCount(ENDP1); y* A+ b6 e9 d) g# A
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);5 V( A8 o# J+ f1 w4 I+ t+ p8 C S
if(n !=0){: i$ o, i# o' Y# Y/ n! g
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {6 o1 M6 H/ g* s `, M" p) l- h: X# ?
DAP_TransferAbort = 1U;4 _7 k! @2 Y9 \+ b- ~) L
} else {
USB_RequestIndexI++;) Q- I) K( v% Y* q% @
if (USB_RequestIndexI == DAP_PACKET_COUNT) {
USB_RequestIndexI = 0U;* a" P/ F4 c7 l ]; u
}
USB_RequestCountI++;
USB_EventFlags = 0x01;
}
}
// Start reception of next request packet
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
SetEPRxStatus(ENDP1, EP_RX_VALID);
} else {% B! X. Y" j6 O/ S/ v; Z5 t
USB_RequestIdle = 1U;
} * [: z t) E c+ n8 f/ x
}0 `' {4 x9 u9 X) A1 M- o
/*******************************************************************************
* Function Name : EP2_OUT_Callback.
* Description : EP2 OUT Callback Routine.: U' L F+ U9 X' l) R. M
* Input : None.- O; e- @! j: _. {, A
* Output : None.5 Y3 E1 T! k* c8 J% m
* Return : None.
*******************************************************************************/
static volatile uint32_t TX_n;4 q8 x. {; d, S6 }) Y# E
static uint8_t *pbuf;
void EP2_IN_Callback(void). |$ D ^: f: v% [6 @' Y
{7 g. p% Z. T0 [; U' X: [
uint32_t a;
if(TX_n>0){: @" C3 k f9 u' c* Y2 H9 _3 U+ ^
pbuf+=64;
if(TX_n>64){* [+ A# ?, `% u8 W8 c" G
a=64;/ m u# ~$ _! I7 W0 s, Y
TX_n-=64;# L9 E+ { j& ]1 z( J
& s4 N7 T" t) F
}else{
a=TX_n;. D0 Z. L* _/ H' ?& q. g5 _
TX_n=0;
}; Q0 V' q' t2 A# o' e& f4 f1 a
9 Z3 c5 ^' R# o2 t3 X% X
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);5 _+ |8 h: X3 G* W+ b/ z
SetEPTxCount(ENDP2,a);
7 |& D& [) G4 z$ w/ V7 F$ M' c
SetEPTxValid(ENDP2);
}else{: ^1 h) x8 j& b- {
#if (SWO_STREAM != 0)! N- a$ w# i2 A' O! k. \
SWO_TransferComplete();/ D0 d. D8 B6 w R% s
#endif
}$ P2 N, N ^6 t0 P( y2 z
}
/*******************************************************************************
* Function Name : EP1_IN_Callback.9 Q8 ]) K/ \& d
* Description : EP1 IN Callback Routine." l" y# T/ r w& t5 ~; m6 U
* Input : None.
* Output : None.
* Return : None.# l% \, `2 t8 W0 W1 v
*******************************************************************************/
void EP1_IN_Callback(void)
{
if (USB_ResponseCountI != USB_ResponseCountO) {( t- ^2 p5 |7 l+ j0 K+ k0 m: X
// Load data from response buffer to be sent back; t1 E: c& u3 w R& m
UserToPMABufferCopy(USB_Response[USB_ResponseIndexO],ENDP1_TXADDR,USB_RespSize[USB_ResponseIndexO]);
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);
SetEPTxValid(ENDP1);
USB_ResponseIndexO++;; t6 R: D" @7 g
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;
}# S9 S4 M$ {; S8 w' ]. e
USB_ResponseCountO++;
} else {6 }0 _/ |; [% t% n1 a, [: ^
USB_ResponseIdle = 1U;- O; z! J* t+ h4 b
}
}/ k/ h1 t* l* x8 n$ j
6 }2 @/ C# Z n7 j: y$ o2 W
// Called during USBD_Initialize to initialize the USB HID class instance.
void DAP_FIFO_Init(void)
{
// Initialize variables
USB_RequestIndexI = 0U;- _4 q7 X8 l7 s( e# x5 T
USB_RequestIndexO = 0U;& y' o7 |& \) I: ]- I
USB_RequestCountI = 0U;
USB_RequestCountO = 0U;9 \. `/ a! J# I, h5 w
USB_ResponseIndexI = 0U;# D' C8 z% c' v1 Z) l
USB_ResponseIndexO = 0U;, V4 Q4 }% _6 u, _8 y- V
USB_ResponseCountI = 0U;9 {' S* B/ H6 T. W+ ^, t! l
USB_ResponseCountO = 0U;
USB_ResponseIdle = 1U;
USB_EventFlags = 0U;
}) y6 n) @9 ^8 `1 ^4 U* B
# k9 V) X% c; X, J+ @
uint8_t DAP_Thread (void) {/ B! j9 B( {. ?; T
uint32_t flags;6 }- O4 P& b/ ]. d g7 ?
uint32_t n;
# {8 b! u D& y( ^
//for (;;) {. f! c9 u$ m9 U- @3 R7 @, M
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);
if((USB_EventFlags & 0x81) == 0)
{0 }1 A& f& N A( h( _- w' F8 e. q. h
return 0;
}
USB_EventFlags &= (~0X81);. a8 A+ s" `; U& g
$ n: X! v5 N1 X: I
// Process pending requests1 s' K' o& O! Z/ V8 B6 t8 }
while (USB_RequestCountI != USB_RequestCountO) {
//if (USB_RequestCountI != USB_RequestCountO) {
// Handle Queue Commands& V& F9 D% `" J! Y7 A6 O! G, Z
n = USB_RequestIndexO;7 b/ t9 g3 l3 `
while (USB_Request[n][0] == ID_DAP_QueueCommands) {
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {; p4 G' i# I& |9 C
USB_Request[n][0] = ID_DAP_ExecuteCommands;. r5 d* }3 V* Z1 B3 d' Y8 w
n++;5 S, D: [! {1 M5 o- [ W
if (n == DAP_PACKET_COUNT) {
n = 0U;
}
if (n == USB_RequestIndexI) {
flags = USB_EventFlags;
if (flags & 0x80U) {
break;; G# ~1 b, Y M; K% ]- e+ E% x2 n$ w
}8 \! p; O+ D5 ^7 @' [- M
}
}
' B9 _8 k5 l: E
// Execute DAP Command (process request and prepare response)
USB_RespSize[USB_ResponseIndexI] =
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);8 e! H) M) }# r! ^6 G/ n
// Update Request Index and Count
USB_RequestIndexO++;$ n- d3 H+ M5 U
if (USB_RequestIndexO == DAP_PACKET_COUNT) {
USB_RequestIndexO = 0U;
}
USB_RequestCountO++;
/ K3 U$ K. @% \% J; y. r8 s
if (USB_RequestIdle) {" A. Z5 \% J4 S! X N: o0 y {
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {' H, B$ ?% l- o8 ?; v H |
USB_RequestIdle = 0U;
SetEPRxStatus(ENDP1, EP_RX_VALID);8 F, N" x' x5 z% k: f/ ~1 t' D5 u
}) B4 L- F( B+ |. i) R, P6 F7 b
}
0 w8 B- e7 p& D7 N: @# I$ b3 D: Z
// Update Response Index and Count/ D+ D6 W- w5 ?8 G' K
USB_ResponseIndexI++;
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {% g) j: D- b1 B3 r6 _( U1 e3 T a
USB_ResponseIndexI = 0U;
}. q* F% ^8 X: P9 w, g' T+ H
USB_ResponseCountI++;9 M! b% y/ z! x1 Q% \# q4 _
if (USB_ResponseIdle) {1 \+ Z0 q! w; e+ B) X
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back& Y5 Z* D2 z6 l- a; ?
n = USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {# d! [ _2 M0 R) {! s$ I5 K0 M
USB_ResponseIndexO = 0U;/ e: ^5 G. l/ J; }3 ^$ |* s/ ~$ h
}* x, b& k! F! E0 p% ] |
USB_ResponseCountO++;
USB_ResponseIdle = 0U;. W& x" P1 ~6 U4 C% ?3 f5 \' J
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);! u: Q- z/ I, ]8 Y+ h' n7 V" b1 V
UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);
SetEPTxCount(ENDP1,USB_RespSize[n]);
SetEPTxValid(ENDP1);+ V) l8 o# ^9 p4 K% z+ P% d9 D
}5 H9 V6 c1 `, Q- D3 j2 q
}, k" W: G1 s9 g; U; J# s
}: @2 r* b; f- d2 R+ S7 L
return 0;7 R! K+ g1 W6 D
}
// SWO Data Queue Transfer. f* _$ B" \& R- F) v
// buf: pointer to buffer with data, y3 j3 E: C3 E: I: d8 ^0 O( S
// num: number of bytes to transfer
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {. H, y; \* |' [9 J: o; O9 u9 K/ E0 W
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);5 n, ~9 P1 z+ I% y' g! Z
uint32_t a;
; z% y8 |4 ]! ^6 A
if(num>64), F [, T* H1 i$ V5 _! B
{: L+ E8 Z9 H9 S+ K; s
a=64;
TX_n=num-64;* l) J6 l# l$ j( I( R
pbuf=buf; j9 k- X3 ^' m& d; a/ x- f
}else {" A0 `0 R$ z$ \, O P( I7 B
a=num;
TX_n=0;* Z0 L) `! J- \ w( V% o
}9 U! k4 ]; V7 x+ y
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);/ [- l; @* S7 m1 P6 w
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);/ q1 Q5 S0 x3 q8 E7 B; o. B' k
}
// SWO Data Abort Transfer
void SWO_AbortTransfer (void) {
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));5 {. K' f! u% y% b, s
//SetEPTxStatus(ENDP2, EP_TX_NAK);: z0 I; j# ` g J
SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxCount(ENDP2,0);. Y: J8 a) _" k& A H
//TX_n=0;
}0 G7 z' m# v0 K" c' [( P) d
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
移植大概是这样的,利用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里面没声明这个寄存器,只得自己定义一下了
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {
return (DWT->CYCCNT);3 y+ p6 j' l, t, i: h* q( b, {
}% ~* U7 S+ y: A( C4 u
void DWT_Init(void)
{6 ^* Z6 n- d3 O, p' K- R& m
/* 使能DWT外设 */& d) @) n% d, p: t* `- u
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; % {- H l \, R4 I7 Z; Z
/* DWT CYCCNT寄存器计数清0 */
DWT->CYCCNT = (uint32_t)0u;
4 S; I9 A/ \& J- h( B; N
/* 使能Cortex-M DWT CYCCNT寄存器 */& e9 f( ^" f7 b a$ C* M
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;5 S- T9 p8 a# I, G4 o7 z
}
然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率, u! c( c' H$ m' u) q" b2 Y
然后改为使用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);
SWO_EventFlags = 1U;
7 F! K, T# d( q* n
1 J, O" r' X2 x9 b) }, P" {
// SWO Thread$ F- {& e2 Q* j4 W0 M$ ^5 G) b
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {( F; ]' V# [7 g
//uint32_t timeout;; ~1 o& N0 p+ ^3 {* M
uint32_t flags;
uint32_t count;
uint32_t index;& q: J4 {. X8 \ d) H( z }
uint32_t i, n;$ @2 R: d7 A! d- I2 R' B# H
//(void) argument;
( ~: z8 Q4 r6 V; \; ]' ?
//timeout = osWaitForever;
+ `% D, e& U# c% v6 f9 h0 v
//for (;;) {6 \" c2 h' G4 s% P' ?$ d; S
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);/ ~8 [" V% h; e" C; a6 s8 T3 G0 F9 z
if((SWO_EventFlags & 0x01)==0)return 0;
flags = SWO_EventFlags;
SWO_EventFlags = 0U; 1 _- {( e4 k( {3 C
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
//timeout = SWO_STREAM_TIMEOUT; 这里是对于进入了SWO_CAPTURE_ACTIVE状态时就把线程超时设置为50毫秒,大概意思应该是osThreadFlagsWait到达这个超时时间后,不管标志是否切换为1U,都放行SWO_Thread调用一次,timeout = osWaitForever时相当于无限长的超时等待1U标志,对RTX不熟悉,不知道是不是这样子/ G2 r* w& R$ I' ?6 x
;
} else {% k$ ~% u" s( Q/ U5 L
//timeout = osWaitForever;
flags = osFlagsErrorTimeout;5 B4 n" |& K. A) ]# X/ Z/ X
}
if (TransferBusy == 0U) {
count = GetTraceCount();
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);; C b( z: i9 A6 J
n = SWO_BUFFER_SIZE - index;1 B: _3 j5 T* Q
if (count > n) {" U5 q$ Z/ y; f+ o
count = n;
+ L8 l e* l: t/ h& ~: z1 ^
}' z' `6 M, {; b) b. e& ^' w# B/ ^
if(count>USB_BLOCK_SIZE)# g- K, J2 S% J1 |% t0 {
count=USB_BLOCK_SIZE;8 W6 X: y2 B2 k8 z$ N+ P4 |3 F
if (flags != osFlagsErrorTimeout) {9 I1 j7 |1 U2 ~" ~! W7 f R) N
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);
} else {" P- H. K* k" o2 h
n = USB_BLOCK_SIZE - i;
if (count >= n) {
count = n;; m6 ?' f* n- E" ^
} else {
count = 0U;
}
} g: a$ ~' w, V
}
if (count != 0U) {
TransferSize = count;
TransferBusy = 1U;" X2 a) q% J; Q4 d; w: ^6 E e
SWO_QueueTransfer(&TraceBuf[index], count);
}
}
}
//}) Z1 {% t" y5 r/ O8 w+ b, p
return 0;( I8 a) \! J' R4 _* Q: M0 d
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.+ `9 Q$ C: }) V' ]
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
static volatile uint32_t SWO_EventFlags=0;+ |+ f- o! V/ N1 C; i1 H
static volatile uint32_t timeout=osWaitForever;- y0 N; ]( H/ |' ]# w' Q# |
static volatile uint32_t timeWait;! v7 z6 e8 b+ y8 a7 y1 N6 k! Y
函数改为这样( R0 F3 S" B9 E l/ t
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;( L: m; T( I) U8 |4 j1 R% ~) ]
uint32_t flags;5 V Z8 E! J$ ]" X5 e
uint32_t count;
uint32_t index;
uint32_t i, n; r9 F! [5 d5 E2 u l( O5 |' s4 N
//(void) argument;- ?% X0 q. X* N( ]7 e1 Z
//timeout = osWaitForever;
4 f2 {1 _/ L# k2 u
//for (;;) {
//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;, q2 ~& \/ y4 Y1 f
}8 I# h* Z8 b' I
flags = SWO_EventFlags;
SWO_EventFlags = 0U; * t" ?/ T9 }+ o E+ N. b
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {9 Q1 {$ p0 B8 y" j
timeout = SWO_STREAM_TIMEOUT;
timeWait=DWT->CYCCNT;- B, S5 C% E& j& O
} else {
timeout = osWaitForever;. l. ~# n0 t- N
flags = osFlagsErrorTimeout;
}# o2 C& X* Z ?% O! E6 ]/ Q
if (TransferBusy == 0U) {$ G& D- O. P/ ?3 }1 H
count = GetTraceCount();' D' ~9 q x) n2 d' I; u
if (count != 0U) {6 \4 c# b; ^3 C' [
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U); U4 y5 F2 m- ?1 u7 s8 F
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;7 C2 r* c4 _( V0 L
}
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;- n$ N: O* L9 Y
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);" H& m% s( A* ~
if (i == 0U) {5 y3 ?0 }8 \% y" N" g8 {9 Z, O
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;" @- G$ D: e. ^, _0 h, N
if (count >= n) {
count = n;( S* R& Y T( Y" j" j" d9 |! d
} else {
count = 0U;
}" t9 r+ \5 J2 u4 E- c% E
}4 ?( N+ g& x& ?' Q% w
}
if (count != 0U) {3 \& I! U* O: S" R! \0 ^
TransferSize = count;, ?) X ?) F$ y5 \- T
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);
}
}
}
//}. n2 l& ~" x3 X* @ g; l
return 0;
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了
) K1 ~! }: E V9 D5 w X
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,少了这个等待时间,能增加端点的传输速率
; P$ L' X9 X7 U2 b3 V: d9 Y
' Y0 W5 H- q1 I
int main(void)$ F) ?7 r9 h, |4 b6 q2 F# R7 A
{; e' ~6 S3 ]; A# W. `
DWT_Init();$ a* K) Z; J% q' j- R6 z1 _$ [
DAP_Setup();
USB_Interrupts_Config();
Set_USBClock();
USB_Init();( y4 \& L* a- S8 J% P/ o! v
//TIM3_Init(35999,0);
//TIM_Cmd(TIM3,ENABLE);
6 z5 N+ U, q2 p% `
while (1)
{8 C% Q$ _# A, E v6 K8 z) c$ M
DAP_Thread();' ?7 k5 {. b% R K- m+ d4 x \
#if (SWO_STREAM != 0)
SWO_Thread();
#endif
}
}
对于DAP_config.h的IO配置我是这样弄的
///@}
// Debug Port I/O Pins) k* w) B4 p$ Q/ ]6 Y
// SWCLK/TCK Pin GPIOA[6]
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198
#define SWCLK_TCK_IN *( uint32_t*)0x42210118
// SWDIO/TMS Pin GPIOA[7]9 \& }3 P. r0 Y M
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C9 P( C5 V! @+ O) _
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C2 Z- M' A, g( w
7 s0 y( E2 z( \! U( o* W; l. i
// SWDIO Output Enable Pin GPIOA[7]* M5 u' W, ?$ p
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 1; \* }' }6 r. ^- ~# u: c( K5 s$ i3 U: \
*(uint32_t*)0x42210074 = 1; \
*(uint32_t*)0x42210078 = 0; \; \+ ~6 L( b! ~% R4 Q7 u
*(uint32_t*)0x4221007C = 0;}
: C* i9 h6 g C( E
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 0; \2 m& N7 {2 z0 a, V% B% R: P4 J
*(uint32_t*)0x42210074 = 0; \
*(uint32_t*)0x42210078 = 0; \. S# F; ^# `6 |$ G3 a; l
*(uint32_t*)0x4221007C = 1; }) Q* [- {1 R- }4 ?4 Z
// TDI Pin GPIOA[8], K% v2 @+ l0 M8 J
#define TDI_OUT *(volatile uint32_t*)0x422101A0$ M3 Q+ t X, @( V$ }) D2 O- w
#define TDI_IN *(volatile uint32_t*)0x42210120( \$ M2 `: F5 T) R) S& |. X% J/ u3 {
( u5 o7 ^2 Q5 F( W$ u
// TDO Pin GPIOA[10]
#define TDO_OUT *(volatile uint32_t*)0x422101A8$ M2 j1 r4 C' R& u7 h; L
#define TDO_IN *(volatile uint32_t*)0x42210128" S1 G `+ ~/ L: H- W
1 e% q; S- [4 K( d9 Z+ @; l( k# y
// nTRST Pin GPIOB[3], R8 {# C) u8 Q6 w3 G
#define nTRST_OUT *(volatile uint32_t*)0x4221818C
#define nTRST_IN *(volatile uint32_t*)0x4221010C3 F# |( B B4 o/ j9 n. e/ F8 L
// nRESET Pin GPIOB[4]
#define nRESET_OUT *(volatile uint32_t*)0x422181906 L# C {2 V% y# M2 p
#define nRESET_IN *(volatile uint32_t*)0x422181101 O4 L5 E! Q, s3 c" c4 @7 C
3 T! c {! K4 K8 n8 t9 O. |
// nRESET Output Enable Pin GPIOB[4]; i, H( m$ o1 K4 S5 C1 O# W
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \5 e( V# r% U" R, r9 \8 S8 d2 r- l
*(uint32_t*)0x42218040 = 1; \
*(uint32_t*)0x42218044 = 1; \
*(uint32_t*)0x42218048 = 0; \1 p* {) ~+ j# S7 ? B
*(uint32_t*)0x4221804C = 0; } . ?$ y$ O" l" e. O" x" t- T' o
5 }: C* d, n( }4 ~" w. o: j
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \( Z+ e. L' l% E) u" ?8 v K
*(uint32_t*)0x42218040 = 0; \& _2 b/ e9 K. z1 d/ ]
*(uint32_t*)0x42218044 = 0; \
*(uint32_t*)0x42218048 = 0;\
*(uint32_t*)0x4221804C = 1; }! S7 ^% V4 k9 C$ ^; T
2 W+ o0 y w% ~! n
5 S- L0 ?6 j5 l
// Debug Unit LEDs
// Connected LED GPIOC[13], [; o/ @" k/ C- f3 }
#define LED_OUT *(volatile uint32_t*)0x422201B4+ Q: e) a, } {; ~$ J) p; ]& B
#define LED_IN *(volatile uint32_t*)0x422201340 q) M' D( N# r8 `' {2 R! |- d: v
$ `) ?& i+ }( g @1 |3 p1 ~4 A, W
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \8 u6 a8 e: O% P+ w) H, L9 G
*(uint32_t*)0x422200D0 = 0; \( ^& l$ R* U) i- L( c& Z8 d8 y
*(uint32_t*)0x422200D4 = 0; \ T, G" G5 O0 ?7 s- M4 f
*(uint32_t*)0x422200D8 = 0; \, ~6 W/ z) ~# h* c" ]5 m, U3 l
*(uint32_t*)0x422200DC = 1; }" }- c; P u* b9 F: ]
// Target Running LED Not available6 l+ g0 q8 S/ g
. M" S7 B- o9 ~* N6 ?
// SWCLK/TCK I/O pin -------------------------------------! f7 \6 L5 |# u' [8 ^
/** SWCLK/TCK I/O pin: Get Input.4 p5 h$ W# J: b" ?" h- Z& J) R
\return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/1 T* |, R# _0 B1 b. @- k. x
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return (SWCLK_TCK_IN);
}
E! r$ O1 u: `" c( R3 x
/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {! z( w+ T9 W* R9 H0 M* k- i1 j
SWCLK_TCK_OUT = 1;3 e" X) ~7 K" w! f5 o; P
}8 D" S* f. h- Y. n& {/ V, n
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level./ Y4 Z) `- G- R( w" R" u( S. l. }
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {9 e: l7 C- g# ^7 ?( e3 O0 s0 }
SWCLK_TCK_OUT = 0;. j6 `# S+ O9 k& l
}; P, i- c! l. R* U# x
5 n" ]7 O w b7 G2 u
4 p; D$ R9 W" B2 s# {6 a
// SWDIO/TMS Pin I/O --------------------------------------6 ]( o9 W( _% w; d" r* c% z* X( Z" J \
$ Q: ~$ R( K5 E) F; e
/** SWDIO/TMS I/O pin: Get Input.3 V( d9 k$ t H% J5 R- R
\return Current status of the SWDIO/TMS DAP hardware I/O pin.$ n8 \1 `1 @) M& t& I: v+ q4 |
*/7 B$ a$ k1 w" [$ k% }* I
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (SWDIO_TMS_IN);
}8 F5 [" D' D& a) T/ u
8 \9 V0 i8 Y- j/ t( t+ M/ a L
/** SWDIO/TMS I/O pin: Set Output to High.' f0 h& G2 W8 x
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {
SWDIO_TMS_OUT = 1;* y- Z2 B; Y1 V" Z( f; n; h0 ]' g
}* z1 w0 j A4 } y0 x3 Z* l; v3 `
/** SWDIO/TMS I/O pin: Set Output to Low.3 L* N W$ m$ B5 a* F e' o! K/ u+ k
Set the SWDIO/TMS DAP hardware I/O pin to low level.6 h2 G: C* V9 m# q/ _- t
*/& G3 P" X3 Q+ Q$ n/ Y9 t$ b
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {; J; R; }' v$ W. x( i2 d
SWDIO_TMS_OUT = 0;; [, W0 q: {2 V8 X* P% o
}+ x3 ?% ^8 ?! H
3 Y9 E+ G. Q$ N) i: p
/** SWDIO I/O pin: Get Input (used in SWD mode only).: o, d! Y, h% ~ `/ i
\return Current status of the SWDIO DAP hardware I/O pin.
*/# @- E6 ] t6 P% l6 `
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return (SWDIO_TMS_IN);
}# ^* b0 h8 r% a. g6 u6 f/ Z9 F
/** SWDIO I/O pin: Set Output (used in SWD mode only).8 G; b1 r' r/ U: y, t1 u8 E7 s8 v
\param bit Output value for the SWDIO DAP hardware I/O pin.0 u& Q/ p& i' e; {; P% q% c3 w
*/( ~) w. Q& N, A, p* I" a8 C* @, ?8 _
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
SWDIO_TMS_OUT = bit;1 O5 K9 M, u$ V% [; q& h( ]" [
}
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).& K' N; O: z% N+ z( a
Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {5 m0 ]% j1 C3 a6 f7 g5 z, @. V
SWDIO_Output();
}
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).2 I( ~5 k' w# ?; f7 W2 c4 c; D
Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls.* Y/ w% o# E7 q9 V. y
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
SWDIO_Input();
}4 c6 M. A0 I- {) R" f
楼上有的说弄无线,其实无线也就是PC<->USB<->无线模块A<->无线模块B-DAP,数据传输的速率主要是无线模块之间的速率限制了,也是非常简单的7 P7 \ s9 Y8 v* \
即单片机先做好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工程,但是编译下载后无法使用。