【管管推荐】STM32经验分享篇
STM32固件库分享,超全系列整理
小马哥STM32F103开源小四轴RoboFly全部资料大放送
【MCU实战经验】+STM32F107的USB使用
基于STM32F103两轮平衡小车设计(开源)
STM32F107VCT6官方原理图和PCB
【福利】用STM32库的朋友有福了:STM32F10x_StdPeriph_Lib_V3.5.0chm...
基于STM32F10xx存储器和系统架构经验分享
基于STM32F1的CAN通信之BH1750
基于STM32F1的CAN通信之OLED
我这个是有复位信号输出线nRESET的,不过IDE要懂得向DAP发出复位命令。
- u7 G/ ?. t2 u, v1 ~. C, v
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。6 f( W- \' A' g. L( ?% T
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。5 Q. r+ Z7 k0 i _# o v$ w5 k
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。 . ^& n- w O% y4 m$ [
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。% K! O- p! D, H! O+ c0 u
/**1 u+ H+ V9 g+ X
******************************************************************************
* @file usb_endp.c$ z* F: Q5 s2 z* t a* d( q
* @author MCD Application Team* ~8 w7 f) k9 ~" f0 p) r
* @version V4.1.0
* @date 26-May-2017
* @brief Endpoint routines
******************************************************************************
* @attention4 f* Q% U$ K! y& ~7 Z# `# m! B
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*: x; j2 T/ E, Q+ H& I
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:% B" H# }$ r; s, Q1 Q
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.# @. u' Q( t) ]
* 2. Redistributions in binary form must reproduce the above copyright notice,2 @: C! |- l7 V- [/ |
* 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
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"0 M0 Z0 L6 R. V+ \
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE1 P( s. u# B5 w/ p
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* 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,- p( _- x8 |8 T1 \' r# A1 V
* 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.
*
******************************************************************************
*/$ n& o) G" U; m5 Z+ j
- s. H3 X; k/ X0 e* d1 N
/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"
#include "usb_lib.h"
#include "usb_istr.h"6 k. P8 i( U, X7 P
#include "stepper.h"6 [& H) G+ F0 p! ^% A4 I/ c
#include "string.h"
#include "DAP_config.h"
#include "DAP.h"
7 N7 c0 k! n- b9 h9 a% V
/* Private typedef -----------------------------------------------------------*/+ H# r! W o* Z/ M8 U
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static volatile uint16_t USB_RequestIndexI; // Request Index In
static volatile uint16_t USB_RequestIndexO; // Request Index Out
static volatile uint16_t USB_RequestCountI; // Request Count In* I4 d) ]. `6 `( b' z
static volatile uint16_t USB_RequestCountO; // Request Count Out+ l% E0 q" c: O# D& h
static volatile uint8_t USB_RequestIdle; // Request Idle Flag7 @$ O k9 W) h a" E0 `* P! e" ~
! K8 T- H1 p5 d+ x2 Z
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 In5 v; a5 e% Y$ Z
static volatile uint16_t USB_ResponseCountO; // Response Count Out, o$ R4 n+ l1 }+ n( N: ? K
static volatile uint8_t USB_ResponseIdle; // Response Idle Flag) Y( s$ J* |& j- R I4 W6 ^ t" u
static volatile uint32_t USB_EventFlags;
! n$ c: y, U% D) W6 C4 Y
static uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Request Buffer( Q" ?0 y' b+ V6 }" o: a" @
static uint8_t USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Response Buffer
static uint16_t USB_RespSize[DAP_PACKET_COUNT];* G: K2 y$ b$ B
/* Private function prototypes -----------------------------------------------*/; `8 H& D' O& W) O4 X$ q; `
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************0 U$ j6 i+ O5 D! y" ]7 ?
* Function Name : EP1_OUT_Callback.7 |8 y+ C% J; G/ H: m# i
* Description : EP1 OUT Callback Routine.
* Input : None.% a. y3 w; o6 z* }. k
* Output : None.* F3 N |: j7 L5 m& l& X
* Return : None.
*******************************************************************************/. ~5 U' v/ F x4 c& |: i3 X/ b1 D
void EP1_OUT_Callback(void)( Z& ~2 y# h" [# o- f5 C. }
{. V: h- B- r" m& B
uint16_t n;- s4 B! p& @; U- ^: I
% c9 A9 j3 @' J" d3 I+ Q4 `& I# O9 s9 r) z
n = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);
if(n !=0){
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {9 n# `8 }5 N$ ?: ^5 g: t/ z
DAP_TransferAbort = 1U;9 M, {" @5 c) z/ y4 R# }
} else {
USB_RequestIndexI++;: ` R0 W8 p" o9 A. K: a K$ x
if (USB_RequestIndexI == DAP_PACKET_COUNT) {
USB_RequestIndexI = 0U;3 w3 M! x7 D1 T' h
}
USB_RequestCountI++;# f& K8 k% D- l& v4 H
USB_EventFlags = 0x01;
}
}
// Start reception of next request packet7 H0 M j1 @$ i
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {# u5 C* y: c4 N- @( `! _" ~
SetEPRxStatus(ENDP1, EP_RX_VALID);
} else {
USB_RequestIdle = 1U;, M" }' S) a" `/ [$ O
} + c7 {* C- x X7 G& I$ \
}
/*******************************************************************************/ H4 S4 [9 Q; d
* Function Name : EP2_OUT_Callback.
* Description : EP2 OUT Callback Routine.+ H. b$ ?2 i5 c7 g; B( _
* Input : None.8 L7 r% [' w4 f8 _4 \9 t# h
* Output : None.
* Return : None.
*******************************************************************************/: V/ j1 q0 L$ Z k, Y
static volatile uint32_t TX_n;
static uint8_t *pbuf;; K. U5 d3 l+ i, S$ Q
void EP2_IN_Callback(void)
{' D( Q+ Z# Z8 m3 v& D
uint32_t a;
if(TX_n>0){8 q6 s/ D' F5 M
pbuf+=64;
if(TX_n>64){
a=64;$ D$ ?5 M: {- n- J% M$ l: T
TX_n-=64;
' h9 `8 u2 \9 q* `+ n
}else{# o6 c% s( K, a9 I; N9 V
a=TX_n;
TX_n=0;' ~. T# H/ I' W y& G( @9 i, ~
}
5 |" {; V: N3 A+ l: B9 ^
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);
6 Z" u. C f3 G. z5 S& K
SetEPTxValid(ENDP2);3 o; U, ]8 v4 ~+ e) I# @
}else{
#if (SWO_STREAM != 0); i5 c& Y0 I; `
SWO_TransferComplete();
#endif
}8 d3 V: N9 s9 j7 e1 w5 q, i
}
/*******************************************************************************4 t' S8 m0 R- D# e1 ^; S
* Function Name : EP1_IN_Callback.
* Description : EP1 IN Callback Routine.
* Input : None.! w3 I7 H" ?- u4 `- H! w* a; h
* Output : None.
* Return : None.
*******************************************************************************/- L* |* A9 r" q+ E% D9 `
void EP1_IN_Callback(void) l$ \, y! n2 N6 K- W* H
{
if (USB_ResponseCountI != USB_ResponseCountO) {4 S' s ^: p1 ]/ G9 K S* Q
// Load data from response buffer to be sent back: M) I! V. y1 M' r( M, p
UserToPMABufferCopy(USB_Response[USB_ResponseIndexO],ENDP1_TXADDR,USB_RespSize[USB_ResponseIndexO]);
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);, A% a0 f- a! B
SetEPTxValid(ENDP1);
USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;
}
USB_ResponseCountO++;
} else {% v: R& q7 s) z! g! u0 O/ F9 U
USB_ResponseIdle = 1U;2 g* Y& h5 G h2 W, F
} ; a, B9 u8 B1 I" W+ L1 R2 D
}' y- V$ K$ e. C2 H1 _6 f2 ? M
// Called during USBD_Initialize to initialize the USB HID class instance.
void DAP_FIFO_Init(void)
{; B# n4 f1 z( x) g- H& D1 n. }
// Initialize variables& H8 h! N! U2 {
USB_RequestIndexI = 0U;
USB_RequestIndexO = 0U;
USB_RequestCountI = 0U;( |. ?; A3 n2 P# X) e
USB_RequestCountO = 0U;
USB_ResponseIndexI = 0U;3 }7 ?: d& d, [7 ^
USB_ResponseIndexO = 0U;
USB_ResponseCountI = 0U;
USB_ResponseCountO = 0U; u& S- R! H8 l' F
USB_ResponseIdle = 1U;
USB_EventFlags = 0U;
}
; V* D8 y8 d `, Z$ W
uint8_t DAP_Thread (void) {
uint32_t flags;
uint32_t n;
//for (;;) {
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);
if((USB_EventFlags & 0x81) == 0)" ~( [: m* e( m8 ~, G: R/ ^
{" [5 w3 Q) T* Z) ^
return 0;- G& E4 \& Q" j5 z- \
}# Y+ T- g8 D% G8 W
USB_EventFlags &= (~0X81);
: B6 g6 }9 v' K5 m" _
. @1 R- D* M8 t/ w2 g
// Process pending requests0 F. B( m. U7 V9 Z
while (USB_RequestCountI != USB_RequestCountO) {3 s. _! [2 C" X6 }
//if (USB_RequestCountI != USB_RequestCountO) {" J5 W' a- ^6 H8 W* S0 O) H4 a
// Handle Queue Commands
n = USB_RequestIndexO;
while (USB_Request[n][0] == ID_DAP_QueueCommands) { e( U P' x7 q2 n
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {
USB_Request[n][0] = ID_DAP_ExecuteCommands;
n++;1 m5 ~7 K* ~6 K
if (n == DAP_PACKET_COUNT) {4 h# x X7 y" x- L, \
n = 0U;
}1 U% g( w+ n9 H+ }9 F c
if (n == USB_RequestIndexI) {; ^+ ~+ h- q& V8 N! d' e
flags = USB_EventFlags;
if (flags & 0x80U) {
break;
}
}* T& ]5 i: G& V8 W5 d& l c
}
// Execute DAP Command (process request and prepare response)' I' a" {- a$ ~. `* F5 p$ A# z, ~
USB_RespSize[USB_ResponseIndexI] =& U4 g2 i% w; B1 a
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);
// Update Request Index and Count1 d3 I$ J9 X Q! E9 j0 i) `
USB_RequestIndexO++;
if (USB_RequestIndexO == DAP_PACKET_COUNT) {7 u) U. w6 d6 g% A* o$ l
USB_RequestIndexO = 0U;
}% x& g! i( U& S" q
USB_RequestCountO++;
0 {; B- h, H$ y7 T
if (USB_RequestIdle) {
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
USB_RequestIdle = 0U;
SetEPRxStatus(ENDP1, EP_RX_VALID);
}
}, R, ?- ]/ J) L+ w, c% g
' ~: i' B# K$ @. l9 j
// Update Response Index and Count
USB_ResponseIndexI++;/ o( e* d( E; a4 {5 J, q. p
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {
USB_ResponseIndexI = 0U;9 B# @: H- O2 F. W0 ~ Q
}
USB_ResponseCountI++;4 j! `: @7 U9 C2 Y: ?
if (USB_ResponseIdle) {, [6 `3 b B0 w
if (USB_ResponseCountI != USB_ResponseCountO) {. z% w1 g+ m. |3 w6 V! S
// Load data from response buffer to be sent back" s" K+ [. \# H) D; {: |& X
n = USB_ResponseIndexO++;& I. h3 f" D4 W, b9 ~' ?! n
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;
}! u0 R! G( {6 K# s6 E: M8 T% r
USB_ResponseCountO++;
USB_ResponseIdle = 0U;
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);3 c5 l" Q2 w5 Q1 L& l
UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);
SetEPTxCount(ENDP1,USB_RespSize[n]);
SetEPTxValid(ENDP1);
}& m9 W' I1 N# r5 D
}+ `; T" T; H, a% C, B) p0 P) z
}
return 0;
} Y0 c3 R6 }0 {, m- P8 a
: p8 t* {) M4 P! z$ O
// SWO Data Queue Transfer
// buf: pointer to buffer with data# a' R. P" C5 p1 n! X9 J
// num: number of bytes to transfer# J6 `0 J. y; ~/ h
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {" v! w- B# P# s; L* C
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);
uint32_t a;
if(num>64)
{0 {, q0 {; ~9 {
a=64;
TX_n=num-64; {% B% u* W) G) J7 ?
pbuf=buf;) d* H) L6 A' U) N6 R' h
}else {( u. ^( e5 O! `$ l: n, Y
a=num;
TX_n=0;- Z [, k3 I8 T$ Z
}
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);& a( z ^0 s% X9 F
SetEPTxValid(ENDP2);) T: n" ~1 H6 F
}
// SWO Data Abort Transfer# m S+ Q# s) f1 `
void SWO_AbortTransfer (void) {
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));
//SetEPTxStatus(ENDP2, EP_TX_NAK);" @+ M+ v- }, Z/ C/ Q2 _# e
SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxCount(ENDP2,0);+ V0 W1 l* T; L, _# U
//TX_n=0;6 { m7 ?" |7 ]1 v: k9 [2 m7 q
}0 H# ]. T( p1 X/ q) K
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
0 Z6 V, N6 v+ k- P
移植大概是这样的,利用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时感觉速度还是可以的,这能体现批量端点的好处& V: R+ T, w+ D$ x7 t E$ x1 E
DWT部分即TIMESTAMP的时间参考,由于没使用Keil的核心库,得自己对相应的寄存器进行开启,而且3.5库的core_cm3.h里面没声明这个寄存器,只得自己定义一下了% W. u- C7 D- _8 E6 b6 N
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {: @3 N) I- L4 G6 E; X
return (DWT->CYCCNT);
}4 p. F; R i+ G9 m" X
6 n. S1 z3 ~3 }: N) t6 i# o
void DWT_Init(void)
{
/* 使能DWT外设 */9 @7 P2 n1 c) _, u$ |# h( x
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
. m. @" C# F/ C" U
/* DWT CYCCNT寄存器计数清0 */3 @2 g: V: ^* p7 k' w$ `
DWT->CYCCNT = (uint32_t)0u;. V. Q' F' q2 ?, O) g' X. c/ p
2 b; k0 l6 e# w% s- J' \6 q: D: j( ^
/* 使能Cortex-M DWT CYCCNT寄存器 */
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}- F" d& \' g2 }# ~! B" W
" \4 [" I" _4 P, z0 F" {" O
$ O- a9 l$ _& O* W
然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率
然后改为使用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);, t A* E2 M8 Q8 [
SWO_EventFlags = 1U;, {, ?: H7 D+ k J
// SWO Thread5 z* F! o: Q6 q/ A6 |$ f) n* a
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {) o$ G) c% A& B
//uint32_t timeout;
uint32_t flags;5 Y) _9 I3 |5 ~9 g
uint32_t count;
uint32_t index;; {7 T) O' L t* v3 l
uint32_t i, n;
//(void) argument;$ a! _6 [* ~3 c( I
//timeout = osWaitForever;
' H, _7 g8 j* J; a2 B7 T/ s; r
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);4 R& o' Z) c$ \2 H- O3 s# {
if((SWO_EventFlags & 0x01)==0)return 0;
7 D V6 [3 M4 M# u
flags = SWO_EventFlags;7 U5 u0 w4 L" v! W' c5 J. \4 |) S
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {& a! K: O' J9 y0 N$ n
//timeout = SWO_STREAM_TIMEOUT; 这里是对于进入了SWO_CAPTURE_ACTIVE状态时就把线程超时设置为50毫秒,大概意思应该是osThreadFlagsWait到达这个超时时间后,不管标志是否切换为1U,都放行SWO_Thread调用一次,timeout = osWaitForever时相当于无限长的超时等待1U标志,对RTX不熟悉,不知道是不是这样子
;7 r# p* L5 N/ \
} else {
//timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}' [. @0 u0 t7 a) T
if (TransferBusy == 0U) {% C8 ~& p1 a: a0 s, t5 J4 }' l
count = GetTraceCount();
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;5 s) X% {4 `2 S0 `/ R2 [) E
} ^% u3 i# { l0 \ {0 D; \4 i$ y
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;0 A0 R, h* O0 L4 Y/ X
if (flags != osFlagsErrorTimeout) {/ V X# P3 B. n
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);7 z1 A2 E. f; J r1 w' ?
} else {
n = USB_BLOCK_SIZE - i;( l7 b G5 l( b' {
if (count >= n) {1 B6 U$ l( _2 ?9 w6 L
count = n;
} else {$ Z' B" p O) s
count = 0U;
}
}* k I: @1 f% x9 V6 @
}
if (count != 0U) {7 `/ ~, s! i8 ~" d6 U# m& ^. g! Z
TransferSize = count;; ?; n1 E# n+ [7 P0 o
TransferBusy = 1U;" I3 z$ M2 W1 P+ {# N6 ?9 {
SWO_QueueTransfer(&TraceBuf[index], count);
}4 e/ Z# ?' i. A$ I9 o8 I
}
}
//}4 O7 q$ ^1 p8 T* {+ [0 [
return 0;& R: ^* T* o9 M/ m p' V6 s
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).3 i3 v/ W2 r8 T3 z: u/ x) D& T
static volatile uint32_t SWO_EventFlags=0;6 i2 T/ I, x: T0 s& D" ?+ C! }
static volatile uint32_t timeout=osWaitForever;
static volatile uint32_t timeWait;
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {: i6 O/ B z+ t; R
//uint32_t timeout;9 Y; \( I; H" v; X6 t, S; r
uint32_t flags;% G* N# Z* d/ d. {! F; v$ O) n& {# u
uint32_t count;
uint32_t index;3 e) o$ v) ^7 U3 X, r+ u
uint32_t i, n;% K1 x5 B& o! ?8 k
//(void) argument;
5 z' h8 K: P' u. E$ l* \
//timeout = osWaitForever;
//for (;;) {/ R3 H: G* H: ]2 W+ f
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);: T' Z+ f1 C- o! a
if((SWO_EventFlags & 0x01)==0)) h* t. [. E" A8 P
{9 b* z6 ?, m3 e3 P# O3 `
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了
return 0;
}" B! I; e- ?% }' Y) B5 [3 c6 i$ V
flags = SWO_EventFlags;( A' V. ^; K0 F0 K+ c
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
timeout = SWO_STREAM_TIMEOUT;
timeWait=DWT->CYCCNT;
} else {
timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}
if (TransferBusy == 0U) {$ `- P8 c, m( |
count = GetTraceCount();+ ^; s8 t! K$ j8 l5 V8 Y
if (count != 0U) {' i, J# }% e# [
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;6 p/ \' a& F1 U' |
if (count > n) {* a. e* {6 A- ?) Q+ G6 m* n
count = n;2 f& e/ p7 h7 [
& X/ M) A6 x8 } L; j
}3 c$ t$ b) ^. r% s0 P/ [
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;
if (count >= n) {
count = n;$ t& Z( y; \4 _- l4 _2 \" q
} else {
count = 0U;
}3 j. k1 m: p/ {5 W3 l$ |0 N2 [. {; L
}
}
if (count != 0U) {" {5 w/ e7 F6 R9 n
TransferSize = count;
TransferBusy = 1U;4 o% s9 z) s, l3 x4 M P" |+ c
SWO_QueueTransfer(&TraceBuf[index], count);
}
}5 e# ]& r4 B3 L3 M6 ]% K
}( z% }0 A/ q- d# x- H7 _: P* w
//}
return 0;
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了9 M6 X: c+ J* g! r! H/ R
$ _& w' |) }- Z' m/ E% |6 H
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,少了这个等待时间,能增加端点的传输速率 Q# o5 i( y* n" `3 o7 j
& X: M: C7 Q, K* I! i [2 Z( p$ V
int main(void)) d$ P, I; x& X9 y) u
{
DWT_Init();
DAP_Setup();
USB_Interrupts_Config();
Set_USBClock();
USB_Init();7 G4 O& w K. ~( O: J# Y x
//TIM3_Init(35999,0);! j; y0 e3 T) C6 K+ D
//TIM_Cmd(TIM3,ENABLE);5 j6 o2 y1 g1 k6 Y
/ W1 b ?- C$ f3 {) O
# R2 h5 `3 `$ s; `$ L$ Z: e
while (1)' C1 G" ]' d, g# J
{7 A0 b, P( O N! @ X. y
DAP_Thread();
#if (SWO_STREAM != 0)
SWO_Thread();
#endif- s& v; i7 H+ d# O, l: K# v
}" ]- O3 j5 y8 h& ~0 k$ f
}
- E* ^# {% P0 A" H- n5 o* x; Q" X
对于DAP_config.h的IO配置我是这样弄的- c3 q0 @1 f, K2 Y! u
///@}" L; A, b& E" [/ J* f, Q/ p" g
// Debug Port I/O Pins
// SWCLK/TCK Pin GPIOA[6]' |# v8 r' q4 Q6 D9 @/ |0 {
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198
#define SWCLK_TCK_IN *( uint32_t*)0x422101180 f4 I3 @1 Q- _. g6 R" D
// SWDIO/TMS Pin GPIOA[7]
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C' `% |: T3 i! A/ A0 I9 |
// SWDIO Output Enable Pin GPIOA[7]
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \3 [, K3 p5 G1 E c" U; w
*(uint32_t*)0x42210070 = 1; \. n$ o# D/ {5 x# Z/ N8 ^6 A
*(uint32_t*)0x42210074 = 1; \
*(uint32_t*)0x42210078 = 0; \6 ` J9 y6 n+ T3 ~0 U
*(uint32_t*)0x4221007C = 0;}
+ R" L7 {1 D: h
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 0; \' _& t' d3 y. v$ T, i- K
*(uint32_t*)0x42210074 = 0; \
*(uint32_t*)0x42210078 = 0; \" s- `" f- r7 A7 E
*(uint32_t*)0x4221007C = 1; }
// TDI Pin GPIOA[8]2 Y( K0 d, p! C4 S
#define TDI_OUT *(volatile uint32_t*)0x422101A0
#define TDI_IN *(volatile uint32_t*)0x42210120
: M4 r* |, k' n& z% e
// TDO Pin GPIOA[10]
#define TDO_OUT *(volatile uint32_t*)0x422101A8& z) B& f( B2 {4 U
#define TDO_IN *(volatile uint32_t*)0x42210128( _1 J* b; l* X8 c2 n! y1 n
( V( E( L I1 f% J( a, I) M
// nTRST Pin GPIOB[3]
#define nTRST_OUT *(volatile uint32_t*)0x4221818C* w' v$ j0 n8 H1 F! f
#define nTRST_IN *(volatile uint32_t*)0x4221010C" L: J% B. X! ?2 r$ Y$ D
D* m" W7 h1 a. K, `/ @
// nRESET Pin GPIOB[4]
#define nRESET_OUT *(volatile uint32_t*)0x422181908 }* {1 n- l$ Z/ ^+ N' ^
#define nRESET_IN *(volatile uint32_t*)0x42218110
V3 m D; P1 J2 j* K
// nRESET Output Enable Pin GPIOB[4]
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \! h! E" l5 @+ ]; w
*(uint32_t*)0x42218040 = 1; \+ W' @: s! G2 o
*(uint32_t*)0x42218044 = 1; \$ X" z# X$ f' E8 |+ j, y
*(uint32_t*)0x42218048 = 0; \
*(uint32_t*)0x4221804C = 0; } - U$ [0 I) O* J5 T& H. S F
3 j0 g& q& T. ?- m9 c b" @
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \4 K) O; i J+ K1 l6 O
*(uint32_t*)0x42218040 = 0; \ f( O- l- j- ]$ r5 x7 q4 Y1 E
*(uint32_t*)0x42218044 = 0; \
*(uint32_t*)0x42218048 = 0;\
*(uint32_t*)0x4221804C = 1; }
" H* v# k2 N# T* d# J# {/ b
// Debug Unit LEDs
// Connected LED GPIOC[13]$ P& _& y% B( Z7 R4 G5 N5 Z( Y; u9 ^
#define LED_OUT *(volatile uint32_t*)0x422201B44 D0 h$ ?, z* h
#define LED_IN *(volatile uint32_t*)0x42220134
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \
*(uint32_t*)0x422200D0 = 0; \
*(uint32_t*)0x422200D4 = 0; \, [0 D) X* j/ ?5 I0 c; Z$ T! Y$ Q
*(uint32_t*)0x422200D8 = 0; \
*(uint32_t*)0x422200DC = 1; }
// Target Running LED Not available
// SWCLK/TCK I/O pin -------------------------------------
7 K/ L* D6 ^) y6 R) [' u
/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/) I3 N" K! p- D2 p
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {7 E8 U* q" V) e4 N- R
return (SWCLK_TCK_IN);3 ^+ e! \, c; e0 `7 e F$ n
}; s6 J: P% M* P4 t# `2 H( ]
' J* `/ x& ?" }& l
/** SWCLK/TCK I/O pin: Set Output to High., _$ u9 c, d( Y' G3 o
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {! a, @9 }! H/ g0 t
SWCLK_TCK_OUT = 1;
}
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/7 T% l" G# \8 p. F
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
SWCLK_TCK_OUT = 0;* _) C8 I/ Z0 ], x7 ?. c
}* R9 c, Z+ {5 x {
// SWDIO/TMS Pin I/O --------------------------------------
5 S, k/ x6 v& O, l) ~2 O7 v8 g9 T
/** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/, }0 W! i8 V9 @$ h+ M5 L
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {: j4 P2 @: W$ }
return (SWDIO_TMS_IN);% d; J' i2 C6 C3 p
}
0 I% B" U! B2 _3 c( ~
/** SWDIO/TMS I/O pin: Set Output to High.$ A4 |0 ?9 m' | l2 [
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/; y& ]& a& E( p2 s
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) { w: Z' |- U/ @+ ~# e5 a8 l- q; w
SWDIO_TMS_OUT = 1;; p6 w8 ]1 b7 C2 w
}
4 l; |' l- }+ H% E4 v7 E, \
/** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level.
*/( J9 G* }7 s7 j: h; m6 O
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {
SWDIO_TMS_OUT = 0;: F% ] G2 g+ I1 l# W
}1 i6 H. _6 ?* g7 A
- J0 ~/ x& i) P7 ^; k: g W+ ~
/** SWDIO I/O pin: Get Input (used in SWD mode only).3 O; s* |; b5 S
\return Current status of the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return (SWDIO_TMS_IN);
}/ Z% h7 r: F) E+ ~
+ Z R3 w ]3 `
/** SWDIO I/O pin: Set Output (used in SWD mode only).5 B$ u! E- Q" E% |. }
\param bit Output value for the SWDIO DAP hardware I/O pin., J* n% [) M& C5 S8 s
*/% d; ]0 @& }/ s! @
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {$ R% c1 I4 ^ c* E0 A$ g* ]- ~
SWDIO_TMS_OUT = bit;- n4 N3 H/ D1 p) _
}# t& q6 p: [! Q7 ? C7 ]
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).0 f, x0 A0 j8 ~+ f7 v/ y, y2 D& f
Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls.
*/3 o0 L1 ]1 O" L; O8 T4 a8 h% s
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {' D D2 W+ `; d$ {
SWDIO_Output();
}
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).% X# Q6 E* f9 Q# ^
Configure the SWDIO DAP hardware I/O pin to input mode. This function is6 R) z1 Q" Y) a/ ^. U
called prior \ref PIN_SWDIO_IN function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {/ r& O+ ]# a( J! b
SWDIO_Input();
}5 X+ {9 B' [, G7 K1 N* U" g
楼上有的说弄无线,其实无线也就是PC<->USB<->无线模块A<->无线模块B-DAP,数据传输的速率主要是无线模块之间的速率限制了,也是非常简单的
即单片机先做好USB接口部分,OUT端点收到的数据发送到无线模块A,无线模块B接收到数据后,推给DAP处理,DAP响应的数据再让无线模块B发送回无线模块A,再通过USB发送回PC,也就是说USB与DAP之间也就多了两个无线模块作为数据的交换,要是会写USB驱动,写个虚拟WINUSB设备的驱动,让Keil的DAP驱动能识别到这个虚拟USB设备,通过ESP32利用WIFI通信应该比使用这种无线模块更快,而且ESP32主频更高,即使IO模拟 SWD接口,都会更快,会写USB驱动的大佬可以尝试一下