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发出复位命令。- Q9 F$ n5 Y' S% p5 j: y
Y3 }+ _' \6 I+ L
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。 y0 w5 S0 p9 H( B R* ]6 n
9 f8 t* H: y$ A0 x
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。 * C( W' j9 V1 s' U6 ]9 d: J. N- L, U$ o
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。. r- m; o0 V) y3 Q% h
1 L3 F; o' X1 X6 g: t
?) s( a& }! Q4 L# \5 h$ c( J
/**' U+ W% ^4 m4 l! q
******************************************************************************
* @file usb_endp.c
* @author MCD Application Team
* @version V4.1.0
* @date 26-May-2017
* @brief Endpoint routines% t6 i3 e( q; d8 s% W
******************************************************************************
* @attention
* H: l% Z q) Z$ _. x3 Y6 i$ }
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*: j9 v2 Q4 P- E% a
* Redistribution and use in source and binary forms, with or without modification,
* 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,# r+ @3 R( {" a& Z6 R0 ~
* this list of conditions and the following disclaimer in the documentation, r* c- o( Q7 h r4 j
* and/or other materials provided with the distribution.: ~! f4 A/ [: N' Z0 V4 b" [7 ~) M; C
* 3. Neither the name of STMicroelectronics nor the names of its contributors7 q. c# G7 i' p B' J
* may be used to endorse or promote products derived from this software- R, M* u) n& a$ B4 H' e
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE9 ?: v1 v6 j$ q8 e& I3 d# J
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE; Q# G' w8 e( U. h9 |8 b- v+ [
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR# Q$ C- t% q" p3 n3 Z' N6 Z
* 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.
* C: t, H* P) S* Z1 ~8 |: ]* _
******************************************************************************. y- z9 R" q8 ]! q3 r
*/
$ B" h' N' J0 O0 @8 j& u; c- A
/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"
#include "usb_lib.h"( q6 ]. d$ h0 q X
#include "usb_istr.h"
#include "stepper.h") k1 Z1 D/ }% U! @" W8 Z
#include "string.h"8 x5 y+ a8 [9 j) D0 N
#include "DAP_config.h"
#include "DAP.h"" G% F2 P5 p9 M: Q# x
5 D# e$ ]! A0 [% T D0 o0 x2 x% K
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/) o& f: y/ Q" j0 `6 w f: `* i- Q
/* Private variables ---------------------------------------------------------*/
static volatile uint16_t USB_RequestIndexI; // Request Index In
static volatile uint16_t USB_RequestIndexO; // Request Index Out3 x. a, F$ n$ ], }1 K
static volatile uint16_t USB_RequestCountI; // Request Count In
static volatile uint16_t USB_RequestCountO; // Request Count Out+ V7 |0 S8 u* p I g% O
static volatile uint8_t USB_RequestIdle; // Request Idle Flag
2 y* S5 m, W9 i) g$ j1 |$ f
static volatile uint16_t USB_ResponseIndexI; // Response Index In+ c1 w. ?8 j* j" x- e
static volatile uint16_t USB_ResponseIndexO; // Response Index Out1 f3 `" ?: j; F2 ~9 n
static volatile uint16_t USB_ResponseCountI; // Response Count In
static volatile uint16_t USB_ResponseCountO; // Response Count Out2 n# ?* O* u/ [
static volatile uint8_t USB_ResponseIdle; // Response Idle Flag# v7 _% s( w; j+ {, O N, b. b1 a0 o
static volatile uint32_t USB_EventFlags;/ ~7 l& C8 ~$ o: |7 q! N0 t' B
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) _1 v) l2 O; r1 O! }% B
static uint16_t USB_RespSize[DAP_PACKET_COUNT];
) H- @- P$ o& _# b+ l9 ?
/* Private function prototypes -----------------------------------------------*/1 E- x# Y! k0 p# j% n! }
/* Private functions ---------------------------------------------------------*/0 w% v' l- X4 p. `
/*******************************************************************************4 A1 G6 j9 ?! q0 s' ~4 O' F
* Function Name : EP1_OUT_Callback.
* Description : EP1 OUT Callback Routine.( I9 {9 P p5 ?
* Input : None.
* Output : None.
* Return : None.9 V* `" R/ x% g7 M: }( p
*******************************************************************************/+ S4 P* q! R: y0 [
void EP1_OUT_Callback(void)
{- ]+ o1 e( t9 g+ {; S! y
uint16_t n;, r5 I; J) X) p0 b J3 `4 Z0 k
n = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);* m, @% C: k0 q. V& S
if(n !=0){
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {
DAP_TransferAbort = 1U;9 n A6 c2 x# _2 I9 W
} else {
USB_RequestIndexI++;
if (USB_RequestIndexI == DAP_PACKET_COUNT) {6 V# t3 f- b& O$ [1 g
USB_RequestIndexI = 0U;" ], I6 n2 r) b& Z2 C
}8 K6 l6 s4 |5 x% S# i6 j* r3 D
USB_RequestCountI++;- U/ [: e2 A- |6 _" {; e
USB_EventFlags = 0x01;
}
} 4 j1 r4 F: Q5 G8 r# @8 w. A
// Start reception of next request packet8 X, Y8 Z0 z) c2 U2 R( K0 U7 ^
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
SetEPRxStatus(ENDP1, EP_RX_VALID);/ X& U' f/ G# t
} else {
USB_RequestIdle = 1U;$ q' U6 ^) A- ?) Z
} ' D% _8 n5 t; K/ A4 f+ D" O' f
}
+ F D* C' L& |( [/ U- o5 t
/*******************************************************************************( L8 c: g0 `4 {' f- E
* Function Name : EP2_OUT_Callback.
* Description : EP2 OUT Callback Routine.9 [- w7 n( f2 h2 T! s# Q
* Input : None.
* Output : None.2 b$ m0 W, X' ^$ o, I; [4 e3 [6 ^0 Q/ j
* Return : None.! H0 P; n6 c% \
*******************************************************************************/, J$ K+ t; n% ?6 u1 e M1 f
static volatile uint32_t TX_n;
static uint8_t *pbuf;. ^ E0 Z$ ?- ~( x
void EP2_IN_Callback(void)
{
uint32_t a;) u2 z, t* A% B2 y2 A b& Q4 D
if(TX_n>0){
pbuf+=64;
if(TX_n>64){
a=64;2 a" v' a2 g" \+ d% O! U
TX_n-=64;
, q, h( r2 w- v; S3 D- P9 i
}else{' a( _# l$ R5 m6 c/ _
a=TX_n;6 X# v# ?& b0 t0 n0 T" M) N: Y
TX_n=0;
}
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);5 ]$ w$ t: L4 q# J& e3 F% x. H) H+ ~3 T
SetEPTxCount(ENDP2,a);) s6 Z6 `- {( X+ i- V
SetEPTxValid(ENDP2);4 x/ q2 K/ |9 l
}else{& H! E& z, W0 @; r$ w/ q9 S
#if (SWO_STREAM != 0)
SWO_TransferComplete();
#endif
}
}
/*******************************************************************************
* Function Name : EP1_IN_Callback.0 K; K5 e, f! }( l5 V* N6 |( J& e
* Description : EP1 IN Callback Routine.9 m' V. ~; ~. m; P
* Input : None.0 B4 K% P& w' i! {/ \
* Output : None.1 P3 ]/ `& T5 p8 \1 ?$ O) {$ I/ ~
* Return : None.
*******************************************************************************/1 y, D: ?8 z# n" A! ~
void EP1_IN_Callback(void)3 |/ i- ?9 w4 r/ p+ g c5 O' @
{% m' c3 N7 }) o: b* h
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back2 h* V/ w V5 d/ L U: y3 t; z. M
UserToPMABufferCopy(USB_Response[USB_ResponseIndexO],ENDP1_TXADDR,USB_RespSize[USB_ResponseIndexO]);. `9 u$ L8 o# u1 A* \6 c% k) `
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);
SetEPTxValid(ENDP1);
USB_ResponseIndexO++;4 q s7 C: V" |# y4 {. o# S
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {7 j! s9 V0 ]0 Y6 S# C6 {
USB_ResponseIndexO = 0U;
}
USB_ResponseCountO++;: G5 @/ h( v# U f( K* Z
} else {* C3 J+ U9 q5 I# X0 Y6 c$ r4 V% p
USB_ResponseIdle = 1U;; s1 w; f# L+ ^+ Q- o1 @
}
}
// Called during USBD_Initialize to initialize the USB HID class instance.$ t7 ^+ M" A% P8 a
void DAP_FIFO_Init(void)
{1 R; e% Y. ^1 J _
// Initialize variables
USB_RequestIndexI = 0U;" |1 J% U+ U4 r' i! W0 O _
USB_RequestIndexO = 0U;
USB_RequestCountI = 0U;9 d. Z) v7 Q! a4 e3 R
USB_RequestCountO = 0U;
USB_ResponseIndexI = 0U;
USB_ResponseIndexO = 0U;' O4 m5 i8 B/ s1 T, P) `
USB_ResponseCountI = 0U;8 e7 ]2 \" M9 V' _ }
USB_ResponseCountO = 0U;
USB_ResponseIdle = 1U;
USB_EventFlags = 0U;" A! k$ o+ f3 v
}
& }$ x- h6 ?) l8 {1 p, U3 r
uint8_t DAP_Thread (void) {
uint32_t flags;* Z. _) g( Z1 ~* N6 h% k" V
uint32_t n;
//for (;;) {
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);
if((USB_EventFlags & 0x81) == 0)
{
return 0;
}) u8 T9 q/ [ j0 c. r% F
USB_EventFlags &= (~0X81);9 m! g- l: q7 [& W
/ X' h% F/ k0 ]# j: a+ H
6 A1 L$ t+ F! w( g& X1 W
// Process pending requests
while (USB_RequestCountI != USB_RequestCountO) {1 E$ O" Z( b: V5 `% X
//if (USB_RequestCountI != USB_RequestCountO) {
// Handle Queue Commands
n = USB_RequestIndexO;. g4 }4 e T: T, R$ |4 _
while (USB_Request[n][0] == ID_DAP_QueueCommands) {7 u6 Y# M0 ^8 g4 n- U Y' K: t1 {3 T
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {
USB_Request[n][0] = ID_DAP_ExecuteCommands;' K v- n4 J k9 u" C
n++;
if (n == DAP_PACKET_COUNT) {8 b: q% U8 s, |2 P' @+ {& c
n = 0U;
}
if (n == USB_RequestIndexI) {2 X/ y8 h" @. A
flags = USB_EventFlags;3 l& [: q( R; {! g/ A9 i ]6 x" ?
if (flags & 0x80U) {
break;* u0 b+ m' `1 |
}
}( w h# D% E- s X: z* q
}5 A C; r: F U! h
@4 G) m, p' b& ?3 {2 ~7 U
// Execute DAP Command (process request and prepare response)9 P s2 q* x- C5 A
USB_RespSize[USB_ResponseIndexI] =. g8 t9 x! ?$ M
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);8 a& _4 E. w% _$ w2 k2 @
: ^* X$ O6 ~* M0 Y9 `% L
// Update Request Index and Count
USB_RequestIndexO++;- H( ?8 ]. c. E8 J5 F& ~2 x
if (USB_RequestIndexO == DAP_PACKET_COUNT) {
USB_RequestIndexO = 0U;
}
USB_RequestCountO++;
if (USB_RequestIdle) {
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
USB_RequestIdle = 0U;
SetEPRxStatus(ENDP1, EP_RX_VALID);
}( p, r* c+ z2 u8 Q% b; z- }- `/ g
}
// Update Response Index and Count
USB_ResponseIndexI++;
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {
USB_ResponseIndexI = 0U;
}% ^7 W; n) M6 i0 ?1 x' Z3 [/ z
USB_ResponseCountI++;$ _8 v3 B5 ~4 G# U [
if (USB_ResponseIdle) {7 T0 ]+ r5 g {! R3 p1 o& |5 ?
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back9 K1 Z5 I' @' i/ \( l7 k& ~6 O
n = USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) { m$ ]* N+ F" G: s& y9 {. U
USB_ResponseIndexO = 0U;% R1 i) |2 e: k+ w/ v
}' z0 I2 F6 f- u4 `1 C
USB_ResponseCountO++;
USB_ResponseIdle = 0U;: L) c$ @5 J4 \0 I4 Y4 p4 |
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);
UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);
SetEPTxCount(ENDP1,USB_RespSize[n]);
SetEPTxValid(ENDP1);
}
}
}1 T. t, M7 J: {6 w9 @' I
return 0;! G5 G9 U- o5 v% I6 l6 H5 L
}! {3 V, `# |7 w5 u3 |
// SWO Data Queue Transfer
// buf: pointer to buffer with data* |9 H) l" ~/ Y
// num: number of bytes to transfer
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {" z, N& U6 r% z% x/ w( Z; @1 W
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);! g# Q! D' }' K" j9 [* q# D% J3 T
uint32_t a;% p4 s/ a. C+ i. s! _, X
if(num>64)" ~. \ y1 |+ v, e
{
a=64;: b/ n9 i1 n1 l2 a. q9 `
TX_n=num-64;
pbuf=buf;
: V0 _! j( [$ f
}else {
a=num;
TX_n=0;: D6 e5 B5 K- A8 e- L
}
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);0 @7 o* B, g2 v/ j4 I6 u+ P' h
}4 M2 ^ {! ~4 }& b4 ~1 d; b7 q
// SWO Data Abort Transfer8 F7 r* G" D V4 o' s9 D& \( c$ V
void SWO_AbortTransfer (void) {) q N9 ]+ x4 o8 A" P W' i. U
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));
//SetEPTxStatus(ENDP2, EP_TX_NAK);
SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxCount(ENDP2,0);. U- p! p4 I& t- l" j, L. V
//TX_n=0;
}% o$ p9 M* i( c# ^: v) |
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/9 B* j/ o8 O, |& I
) z/ r+ J" s! G* {9 S
移植大概是这样的,利用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里面没声明这个寄存器,只得自己定义一下了& d( e- @- ]; F) n6 ?
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {. |2 U% G, w4 ~" s( c0 Z: c" `
return (DWT->CYCCNT);# G y* v9 v. Q7 n
}
void DWT_Init(void)
{: _4 i. [3 j$ J) @ L' g$ l
/* 使能DWT外设 */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
/* DWT CYCCNT寄存器计数清0 */
DWT->CYCCNT = (uint32_t)0u;2 X! E2 ` o5 U" Z/ F
0 P7 ]$ ^% L6 t; |; \
/* 使能Cortex-M DWT CYCCNT寄存器 */+ q8 Y4 _1 ]/ b; Z% W5 `) K
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;0 i1 f' x4 a4 }9 N* l, P* r
}
4 b6 x/ _! ?: N4 r: W7 [
然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率( w4 ]( @5 `4 K8 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;
在SWO里每一处调用osThreadFlagsSet的地方都改为如:
//osThreadFlagsSet(SWO_ThreadId, 1U);! L! k |3 U2 T# b* p
SWO_EventFlags = 1U;( i% g) ?. I4 t$ T# g; [$ [
8 X/ Y3 R" s. `' i9 G& K7 V( ^
! p" z1 n1 k) V+ E
// SWO Thread
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;
uint32_t flags;3 o) Q" n% Q6 J/ n' _
uint32_t count;
uint32_t index;. I% q5 i3 p9 E
uint32_t i, n;
//(void) argument;
# t' z( S1 O; k9 ?& s, d; |
//timeout = osWaitForever;
0 ^ G5 t$ X2 ]9 Z
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);1 }8 r, R# V& E: x# V" f3 x5 \
if((SWO_EventFlags & 0x01)==0)return 0;
flags = SWO_EventFlags;) @7 e- C+ ^4 f
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {( [0 o% @7 {" Z* C0 D% Z5 N
//timeout = SWO_STREAM_TIMEOUT; 这里是对于进入了SWO_CAPTURE_ACTIVE状态时就把线程超时设置为50毫秒,大概意思应该是osThreadFlagsWait到达这个超时时间后,不管标志是否切换为1U,都放行SWO_Thread调用一次,timeout = osWaitForever时相当于无限长的超时等待1U标志,对RTX不熟悉,不知道是不是这样子
;
} else {
//timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}
if (TransferBusy == 0U) {6 [# f% B, |8 S9 W, W
count = GetTraceCount();3 M9 x$ J0 |9 S; ^7 u+ [% D7 |
if (count != 0U) {$ B* ~- o! F; i
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);& D4 T( Q& _3 q' u! g1 @* m" H; C
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n; p- ?! V1 L1 Q6 t
}
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;( ]" U+ [1 T h% J+ n$ b8 s
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);+ B/ |. M3 L/ j+ F1 b5 Q
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);+ ]; H, k) } g' M
} else {4 E8 R# R+ j( ^6 }1 J6 Y
n = USB_BLOCK_SIZE - i;) d; e- C$ l. X5 C& U! F) N& I, h, K
if (count >= n) {
count = n;
} else {
count = 0U; R6 }0 \/ i1 |6 E' k
}) T; _/ [0 L% M' ^
}
}
if (count != 0U) {# N4 \1 A# f+ {+ d" y, B) p
TransferSize = count;
TransferBusy = 1U;* v, e e0 z% a3 Z0 v
SWO_QueueTransfer(&TraceBuf[index], count);1 H* ^$ z& A1 W7 G! I& T
}$ _' C8 F" u! H9 m9 \
}
}8 A4 ], p$ g' e2 O. u
//}1 \8 o! Q- i$ E& G! |3 L: n/ @! g: J- y
return 0;
}/ c' W% }1 x/ Z+ B- H# Z' J
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
static volatile uint32_t SWO_EventFlags=0;
static volatile uint32_t timeout=osWaitForever;
static volatile uint32_t timeWait;! D0 s( v p8 b( W% G! i
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {$ A: H% `$ {* i3 F: c
//uint32_t timeout;
uint32_t flags;
uint32_t count;2 L3 w/ ^4 V; D/ L' n0 N7 h
uint32_t index;
uint32_t i, n;# F+ i* ^7 D8 W9 k$ q+ `: K2 p. B0 w
//(void) argument;
//timeout = osWaitForever;
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if((SWO_EventFlags & 0x01)==0)4 G- J# f* \3 w3 z1 V5 h" R
{
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了
return 0;
3 m0 B( y0 r" e$ |+ ~ f
}
9 @- M5 B: u" g' Y& r6 k1 q S
flags = SWO_EventFlags;
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
timeout = SWO_STREAM_TIMEOUT;0 L7 Z' o$ C1 v6 w2 M, ^4 @! O
timeWait=DWT->CYCCNT;
} else {
timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}
if (TransferBusy == 0U) {
count = GetTraceCount();/ |" C) b( ]2 c4 \" o
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U); n& z7 E- Z) D% W
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;
}/ _- ~2 T/ `( Z
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;4 B8 [8 [7 Y3 ?8 w: X
if (flags != osFlagsErrorTimeout) {. u/ K5 n1 l6 A% O9 j Y
i = index & (USB_BLOCK_SIZE - 1U);# f6 I* D1 G; p# |
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);" r/ A8 R0 F4 u! h3 ?7 p; g
} else {2 k+ s, S, {0 m2 V3 l
n = USB_BLOCK_SIZE - i;9 Y w; |. x) f' o6 c1 R! q
if (count >= n) {
count = n;( G( _2 V: @1 [ B
} else {/ ]. m9 r. o/ ^7 c$ V% G: m
count = 0U;
}5 r0 Z! p x$ o5 @6 ~0 L8 }
}9 W7 G5 _4 A# N$ C+ A
}( c# @" w( d: \
if (count != 0U) {
TransferSize = count;& w' g+ r9 E D# }2 w1 w
TransferBusy = 1U;& I$ r, M5 k- C- ?6 x# ]% K% W
SWO_QueueTransfer(&TraceBuf[index], count);7 S& p- }$ @0 u5 Z# k! v5 H/ d
}
}
}0 ?8 V, R4 {! j" R/ C0 C
//}
return 0;; B8 L. H) F6 T4 b: B" J, P3 `
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了/ E$ L3 ]2 y+ N# S
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,少了这个等待时间,能增加端点的传输速率1 ?, W6 S- g) ^
+ V: O, C0 T3 R6 e" ?2 p
int main(void)
{
DWT_Init();
DAP_Setup();
USB_Interrupts_Config();, Y$ U1 o6 n# ]6 G" J5 B. q
Set_USBClock();
USB_Init();
//TIM3_Init(35999,0);
//TIM_Cmd(TIM3,ENABLE);
Y9 b. v, [0 d" q- J
while (1)
{( j8 S% b) y4 D- d; g' i
DAP_Thread();
#if (SWO_STREAM != 0)% y" `. R3 h/ j% [ y( Y; R
SWO_Thread();
#endif% Q2 h( G1 _8 h( p6 x. j# l: g
}
}3 K* p$ Q3 U* g- M( o3 X# E
对于DAP_config.h的IO配置我是这样弄的" }, G& O: Z5 U" x% N
///@}2 T8 k! ?( H9 }
// Debug Port I/O Pins
// SWCLK/TCK Pin GPIOA[6]
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198
#define SWCLK_TCK_IN *( uint32_t*)0x42210118: h* B+ }- _' m+ N
// SWDIO/TMS Pin GPIOA[7]
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C j; S# [% \1 ~) w% y. r( \( `8 a
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C
* H4 o m `3 a( O) ?9 K' ?
// SWDIO Output Enable Pin GPIOA[7]- D% [7 t. ~- o# v0 s
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \1 D4 h h# W; O9 y4 h
*(uint32_t*)0x42210070 = 1; \$ N J# U) ]- z: k8 U
*(uint32_t*)0x42210074 = 1; \( ]3 l- |5 U! \/ @" U/ y
*(uint32_t*)0x42210078 = 0; \
*(uint32_t*)0x4221007C = 0;}
" }7 k) ~* r) m" j Q) a6 q3 y
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \% C3 o7 w7 V# @/ e4 d' b
*(uint32_t*)0x42210070 = 0; \
*(uint32_t*)0x42210074 = 0; \
*(uint32_t*)0x42210078 = 0; \9 x% R9 s: F9 {
*(uint32_t*)0x4221007C = 1; }' S$ G2 ^9 H9 J& w3 H
6 b3 X! r1 _, D! O* T* |
// TDI Pin GPIOA[8]+ V2 z9 y9 N% g6 n1 z+ q* ]0 N5 \
#define TDI_OUT *(volatile uint32_t*)0x422101A0
#define TDI_IN *(volatile uint32_t*)0x42210120
" i- q$ j, {: H7 N1 Y
// TDO Pin GPIOA[10] }( W. m6 E% d% n( U! E) `- v
#define TDO_OUT *(volatile uint32_t*)0x422101A8
#define TDO_IN *(volatile uint32_t*)0x42210128. y) U" ^# R" Y) \6 @; w9 L
- }- ^% E0 j9 [: m6 v
// nTRST Pin GPIOB[3]" i7 x7 _: c8 I3 X+ Y, \' `; F
#define nTRST_OUT *(volatile uint32_t*)0x4221818C8 d4 K5 ?5 E4 O0 K# G' ?
#define nTRST_IN *(volatile uint32_t*)0x4221010C/ e/ F9 ^, }) U% B% `4 L
. B. h/ S9 \( @1 O# o; Z
// nRESET Pin GPIOB[4]
#define nRESET_OUT *(volatile uint32_t*)0x42218190( ^ d) \4 @* g1 P" g. o3 m
#define nRESET_IN *(volatile uint32_t*)0x42218110
4 z( X' h- f1 w" {
// nRESET Output Enable Pin GPIOB[4]% g. w; B4 R$ Y( {4 t+ L
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \% G- W7 a5 }( s2 p3 B" r* t- j( |% q
*(uint32_t*)0x42218040 = 1; \1 d9 w4 r9 z) ]/ H5 r" I9 v
*(uint32_t*)0x42218044 = 1; \+ k4 O) F2 w: ]& i0 r( z
*(uint32_t*)0x42218048 = 0; \
*(uint32_t*)0x4221804C = 0; } / g. f% B2 _. P9 W* o; S! V
6 y, e7 k% r, r0 K9 m3 C4 N# ~% t
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 0; \" V1 }/ @) j( H5 }
*(uint32_t*)0x42218044 = 0; \
*(uint32_t*)0x42218048 = 0;\
*(uint32_t*)0x4221804C = 1; }
// Debug Unit LEDs* p" K1 v+ n( m1 M
// Connected LED GPIOC[13]
#define LED_OUT *(volatile uint32_t*)0x422201B4/ q1 i; f$ ]( c0 l
#define LED_IN *(volatile uint32_t*)0x42220134
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \/ R, A- L4 N3 l
*(uint32_t*)0x422200D0 = 0; \
*(uint32_t*)0x422200D4 = 0; \6 P. S# J8 a, E1 R. O, E4 X4 a
*(uint32_t*)0x422200D8 = 0; \
*(uint32_t*)0x422200DC = 1; }1 \% w: Y, g# g6 K
// Target Running LED Not available% ]& N$ r0 ^9 `4 Y6 N! e
4 y% }+ r. k" u) a9 s8 j0 Q
// SWCLK/TCK I/O pin -------------------------------------
4 X3 U/ r* u- {3 ~& e8 V
/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.8 Q1 K1 o2 ^+ B3 C2 s: i
*/) Y/ @4 E& b- ], H0 r6 t9 Q
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return (SWCLK_TCK_IN);
}' g! `/ ~* _0 V7 o, Y% x7 I' ^5 w
/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/! Q5 v3 N1 \9 G, ^7 e
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {/ P6 M9 p5 `3 q$ K: Q# H
SWCLK_TCK_OUT = 1;
}7 o4 s8 n$ c/ i7 g
, Z* M0 ], v$ S, N* z0 `7 o- F! |
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.2 s( n5 B7 H6 M2 j
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
SWCLK_TCK_OUT = 0;0 G% d/ M9 M& f4 C- c/ p( [. a& G2 b
}
// SWDIO/TMS Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin.8 q/ i U+ v; ~4 U$ d
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (SWDIO_TMS_IN);( l2 x3 T$ Y; e- z3 r
}" f: m' L0 h7 m
* Q- Q5 v% R2 W+ L$ s
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.7 [8 E% ?& _1 C
*/$ s2 J: u' h% r* d/ @0 g* @. e& s
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {/ M- x+ B L' V2 I c) M" m; p8 t. K
SWDIO_TMS_OUT = 1;
}
/** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level., `# N; B( g# o; o4 X
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {
SWDIO_TMS_OUT = 0;
}
; o( e' j- f1 N- c8 D
/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin.5 i9 ^% `' }2 V8 S9 @- M
*/+ [" l7 u( f$ N3 R
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return (SWDIO_TMS_IN);
}
/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin., l) A8 f( g* j" C
*/- P, n" v! S/ D8 e$ e% a" T
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
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. O. P1 {4 K0 K/ n; K: w- r. H
*/% l/ e- B0 a" A+ K) S/ A
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {
SWDIO_Output();
}0 M" J- K& C# g. _
( B; ], ]3 J) N) w: S8 F
/** 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.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {/ t( a6 V( p& o3 U* S+ w
SWDIO_Input();
}' q! V' O1 ~5 Q/ Z; f# K- r
楼上有的说弄无线,其实无线也就是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驱动的大佬可以尝试一下& N* ~: `- g3 ^( {0 `: T4 M
有人将这个工程移植到stm32f4上吗,我在网上找了一个f4的dap工程,但是编译下载后无法使用。