STM32固件库分享,超全系列整理
小马哥STM32F103开源小四轴RoboFly全部资料大放送
【管管推荐】STM32经验分享篇
【MCU实战经验】+STM32F107的USB使用
基于STM32F103两轮平衡小车设计(开源)
STM32F107VCT6官方原理图和PCB
【福利】用STM32库的朋友有福了:STM32F10x_StdPeriph_Lib_V3.5.0chm...
基于STM32F10xx存储器和系统架构经验分享
基于STM32F1的CAN通信之BH1750
基于STM32F1的CAN通信之OLED
我这个是有复位信号输出线nRESET的,不过IDE要懂得向DAP发出复位命令。6 R1 a) X$ \1 f4 Y* Y' t' K
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。, e9 r1 ^; R \% H
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。
; c7 o/ L9 `. w6 h
/**" h3 e6 _: X% z- ]8 c6 k% o6 I
******************************************************************************" y7 Z( ?1 |6 W
* @file usb_endp.c; f. Q: f& O* u q" m P. P
* @author MCD Application Team' R7 Y# c3 O1 q5 Z5 a; I# k
* @version V4.1.0' G7 g( f/ H! o. W. {* g! |1 s
* @date 26-May-2017/ e0 _' C+ ]; ^2 D
* @brief Endpoint routines& u, w$ T' F7 `+ @# F$ U/ L% u+ w
******************************************************************************' j% _7 d. U) r5 l0 @ v
* @attention/ M3 O8 i; s! k
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*1 h4 Z+ o8 o9 I5 G: C; z3 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,6 E' J9 _1 j( s7 \6 Z; w
* 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.
* 3. Neither the name of STMicroelectronics nor the names of its contributors o/ P! E Q1 x+ m
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*' ^. `% o- [( K
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE5 d* U7 v5 {) w* ]/ V
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE* q( q1 d$ Z( T& r$ T9 R
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL8 o+ r9 q. o4 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR; y6 i5 H7 Y' s( H5 p" `
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER! q2 z4 s" ?% d% t: Y6 {2 f
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,3 x" Q0 [: C+ G/ E3 |+ P( @
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE9 i8 F5 j2 m" O& T. ?
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************* B" ^, K) _+ z% Q9 P; m
*/) r9 e: e/ }* R( p0 N
0 }3 t+ j3 ~& J& h9 |4 @. E" g8 l
/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"
#include "usb_lib.h") a6 [7 s1 @! S) i* l
#include "usb_istr.h"
#include "stepper.h"3 l8 M+ v2 J, q. g: t
#include "string.h"
+ W# Z+ T, `& g# L- K
#include "DAP_config.h"
#include "DAP.h"
& j) R, A$ g. g& t9 d: x
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static volatile uint16_t USB_RequestIndexI; // Request Index In; |5 [ E/ A9 Y) N
static volatile uint16_t USB_RequestIndexO; // Request Index Out
static volatile uint16_t USB_RequestCountI; // Request Count In; Z7 g, U6 X' B. X4 {6 R- [1 ]
static volatile uint16_t USB_RequestCountO; // Request Count Out( }" G) P# ~! r
static volatile uint8_t USB_RequestIdle; // Request Idle Flag
4 w. u2 |- o1 Z% o9 U1 ]
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
static volatile uint16_t USB_ResponseCountO; // Response Count Out
static volatile uint8_t USB_ResponseIdle; // Response Idle Flag
static volatile uint32_t USB_EventFlags;- s: o4 F; C5 |7 J! A$ v5 A
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+ e" W/ u6 p9 V$ L( E1 Z
static uint16_t USB_RespSize[DAP_PACKET_COUNT];5 q# ^; M! q d5 a2 X+ ]
# x# N8 p* ^8 E7 K5 t5 [ I
/* Private function prototypes -----------------------------------------------*/$ C E% k3 O @
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************! k2 o, a; K5 r: e) R' A
* Function Name : EP1_OUT_Callback.7 M, @+ x3 V. ?0 i: R# Y
* Description : EP1 OUT Callback Routine.( G, q) n7 x T6 i$ h+ R3 s) n
* Input : None.
* Output : None.5 n* \0 ^2 N" Z1 R; G
* Return : None." Q( t# d$ M. }( ? m, ]# _9 s
*******************************************************************************/6 E7 D% c& J1 W( s; w
void EP1_OUT_Callback(void) I' o9 m- f4 ~5 A! w$ \, \
{
uint16_t n;
7 p0 ^) }. @$ d- Z0 T. V
n = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);: B' F! x- `- s
if(n !=0){ {- D, f7 F4 C& l6 M, U9 I, |. b+ }
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {
DAP_TransferAbort = 1U;
} else {
USB_RequestIndexI++;8 [0 b( G- c, H ~' U
if (USB_RequestIndexI == DAP_PACKET_COUNT) {' S2 F- H7 X/ G/ C! t7 e9 z
USB_RequestIndexI = 0U;
}" H0 o' U4 ]- ], ]
USB_RequestCountI++;/ G+ s" l8 a( O. h# H# N
USB_EventFlags = 0x01;
}3 b# B9 q2 q. c
} 0 w: A) a, H( L' B G
// Start reception of next request packet! [$ a% `( |5 }
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
SetEPRxStatus(ENDP1, EP_RX_VALID);
} else {1 ]; g7 t/ {% y7 P: f$ _2 c
USB_RequestIdle = 1U;
}
}
/*******************************************************************************: E, {: I" f& b
* Function Name : EP2_OUT_Callback.* x5 M/ T* q k+ S0 {: t& s6 V
* Description : EP2 OUT Callback Routine.% n* X3 p! [# G- R! n4 q/ G q: h) l
* Input : None.: {0 R9 L; x$ C6 S
* Output : None.. N8 W8 l. c# K3 ] @
* Return : None.
*******************************************************************************/( C" P& U: n3 N' V; k0 `
static volatile uint32_t TX_n;8 Z" d+ z/ N1 P! h1 i- }
static uint8_t *pbuf;
void EP2_IN_Callback(void)' l) l0 u9 z% p+ D/ V( M
{
uint32_t a;. J& Q+ k3 r6 [ K g4 I) ^
if(TX_n>0){0 D: [: `7 a3 f. s. K
pbuf+=64;
if(TX_n>64){
a=64;
TX_n-=64;2 }( w R) i" B' l& d" ^7 H
}else{
a=TX_n;$ j7 W# c1 t1 p. J2 a; W0 P/ a) U
TX_n=0;
}8 _2 k9 O+ L7 J$ }* S \2 `
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);
}else{6 B/ U! X/ j. K5 ]# X7 X. N) k: S
#if (SWO_STREAM != 0)5 J% _$ _7 S3 L: z( q& _5 z
SWO_TransferComplete(); ~& P# N" R$ T/ w: k+ b* C
#endif
}- F4 a- A* e4 z4 ?7 t2 X7 \
}8 v8 e& K7 w$ _- }
' w- l' }+ |( X$ k$ b1 R6 Q& a: G
/******************************************************************************** v5 d$ L O! r3 W' ]
* Function Name : EP1_IN_Callback.+ R+ q1 ]7 R5 Q, I
* Description : EP1 IN Callback Routine.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void EP1_IN_Callback(void)
{
if (USB_ResponseCountI != USB_ResponseCountO) {. T3 }9 J& X# z
// Load data from response buffer to be sent back
UserToPMABufferCopy(USB_Response[USB_ResponseIndexO],ENDP1_TXADDR,USB_RespSize[USB_ResponseIndexO]);8 g# p' ]" r5 H% J7 W% D; N
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);1 r* v# _ X. K7 J$ |. [
SetEPTxValid(ENDP1);
USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;
}5 P, i$ q' \$ h$ f
USB_ResponseCountO++;
} else {
USB_ResponseIdle = 1U;' k! p0 @/ m7 u' j
} 8 e& c8 r" h B7 b! Y
}
// Called during USBD_Initialize to initialize the USB HID class instance.+ i: Y0 T" Q% R# w' I( t- H
void DAP_FIFO_Init(void)
{; I9 n1 w# a: Z4 f
// Initialize variables
USB_RequestIndexI = 0U;' Q2 r" s7 h; K' A
USB_RequestIndexO = 0U;
USB_RequestCountI = 0U;0 g6 U% Y. H: F, j$ J F
USB_RequestCountO = 0U;9 p. H9 a( r2 y2 F; T
USB_ResponseIndexI = 0U;0 E$ x& \- M" X; P9 t9 m; c
USB_ResponseIndexO = 0U;3 ~! }, G4 D# j* Y- ~( Y+ b
USB_ResponseCountI = 0U;
USB_ResponseCountO = 0U;( Z4 A. t* o: }0 @
USB_ResponseIdle = 1U;- ]; j+ X; Q' G& E; k5 u; L
USB_EventFlags = 0U;
}
uint8_t DAP_Thread (void) {
uint32_t flags;
uint32_t n;
//for (;;) {9 E! t! v2 l( K" y" a/ o' S
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);: a- \/ @# {: n, h/ k1 d# \
if((USB_EventFlags & 0x81) == 0)
{
return 0;
}
USB_EventFlags &= (~0X81);* H8 v: \0 v* @9 o
// Process pending requests+ G0 H" W; z. p
while (USB_RequestCountI != USB_RequestCountO) {# j9 B2 r- R: D
//if (USB_RequestCountI != USB_RequestCountO) {1 Z1 W: \9 v) }, ` q) F4 k% B
// Handle Queue Commands
n = USB_RequestIndexO;
while (USB_Request[n][0] == ID_DAP_QueueCommands) {
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {5 W. {* H0 Z% B1 {5 W2 T- `: D' B
USB_Request[n][0] = ID_DAP_ExecuteCommands;
n++;
if (n == DAP_PACKET_COUNT) {1 ~; ?0 h# Z5 G6 Z: t
n = 0U;$ x9 }; r7 i1 h4 |& F
}8 V) i8 O u! H' P/ |" F
if (n == USB_RequestIndexI) {
flags = USB_EventFlags;' n. v% h( h# Y- f' M( b1 }; q
if (flags & 0x80U) {$ I1 s- [. h$ l
break;
} P' d$ T- [! Y/ R* a0 a# J
}: B5 I; C( V8 e2 J, q
}
// Execute DAP Command (process request and prepare response)) W5 i+ V1 t* q' \- b; ]- T( P% M
USB_RespSize[USB_ResponseIndexI] =6 }$ w" F5 T' b
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);
// Update Request Index and Count( f; N# b Q; s2 a) _3 `
USB_RequestIndexO++;
if (USB_RequestIndexO == DAP_PACKET_COUNT) {
USB_RequestIndexO = 0U;
}
USB_RequestCountO++;
if (USB_RequestIdle) {* j6 `- t) `4 n& R3 L0 U. `
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {. W; u. g# C, ]( D: U2 b
USB_RequestIdle = 0U;' w- D. X" C& y3 d: }- n, M
SetEPRxStatus(ENDP1, EP_RX_VALID);
}
}
6 \& Y$ f6 Z6 G% N. S4 ^
// Update Response Index and Count$ r* X/ O) Z7 E& B7 f V
USB_ResponseIndexI++;
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {
USB_ResponseIndexI = 0U;, R1 J9 i, g6 N9 \8 X
}! m2 a3 p' Y" v3 b, j
USB_ResponseCountI++;
9 S4 X3 ]; d3 O3 Z- @3 d3 d
if (USB_ResponseIdle) {
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back2 V( F6 A f! T) q8 c4 ]
n = USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;$ e. H0 W- g2 q
}
USB_ResponseCountO++;
USB_ResponseIdle = 0U;) |$ |! b1 C; `8 c" n8 X" j
//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);
}
}
}
return 0;
}
+ J' j( S" Q/ B4 |7 C
// SWO Data Queue Transfer
// buf: pointer to buffer with data
// num: number of bytes to transfer# C F( W8 s, x! B7 t# E3 C
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);
uint32_t a;
* I7 Q% c! a1 e# l
if(num>64): W3 n7 V8 c! I* L$ p2 P
{( G, ]7 d- o: u& G9 L6 A+ l
a=64;( |' M5 q$ t [2 V2 w @8 ?3 ]
TX_n=num-64;, G) e+ x% v _5 W9 o$ [0 @
pbuf=buf;
* I# I% _" k/ O8 x1 s
}else {
a=num;3 u/ z5 ?6 |+ K% }5 ?* o
TX_n=0;
}
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);
} f0 u9 d. _& [+ ~* o
9 g4 F- N* g: K; p
// SWO Data Abort Transfer* F) H O+ m w& X, E7 v
void SWO_AbortTransfer (void) {5 ]8 L' O2 o) ?3 X! l& u
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));4 a3 [2 W/ M5 J R
//SetEPTxStatus(ENDP2, EP_TX_NAK);
SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxCount(ENDP2,0);
//TX_n=0;* ~5 S6 b# @* }/ w/ t r
}
/************************ (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时感觉速度还是可以的,这能体现批量端点的好处* t$ L4 T0 b! k9 q6 o
DWT部分即TIMESTAMP的时间参考,由于没使用Keil的核心库,得自己对相应的寄存器进行开启,而且3.5库的core_cm3.h里面没声明这个寄存器,只得自己定义一下了7 z; j+ S) n2 R! C) K' m
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {- r' W6 e( S) R9 z8 V( a
return (DWT->CYCCNT);, |% Z! c" O, u
}$ [' W% Q0 \6 k0 Y7 L7 n
void DWT_Init(void). b7 Z7 Z, q) k9 u! Y
{* w, x1 h1 p( d' ^
/* 使能DWT外设 */' B9 h4 n N1 @4 G
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
/* DWT CYCCNT寄存器计数清0 */
DWT->CYCCNT = (uint32_t)0u;
& C! L5 h! O9 X Z4 G
/* 使能Cortex-M DWT CYCCNT寄存器 */
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
4 J: Y7 g# }' S" G! ?2 M7 `
然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率- }( G# T9 p1 O# ^, v- ^
/ B( ^# E3 C+ y' r5 ~' 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;0 {" n& X( X2 H: B
在SWO里每一处调用osThreadFlagsSet的地方都改为如:6 v7 _! U) `- h: B$ R+ T
//osThreadFlagsSet(SWO_ThreadId, 1U);, F4 ]# @- F( B ^% D# S
SWO_EventFlags = 1U;, W' m2 u+ p: @+ w, W( W
8 X) i* l% n% K- y: M! S
// SWO Thread
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;& Z: h/ t( c. {) {
uint32_t flags;
uint32_t count;
uint32_t index;
uint32_t i, n;" @1 r, U: r4 l1 }& O. ~3 F
//(void) argument;, m2 G. [$ Y4 I2 e
$ {" L- V6 M6 z7 |7 f
//timeout = osWaitForever;
[) y1 k& V& L; t# h6 ^- i6 H `
//for (;;) {0 u% a! W/ L% I9 |; B( V
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);2 G0 y/ K% O1 W/ |; e
if((SWO_EventFlags & 0x01)==0)return 0;
0 r: }0 K2 l& W* Y& I% w
flags = SWO_EventFlags;
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不熟悉,不知道是不是这样子
;+ p. u; Y, t$ K) r' I/ I, n, E
} else {: P4 {+ z; V, S1 h
//timeout = osWaitForever;
flags = osFlagsErrorTimeout;1 L# w' `1 U7 T- f. `. p: y# V" J
}
if (TransferBusy == 0U) {) G$ v9 T$ n+ b5 D6 o: Z+ X
count = GetTraceCount();0 d! E- d( r3 x5 e- v m
if (count != 0U) {7 Q/ v% k! ^! D/ G( i3 f
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;2 w) N6 F! D; v& M, J- f" j
. W+ f# |& e& l9 P8 I+ s
}; y6 L5 A/ c b5 e' |
if(count>USB_BLOCK_SIZE)3 ^; _1 O2 r5 @9 U! E, o2 S
count=USB_BLOCK_SIZE;
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);1 I- k# F z( n0 }5 n" I% c
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;
if (count >= n) {" G5 C9 ^. w7 N% t# w' {0 l% G
count = n;8 e4 J( M4 k; f- t+ I r' p
} else {
count = 0U;
}
}
}4 `6 J- {8 R u0 l& ~8 H! X
if (count != 0U) {8 b: T7 Y+ T0 W/ v5 q; o
TransferSize = count;
TransferBusy = 1U;. B' Y, X% k5 [! s7 _
SWO_QueueTransfer(&TraceBuf[index], count);5 m7 i" R+ k. `# ]4 B
}" E* H* w4 o; k
}, R2 t1 y1 |2 X, u
} d1 w& X& P0 f
//}6 T9 |* j& w E' M; |( W' q
return 0;
}* N* d" h- ]: g& M
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).2 ?" L% l: }- t0 \) ^' ~
static volatile uint32_t SWO_EventFlags=0;) B8 d& W0 J, f
static volatile uint32_t timeout=osWaitForever;* w% |' J3 ?0 p G' i
static volatile uint32_t timeWait;
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;: _1 `1 N. p$ O
uint32_t flags;' ~' C) L+ z1 K- h& @) O! a
uint32_t count;: @5 P. X' g/ K! C9 W9 J! i
uint32_t index;& Y* _' \0 w# X% x* D
uint32_t i, n;
//(void) argument;
& b/ ^; A$ V) j: J# v( r
//timeout = osWaitForever;
0 D1 N7 w7 |& j9 z
//for (;;) {* D6 m7 I+ {6 Z. y8 V/ a2 f
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);2 ]8 c& e) I- g$ w, J! J; S6 G" @" Y
if((SWO_EventFlags & 0x01)==0)6 E3 j0 e* M# t) c% J/ f4 u' l2 O8 W
{
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了
return 0;4 F* r, y0 \5 p* C/ x0 C
}# \6 L6 g- Z" M5 q% S! e
3 H/ n8 E9 C( ~9 b1 V8 O
flags = SWO_EventFlags;4 o7 ?, k6 q- d) k+ V
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
timeout = SWO_STREAM_TIMEOUT;9 C1 Q- d0 J( Y1 Y- B
timeWait=DWT->CYCCNT;/ m# y, u" a5 B8 D
} else {8 F4 p& x8 H+ E6 l$ o
timeout = osWaitForever;* i8 O; x) q3 x+ ]6 i8 m2 V
flags = osFlagsErrorTimeout;0 s, D. I' v; {" X8 a; K" V0 N- O
}
if (TransferBusy == 0U) {
count = GetTraceCount();
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);- ?+ h2 p4 [. p; a" g
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;4 v# W9 L3 x, {
: u9 p; l u' I$ n. M
}! H2 c+ m1 C; z8 K
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;, k7 B# r0 P, v5 i/ Q4 g* M
if (flags != osFlagsErrorTimeout) {+ Y2 m' [# _1 F7 c2 V/ v6 w: s
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {! r9 Z( U; Y1 C. }0 K% x
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;
if (count >= n) {
count = n;
} else {) U+ Z4 C4 o; q9 \ Q
count = 0U;- p) [: F0 M4 `2 @4 r3 o2 j
}9 X/ C; L* S' p/ G
}
}/ S2 F* Z5 O' U
if (count != 0U) {
TransferSize = count;3 f4 x9 e; F/ q* K; X/ Y `
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);1 W* j7 e8 D# m2 a5 H+ b
}
}
}
//} U2 V1 g; I/ f- t ~$ `* l
return 0;
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了- Q; _( u- y' X# v* q
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,少了这个等待时间,能增加端点的传输速率! u5 N: T4 t2 h& {( `( Q5 s
" a) g) O; i. z. N- ^. R) P" i
int main(void)
{& J% s$ C/ b$ n! Z% ^ j M( r
DWT_Init();
DAP_Setup();1 p; K& j2 B5 x6 D
USB_Interrupts_Config();
Set_USBClock();6 ?* f4 y+ P$ U. d6 l' U- Q/ |
USB_Init();
//TIM3_Init(35999,0);9 x4 s+ y3 W1 Y9 C
//TIM_Cmd(TIM3,ENABLE);3 D3 n V! n+ S k8 A+ S& q
while (1)
{3 ^' T% P% K4 ]5 Z/ t: k5 i/ n
DAP_Thread();
#if (SWO_STREAM != 0)
SWO_Thread();' m, R( y! s/ i9 v8 b
#endif! t5 X9 [% J' l% L+ \- {
}# z/ X {# f% W, E
}
对于DAP_config.h的IO配置我是这样弄的 W. \1 ^2 G) v2 |
///@}# {& u% f$ B0 D
// Debug Port I/O Pins
// SWCLK/TCK Pin GPIOA[6]
#define SWCLK_TCK_OUT *( uint32_t*)0x422101982 H) c0 B$ L. i9 ^# `# g
#define SWCLK_TCK_IN *( uint32_t*)0x42210118, x7 j& p2 G W+ n: K
// SWDIO/TMS Pin GPIOA[7]9 S( }/ X& { q5 |( x5 ~$ H1 y
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C- I5 b( S: d0 h
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C# }* W3 ^7 v, g8 D; b9 g1 K s
% J3 N) p/ _% c3 l% F
// SWDIO Output Enable Pin GPIOA[7]
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \7 N R) i, D. b8 z! A$ T3 o
*(uint32_t*)0x42210070 = 1; \
*(uint32_t*)0x42210074 = 1; \
*(uint32_t*)0x42210078 = 0; \- O, |2 L9 a" V# l. i7 \
*(uint32_t*)0x4221007C = 0;}2 Y/ t2 H0 m; V& y+ v
/ H3 T5 N. b! R. }* c/ I" y
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 0; \
*(uint32_t*)0x42210074 = 0; \
*(uint32_t*)0x42210078 = 0; \
*(uint32_t*)0x4221007C = 1; }
// TDI Pin GPIOA[8]9 L' p7 O _/ \, P
#define TDI_OUT *(volatile uint32_t*)0x422101A0
#define TDI_IN *(volatile uint32_t*)0x42210120& E( H" }7 H/ ]. ?# @4 I% v& C6 \3 L) f- {8 Y
// TDO Pin GPIOA[10]
#define TDO_OUT *(volatile uint32_t*)0x422101A81 x6 h/ g" c0 L' b/ G" D5 C" j" F4 }
#define TDO_IN *(volatile uint32_t*)0x42210128
! T3 r. }- l4 [; j+ y, `3 G1 a
// nTRST Pin GPIOB[3]% b- \' I9 p, {& v: t
#define nTRST_OUT *(volatile uint32_t*)0x4221818C3 s7 f. \ c5 B4 {0 t# p
#define nTRST_IN *(volatile uint32_t*)0x4221010C5 f; P1 @- G- ]$ \- R1 O
// nRESET Pin GPIOB[4]+ x+ E: F6 o' B; ~ |3 i, D# o& a
#define nRESET_OUT *(volatile uint32_t*)0x42218190" V8 y( h( P8 E7 @! B: y
#define nRESET_IN *(volatile uint32_t*)0x42218110- K1 [* z% a( H, i. h
// nRESET Output Enable Pin GPIOB[4]! {/ x( v+ a) i4 ?- M
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 1; \! P1 D) d0 q+ w4 H* T6 Q
*(uint32_t*)0x42218044 = 1; \
*(uint32_t*)0x42218048 = 0; \! P* w0 o; P9 m7 y$ K
*(uint32_t*)0x4221804C = 0; } 9 ]% r- N a. w: I7 y/ A; c9 l/ O" q
; n& a& f3 B' Q, u
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \4 h; x0 A9 t. ^' R% ]" L- B, ^: Y
*(uint32_t*)0x42218040 = 0; \
*(uint32_t*)0x42218044 = 0; \: { e6 L2 V# }3 h g9 s
*(uint32_t*)0x42218048 = 0;\" t, m" z+ _3 V
*(uint32_t*)0x4221804C = 1; }; C$ _$ v8 x( D [1 p3 F
/ |2 p7 t: J. c* f. H
// Debug Unit LEDs, X! Y+ T* q3 e0 N
// Connected LED GPIOC[13]( P: F4 u* P: N, S# I8 [
#define LED_OUT *(volatile uint32_t*)0x422201B40 q3 N$ S; Q' [( S4 n/ X
#define LED_IN *(volatile uint32_t*)0x42220134
+ Z" T, ]5 U9 T4 Y( c
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \9 a7 W8 E+ K7 {4 I% [
*(uint32_t*)0x422200D0 = 0; \, H. f5 i# h- _2 A
*(uint32_t*)0x422200D4 = 0; \
*(uint32_t*)0x422200D8 = 0; \
*(uint32_t*)0x422200DC = 1; }" @9 \/ Q4 ?4 @& {7 O6 K% [
// Target Running LED Not available4 M" P+ d: e2 d! T: l. x
// SWCLK/TCK I/O pin -------------------------------------/ F- V6 Y5 X" V+ R
/** SWCLK/TCK I/O pin: Get Input.5 |% F$ r0 K: R& b8 `
\return Current status of the SWCLK/TCK DAP hardware I/O pin.! S% |- U9 w x+ ~0 |) \
*/
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return (SWCLK_TCK_IN);
}% k( u: _3 P( h5 o* a
: h0 G% o/ j/ q
/** SWCLK/TCK I/O pin: Set Output to High.- B/ l- x, S, e, g2 ~ m" J
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/2 I( e. }7 K2 N" k( S" N6 B
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {) q5 i% p/ c3 g7 k' a
SWCLK_TCK_OUT = 1;
}
) j8 u& h3 r1 G; v& r
/** SWCLK/TCK I/O pin: Set Output to Low.) W ~0 I# S# A! {: N' y* h
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/- q. i1 s- H5 l1 O+ m# @
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {+ Y5 A6 f' b, X6 F
SWCLK_TCK_OUT = 0;5 N9 r1 B5 }5 @5 w1 U0 q. y
}
2 m' X* M0 t% `# X9 d7 w; M* O; d9 P
" j+ B! Y) B. B- k% G0 l8 V Z
// SWDIO/TMS Pin I/O --------------------------------------3 L3 z4 C. T1 R1 E* v+ |' I8 f# n/ K
0 t* a: r6 A! \! n, ^' L
/** SWDIO/TMS I/O pin: Get Input.0 h5 l5 g6 g1 h J* f! }; T
\return Current status of the SWDIO/TMS DAP hardware I/O pin.3 z1 ] r$ L1 S3 D8 Z
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (SWDIO_TMS_IN);0 ], S1 }7 H# R
}
! E( C9 h8 ]8 a3 {" u/ V7 l% w
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/: j; p% y7 ~! e/ u/ N: X* Q
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {5 t3 X B. L/ @$ u* M# U
SWDIO_TMS_OUT = 1;
} P+ `( K7 e& Q x* z
/** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level.$ P9 I/ M! F3 G" B/ Q1 T. n
*/4 o3 f, C* o ~8 O, U1 Q: i3 N3 k
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {( q. G S1 S. K/ r3 O6 d
SWDIO_TMS_OUT = 0;
}- J9 f% I1 C' W' u
$ }9 d" a! h! P* ]5 Y' H/ r
/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin., S d1 e0 @! g, j# w0 `5 r8 R
*/* e5 m" i, N' R" U, K$ r
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {* z4 t7 \- L8 h2 ^
return (SWDIO_TMS_IN);+ S2 ]. l% \0 H7 T$ z# o/ B
}
, E3 Z. L% C" B Y* g3 ]
/** SWDIO I/O pin: Set Output (used in SWD mode only).6 W- D. t0 M) o% i2 T
\param bit Output value for the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {! v8 F: J0 \* R" ~7 U
SWDIO_TMS_OUT = bit;
}: l/ X" c" L9 w+ i3 N+ n; m* |
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).9 h6 ]: w4 w- Z9 G. F5 A% Y! S9 J4 n
Configure the SWDIO DAP hardware I/O pin to output mode. This function is3 n! h, M# d5 v/ i2 f4 | C
called prior \ref PIN_SWDIO_OUT function calls.
*/7 I6 r9 b+ j# l' _+ I
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {
SWDIO_Output();
}
" y0 e7 Z( O2 p) }5 \+ ^0 o6 o* |
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).9 Q4 h" a" B- O/ x+ C' c* {; c
Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls.
*/. B% V/ n* c6 R
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {( @8 N) f, l" c7 v
SWDIO_Input(); B2 s f9 g. C+ G' _' q. Y
}
楼上有的说弄无线,其实无线也就是PC<->USB<->无线模块A<->无线模块B-DAP,数据传输的速率主要是无线模块之间的速率限制了,也是非常简单的! h% ?( W6 i, T9 b
即单片机先做好USB接口部分,OUT端点收到的数据发送到无线模块A,无线模块B接收到数据后,推给DAP处理,DAP响应的数据再让无线模块B发送回无线模块A,再通过USB发送回PC,也就是说USB与DAP之间也就多了两个无线模块作为数据的交换,要是会写USB驱动,写个虚拟WINUSB设备的驱动,让Keil的DAP驱动能识别到这个虚拟USB设备,通过ESP32利用WIFI通信应该比使用这种无线模块更快,而且ESP32主频更高,即使IO模拟 SWD接口,都会更快,会写USB驱动的大佬可以尝试一下