UDS诊断服务
使用Nano板验证驱动SPI串口屏的颜色显示
使用STM32F103制作的无线下载器
小马哥STM32F103开源小四轴RoboFly全部资料大放送
STM32F103移植LittlevGUI代码
【MCU实战经验】+自制MP3使用STM32F103ZET6和ch375读取u盘,vs1003解码,音质超棒
串口通信波特率异常的解决办法
【MCU实战经验】+STM32F103的uCOSII详细移植
游名科技:STM32F103+TMC2160:86步进电机和驱动一体原理图/PCB...
在高容量 STM32F103xx 微控制器中实现 ADPCM 算法
我这个是有复位信号输出线nRESET的,不过IDE要懂得向DAP发出复位命令。
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。
9 V# i6 f9 a. _% X
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。 # D7 M8 x- d Z7 S- G5 H$ a2 S% m
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。8 a9 h7 g! `. U8 U
/**/ U: I$ X2 r3 h( U! Y+ Z
******************************************************************************
* @file usb_endp.c
* @author MCD Application Team0 {# {4 X5 H. \3 k& v; S3 X
* @version V4.1.05 W/ r& Q! y }, A8 Z0 y* z
* @date 26-May-20179 {9 \5 }* k& W
* @brief Endpoint routines
******************************************************************************
* @attention+ L- c6 p7 p( s0 f: h, P
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>9 ~7 `* K& {* \6 z
*
* 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,* a6 V3 G3 m- q
* 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* o$ ]( _$ R% o5 N% Q8 T% o/ {
* without specific prior written permission.8 }9 ]1 ]! K, c9 m
*1 G' N- Y8 t' y$ N: f8 }4 I
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS") V' }# y; b( i7 H' j
* 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 LIABLE. D1 C2 C: B/ E& k5 E2 c+ 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,3 ^3 o& h' ^5 a O9 s$ g5 l
* 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.# d! X6 r6 Y+ C+ `. y
*
******************************************************************************& C `! _7 n8 V4 q$ D7 d
*/3 b% J1 y" f3 e
/* Includes ------------------------------------------------------------------*/9 B% A% \5 z) Z
#include "hw_config.h"& \8 C& x0 C) e8 l9 k
#include "usb_lib.h"
#include "usb_istr.h"
#include "stepper.h"1 D" D$ x0 C( o1 k4 N
#include "string.h"; `# r# ]( P9 T; G& S
#include "DAP_config.h"
#include "DAP.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/) T( F# x$ n) c
/* Private variables ---------------------------------------------------------*/
static volatile uint16_t USB_RequestIndexI; // Request Index In! F! j5 P6 ?* Z* u; X* X
static volatile uint16_t USB_RequestIndexO; // Request Index Out6 k, N$ K) t' Z2 P* k5 P* W# C
static volatile uint16_t USB_RequestCountI; // Request Count In
static volatile uint16_t USB_RequestCountO; // Request Count Out
static volatile uint8_t USB_RequestIdle; // Request Idle Flag
static volatile uint16_t USB_ResponseIndexI; // Response Index In( ]/ B+ e* H2 f, V( q& @
static volatile uint16_t USB_ResponseIndexO; // Response Index Out g' `* [* M/ L7 s
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 Flag4 E* `1 ]4 Y! c; [2 @; I
static volatile uint32_t USB_EventFlags;
static uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Request Buffer! m; W! y5 \0 P
static uint8_t USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Response Buffer9 O$ C8 e+ w( v- p2 w; ?
static uint16_t USB_RespSize[DAP_PACKET_COUNT];
/* Private function prototypes -----------------------------------------------*/! S# ^; h# \# R3 T# t
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : EP1_OUT_Callback.& T/ F+ X) A5 W2 c. w2 P
* Description : EP1 OUT Callback Routine.' n% r/ ~0 O2 E6 w' H+ C N
* Input : None.0 A" L/ L% v: M
* Output : None.) X# }0 t% {8 F( v x$ v5 }
* Return : None." x! E/ m; \2 `/ P; z
*******************************************************************************/
void EP1_OUT_Callback(void). @6 _$ k+ k L6 ~! ~
{
uint16_t n;
* g2 I* B9 j! E
n = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);
if(n !=0){
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {: F, H5 G/ B! {
DAP_TransferAbort = 1U;* ^9 ?' x( z/ l9 J# e0 N+ e
} else {: k: s8 a8 D; p& l/ ~' s
USB_RequestIndexI++;0 |& H0 `" j, k$ X7 \' U% E
if (USB_RequestIndexI == DAP_PACKET_COUNT) {
USB_RequestIndexI = 0U;& j5 O$ d& X( l+ g8 @! c u
}2 Z% [! z' I. X* ~
USB_RequestCountI++;
USB_EventFlags = 0x01;
}2 U. `2 z, x. X2 w! y9 n! P, c0 r
} 7 y: i! ~9 A K# D7 Q: m+ f
// Start reception of next request packet
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {) a. n j# v; `! X8 G! D
SetEPRxStatus(ENDP1, EP_RX_VALID); W7 F8 ?4 s8 _: f3 @" a6 W0 O$ v
} else {" d. B# K# K" T; z
USB_RequestIdle = 1U;7 R- b+ p: a+ F. L% g* w# L6 t+ ~/ g
}
}
0 j8 _/ \, n9 ~9 j
/*******************************************************************************
* Function Name : EP2_OUT_Callback.) X" a. P# ^: @. ^# T
* Description : EP2 OUT Callback Routine.- I2 R5 D+ M3 E% X5 o
* Input : None.( S6 ^) V6 M2 K
* Output : None.( R- y* f) p- q" X; _- o
* Return : None.& H Z7 K) Y% }( P
*******************************************************************************/' E! V5 S8 G5 P) q. A5 X
static volatile uint32_t TX_n;
static uint8_t *pbuf;5 k& ?7 ~. l" f* w$ s/ W
void EP2_IN_Callback(void)* f3 [/ P& j, L0 D9 \# H
{0 q; Q( c7 s& J, s [6 h/ P3 l, X
uint32_t a;8 u6 S% ]5 [2 R; X
if(TX_n>0){
pbuf+=64;4 M# k" o9 Y4 }$ Q
if(TX_n>64){( w+ @ i# I0 q" a. p- y# U
a=64;
TX_n-=64;; ~. {, [' b9 i
, b& k* N. u4 y5 I- W* _
}else{1 p2 x" h1 T. g
a=TX_n;! w- V" h# R. Y% Y- t; J7 g8 X
TX_n=0;+ a& _3 i) H! {
}+ H- Y/ o0 V% F5 Z! j
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);- M4 C! p8 H9 I7 z
7 O1 ^ s3 X$ R$ o
SetEPTxValid(ENDP2);
}else{% F( W- r) L3 e2 G d# {/ Q
#if (SWO_STREAM != 0)# c' G% M+ w$ ^
SWO_TransferComplete();- ~9 L! d) x% H6 T
#endif
}( A2 h5 k5 h* h w" D, v
}, n: I8 @: T$ W0 ~
$ E/ n& i% ^% m* m4 h8 S
/*******************************************************************************7 R# g z9 j) M& a# a
* Function Name : EP1_IN_Callback.
* Description : EP1 IN Callback Routine.
* Input : None.
* Output : None.9 ~0 P% P& C; x! S1 z
* Return : None.( G* |5 Q& g) K, m9 h, W6 c/ |
*******************************************************************************/$ i+ u0 Z v9 g8 Z: [
void EP1_IN_Callback(void)
{1 ~+ j, u9 ?' i8 o7 x" P+ W3 h
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back
UserToPMABufferCopy(USB_Response[USB_ResponseIndexO],ENDP1_TXADDR,USB_RespSize[USB_ResponseIndexO]);
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);' C+ ]% V6 K% K- }& }
SetEPTxValid(ENDP1); $ R' B- ?/ p' a; V; o) P1 x
USB_ResponseIndexO++;; o/ m% l: g P @& W7 ]
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {1 B& e) m4 {1 F" g3 Z
USB_ResponseIndexO = 0U;
}+ f' }& |4 p' `9 W& M! O
USB_ResponseCountO++;
} else {
USB_ResponseIdle = 1U;5 v5 V5 C w1 T
} ! C+ ?* p0 [, F& W. E2 F! }
}
+ I; ^3 X) A4 X/ b$ j9 L& i6 p/ G
// Called during USBD_Initialize to initialize the USB HID class instance.( w. C& [- ]! I, J o1 W L
void DAP_FIFO_Init(void)
{7 y. f& Y2 o1 C
// Initialize variables7 ?0 c9 z- ^) c
USB_RequestIndexI = 0U;1 j! M4 m5 i4 [& D2 f
USB_RequestIndexO = 0U;; G* h$ f+ R# H" M3 a
USB_RequestCountI = 0U;1 x! L$ [( d2 c% W7 x
USB_RequestCountO = 0U;
USB_ResponseIndexI = 0U;8 K4 V8 i: {8 S: b0 X( {
USB_ResponseIndexO = 0U;
USB_ResponseCountI = 0U;) I0 a9 b9 Q2 \4 ^' h, a
USB_ResponseCountO = 0U;
USB_ResponseIdle = 1U;% V* i9 ?. m. o" v) C+ O/ h
USB_EventFlags = 0U;
}- i6 G) v' T: x: c N+ g
l2 B, @+ |) P$ Q
uint8_t DAP_Thread (void) {- g3 K6 W% O9 u8 F2 p0 f! j. f
uint32_t flags;
uint32_t n;
- Q9 Y6 I( V2 v. C$ ]
//for (;;) {
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);
if((USB_EventFlags & 0x81) == 0)
{
return 0;$ V% Q* g7 E3 |* x
}
USB_EventFlags &= (~0X81);
// Process pending requests" T/ B& s n! v& r
while (USB_RequestCountI != USB_RequestCountO) {
//if (USB_RequestCountI != USB_RequestCountO) {$ b7 `# X# U6 v! h9 q; }; o
// Handle Queue Commands3 {( n9 b' a; \ H3 ]
n = USB_RequestIndexO;
while (USB_Request[n][0] == ID_DAP_QueueCommands) {; j2 d! h$ s6 j( e M! o
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {7 M# N% x% D6 n8 E4 c
USB_Request[n][0] = ID_DAP_ExecuteCommands;
n++;
if (n == DAP_PACKET_COUNT) {
n = 0U;
}# }! r/ T# C1 Q6 |
if (n == USB_RequestIndexI) {
flags = USB_EventFlags;
if (flags & 0x80U) {
break;
}
}
}
// Execute DAP Command (process request and prepare response)6 T9 f6 _( P |8 w4 w; U, i
USB_RespSize[USB_ResponseIndexI] =3 R9 W$ y1 D0 P9 b- y# q: ^0 P8 K1 M
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);
: C& a$ C; N0 b" P, b3 A
// Update Request Index and Count' H. W9 V+ E8 F% q& k
USB_RequestIndexO++;
if (USB_RequestIndexO == DAP_PACKET_COUNT) {
USB_RequestIndexO = 0U;+ {& _& n; Y( G; p; }$ {
}
USB_RequestCountO++;( H$ i8 {- X/ R
5 Q' G- h- e: O$ J! N
if (USB_RequestIdle) {- b5 A9 I# t% [# t
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
USB_RequestIdle = 0U;# ~7 B- ]! h, j" o5 h# G2 M
SetEPRxStatus(ENDP1, EP_RX_VALID);9 M' _" E G/ c0 F* C9 a7 I5 L& Q
}
}
! s) Y! L8 U; p: ^) _# ]
// Update Response Index and Count
USB_ResponseIndexI++;
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {
USB_ResponseIndexI = 0U;" Q9 }- |. d% L, i. R" E. L
}" P, K& U8 @3 u/ r, w6 B, ^6 D% x
USB_ResponseCountI++;1 u7 |" Q6 ~* w9 Q' |+ T7 w/ l
" K/ K3 P6 |9 P: ?/ S: v
if (USB_ResponseIdle) {
if (USB_ResponseCountI != USB_ResponseCountO) {+ ]4 y; T" s' c$ a
// Load data from response buffer to be sent back- C* Y7 N, E9 Y/ y- l% c, p5 |
n = USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;+ w, z' k! Z" { c1 i% _+ W0 W
}" P4 L+ F" i/ [/ [) y: D5 R
USB_ResponseCountO++;1 ?1 M, j. X; a$ O
USB_ResponseIdle = 0U;
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);' h2 ^, V- m$ K2 l/ W
UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);
SetEPTxCount(ENDP1,USB_RespSize[n]);* m8 a' v4 G2 a) w
SetEPTxValid(ENDP1);7 n! J w5 a* B. Q" o
}- Z7 P) k9 n6 q0 g: v6 c
}
}+ O, J' H; n% W! z. O' N
return 0;
}
// SWO Data Queue Transfer
// buf: pointer to buffer with data+ e' k9 W# q4 E4 l/ ^; c! z* M
// num: number of bytes to transfer
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {0 U1 q, f: I5 ~' p9 r7 ?3 c
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);/ z0 _3 J$ ?) C$ m) Q1 _% s( J
uint32_t a;
if(num>64)4 x, i: A( f) g+ h
{
a=64;' C7 q" G. j" X# P m" [- J& ~
TX_n=num-64;! P* l; x; o3 w6 A5 e8 }; H
pbuf=buf;
}else {
a=num;2 M& L7 L. S9 X
TX_n=0;: U9 k+ C! ]1 H/ H( K
}5 E# C+ `- o3 b! Z; M( f0 z. g
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);
}7 r2 N3 l* ^2 W
// SWO Data Abort Transfer) O4 h1 `4 Z. u2 j) }& M; d
void SWO_AbortTransfer (void) {$ \- A1 T+ R# i# F
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));
//SetEPTxStatus(ENDP2, EP_TX_NAK);
SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxCount(ENDP2,0);
//TX_n=0;2 {+ q3 H" `7 |( s
}1 ?- N7 ]6 a; _9 }5 a/ k/ F' U, G
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
( b' z* y& z2 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里面没声明这个寄存器,只得自己定义一下了
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {) C4 W; t1 \$ J. R: k& S+ O d$ Q
return (DWT->CYCCNT);' ^/ L" n: g; p. U
}
void DWT_Init(void)
{( K; m- v# }$ |
/* 使能DWT外设 */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; : r, g' @1 ]4 t! O ^+ }+ A
- h$ l; O2 ^' w2 R2 e: n0 k
/* DWT CYCCNT寄存器计数清0 *// C$ x# Y9 W% b" J6 I {6 b' e4 B
DWT->CYCCNT = (uint32_t)0u;
/* 使能Cortex-M DWT CYCCNT寄存器 */
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}! j: s/ R) U( L8 F$ w! Q; {
然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率
5 U0 [9 ^8 U7 F0 g
然后改为使用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的地方都改为如:* Z( T3 ]" V' s/ c: |
//osThreadFlagsSet(SWO_ThreadId, 1U);
SWO_EventFlags = 1U;; p+ P- X- l/ \/ y: J
7 Z1 `8 C# ?5 Q8 H. J
4 U+ H' E: j7 A1 o7 z, g
// SWO Thread
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;6 ^4 Q$ j9 E4 `
uint32_t flags;
uint32_t count;$ O; P! V( N7 G7 C$ J3 q
uint32_t index;" C' X7 [7 n2 `% @( B) H
uint32_t i, n;
//(void) argument;
% M) h% p6 J3 \; ?6 N# ^+ M
//timeout = osWaitForever;
+ _1 a$ U) u W$ v) M
//for (;;) {* ~) e7 W( M9 ? [
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if((SWO_EventFlags & 0x01)==0)return 0;
$ s% Q3 a# w; q
flags = SWO_EventFlags;# k, H" g& _1 A' ]0 O" ^ [
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不熟悉,不知道是不是这样子& T5 E7 ^0 a+ h/ i, m+ [
;
} else {
//timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}
if (TransferBusy == 0U) {
count = GetTraceCount();
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n) {3 `4 @) f$ B- A+ `6 c5 _" d c) G
count = n;: T5 v' ] m3 |/ w9 v
0 b; S: x8 ]' T! a( f# n
}
if(count>USB_BLOCK_SIZE): S* g8 }7 E) g- D7 y! j% B }( \
count=USB_BLOCK_SIZE;
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);8 u' r t, }1 f! c
if (i == 0U) {' s9 S- U% G+ U. a( u
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;2 n7 [1 `2 j4 l' i( C
if (count >= n) {
count = n;
} else {; u+ @# Y8 O \
count = 0U;& Y, U o1 S0 O3 L2 Y1 m3 g+ v
}
}
}
if (count != 0U) {! F" x; e, l! ?% v2 T
TransferSize = count; F4 K+ {. w* V9 F+ h0 T
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);
}
}
}
//}
return 0;" M9 Z4 W9 g0 I V, c5 X
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.# F/ e9 H7 p8 t. Q0 F9 L6 P$ l' H
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).- o1 n* w5 i( a
static volatile uint32_t SWO_EventFlags=0;
static volatile uint32_t timeout=osWaitForever;1 {# z9 @7 m7 Y# o
static volatile uint32_t timeWait;
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;
uint32_t flags;
uint32_t count;
uint32_t index;( ]) D$ w5 C$ Y8 s
uint32_t i, n;) _, p3 q9 s7 x1 o) Z# V5 D' k
//(void) argument;
//timeout = osWaitForever;
3 t+ d& j! _% j- `% d3 e% ]! M1 S
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);; i* Y+ N2 p' D
if((SWO_EventFlags & 0x01)==0)
{
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了- [: b' R9 R `8 f
return 0;4 `. S: _7 I* U
}
0 V3 Y' ?" D, I5 l+ V
flags = SWO_EventFlags;% Y# a" O3 W& o" }- L7 J
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {$ G% k# j" ^# s
timeout = SWO_STREAM_TIMEOUT;7 ^" X* h5 i# f2 Z E
timeWait=DWT->CYCCNT;+ s- C. f# h6 |6 x/ b! ~
} else {
timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}
if (TransferBusy == 0U) {
count = GetTraceCount();4 G; h6 l; y: M1 }0 b
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);+ h* u/ p; D5 I
n = SWO_BUFFER_SIZE - index;3 q/ f# A) v3 A/ Y8 B
if (count > n) {
count = n;7 g& z' r6 W/ O8 m ^, \8 I
}
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;6 d2 H- _8 P2 {* ?7 t
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {4 }7 b/ b2 r( G- H& ]' D0 K
count &= ~(USB_BLOCK_SIZE - 1U);
} else {( B" a; y& a6 D( K) f
n = USB_BLOCK_SIZE - i;" `" l4 n6 e5 a4 C
if (count >= n) {- v- i5 M8 `! D% I& p% A. A- g
count = n;
} else {
count = 0U;0 c" ]* W# _' H) }8 e2 F
}
}
}
if (count != 0U) {
TransferSize = count;
TransferBusy = 1U;/ X \0 }! T2 B9 \
SWO_QueueTransfer(&TraceBuf[index], count);8 Q+ ?5 W4 l! ^
}" ]; S4 n8 U8 h e$ e
}
}* R4 W% J9 ?( r: w5 X, O6 W
//}6 P& f! z4 D0 X5 C! w- n
return 0;' }! j# |8 y8 X9 d* O( z1 ~
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了
6 \1 _& s- K" q3 e: 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,少了这个等待时间,能增加端点的传输速率$ U, R7 R- F) B
int main(void)
{% m7 O Y }( [( e) B5 E! Z9 i
DWT_Init();
DAP_Setup();6 L2 t8 j$ ] ^5 I
USB_Interrupts_Config();
Set_USBClock();3 E9 p, `% B$ ~3 {
USB_Init();
//TIM3_Init(35999,0);# e+ ~2 B: T+ n6 }5 x6 `
//TIM_Cmd(TIM3,ENABLE);3 o) Q' |% l$ `" j; R9 ?
+ z5 i! D9 [9 w+ `7 @" T
while (1)
{
DAP_Thread();4 y9 R& T8 A. Y0 R0 P; i8 ?
#if (SWO_STREAM != 0)( S% L: j2 b+ t$ c. V) U
SWO_Thread();: g0 `$ h( t% P, [ d3 ^3 T( l
#endif
}
}
5 m% R. f8 t6 u0 X1 O8 j) o
对于DAP_config.h的IO配置我是这样弄的1 l3 f/ Q* p E( I( Z
///@}
// Debug Port I/O Pins- H! H( I& L# C1 b) X8 J
// SWCLK/TCK Pin GPIOA[6]
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198* _! N8 k9 _) ?
#define SWCLK_TCK_IN *( uint32_t*)0x42210118! g( R f. K$ V6 _. L
// SWDIO/TMS Pin GPIOA[7]2 T0 {* T6 F; J# w8 p
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C
// SWDIO Output Enable Pin GPIOA[7]
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 1; \
*(uint32_t*)0x42210074 = 1; \ w9 F9 q3 F4 h0 |
*(uint32_t*)0x42210078 = 0; \
*(uint32_t*)0x4221007C = 0;}
# E8 z( f8 I! i/ {" J+ Y2 {
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 0; \
*(uint32_t*)0x42210074 = 0; \& a* ^" G( v! q9 ]3 F
*(uint32_t*)0x42210078 = 0; \4 Y6 C6 o8 V9 O
*(uint32_t*)0x4221007C = 1; }
// TDI Pin GPIOA[8]
#define TDI_OUT *(volatile uint32_t*)0x422101A0 b. z! r" ?1 k
#define TDI_IN *(volatile uint32_t*)0x422101203 U! w, U2 J; v, z8 A5 a% j( k' I C
// TDO Pin GPIOA[10]$ E/ n. `' L. Y$ F' [
#define TDO_OUT *(volatile uint32_t*)0x422101A8
#define TDO_IN *(volatile uint32_t*)0x42210128
// nTRST Pin GPIOB[3]! X, M! p6 m2 X1 G( G- a
#define nTRST_OUT *(volatile uint32_t*)0x4221818C1 z$ [6 ]' K8 o3 r+ U3 v( u
#define nTRST_IN *(volatile uint32_t*)0x4221010C8 a% \8 X4 s2 _3 o6 ^% n
// nRESET Pin GPIOB[4]
#define nRESET_OUT *(volatile uint32_t*)0x42218190
#define nRESET_IN *(volatile uint32_t*)0x42218110. S6 e; h5 E% V: p, i
4 [& \, C2 n$ C
// nRESET Output Enable Pin GPIOB[4]# v+ U; \; u; m+ i' u) O# H5 [8 b
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \, B' p; s1 m' B" A! G
*(uint32_t*)0x42218040 = 1; \
*(uint32_t*)0x42218044 = 1; \+ i" Q1 F. z c V0 f9 d' b" X
*(uint32_t*)0x42218048 = 0; \
*(uint32_t*)0x4221804C = 0; }
2 y6 N2 {3 P: N( q3 { m/ u1 V+ d A' O
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \. M8 e0 n/ W" i
*(uint32_t*)0x42218040 = 0; \
*(uint32_t*)0x42218044 = 0; \8 I2 T5 |0 z% h5 j0 ~" U1 e
*(uint32_t*)0x42218048 = 0;\. p# I5 N# a# v; Q
*(uint32_t*)0x4221804C = 1; }
% Q( U1 x% ]* e8 B
// Debug Unit LEDs0 d8 G3 L* O0 i. L
// Connected LED GPIOC[13]
#define LED_OUT *(volatile uint32_t*)0x422201B4) H- Q! I0 }! L4 z" d5 j1 `
#define LED_IN *(volatile uint32_t*)0x42220134/ Z% f" E9 l( }8 B
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \* @2 k; U( k9 h: Z) Z+ @$ @
*(uint32_t*)0x422200D0 = 0; \7 i( r6 {' h- r9 x) _1 f q, L
*(uint32_t*)0x422200D4 = 0; \8 V- O$ v0 ?/ a% k* @# } T! J/ A/ r7 O
*(uint32_t*)0x422200D8 = 0; \" ~) g- _% y5 L0 s9 T( O% g) }
*(uint32_t*)0x422200DC = 1; }+ ~$ D5 E& ?# O# u
// Target Running LED Not available. a- h, b; F! o' `: `4 e1 e
( b; R' C. ^) S) i, n9 R, ~( `% h
// SWCLK/TCK I/O pin -------------------------------------
/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.* m1 \; B* E# ~5 P
*/) |7 Z& g$ _1 d
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return (SWCLK_TCK_IN);
}
/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.: n) c3 e. M. r" c+ f9 P7 l
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {
SWCLK_TCK_OUT = 1; Q( r4 P ~# Z& L
}
! D- |% |8 N3 ~1 f) U0 L3 m
/** SWCLK/TCK I/O pin: Set Output to Low.% L) h9 m3 h8 K8 M: H! |* t
Set the SWCLK/TCK DAP hardware I/O pin to low level.0 j0 X3 M: w. O
*/! H, p% H; a3 @* D0 f
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
SWCLK_TCK_OUT = 0;' a' e/ Q3 _& b/ A `" C# M
}& u1 f8 ~- C, S7 F5 r( o( w0 c
// SWDIO/TMS Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input.+ R* r; c6 ~7 _4 d
\return Current status of the SWDIO/TMS DAP hardware I/O pin./ u! A4 \ |# c, h8 P; t
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (SWDIO_TMS_IN);
}
8 K5 G- Y- o6 r. J8 D0 Z8 E4 f
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) { r3 p! ]! ^. x8 h
SWDIO_TMS_OUT = 1;
}; A4 V# n% q& O: d# n& e- w
' Z ]7 I; n5 U/ F2 y9 [
/** SWDIO/TMS I/O pin: Set Output to Low.6 m0 x( g: v' E/ h. H
Set the SWDIO/TMS DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {% m: W2 |& Z/ _% ^/ c+ `, Q
SWDIO_TMS_OUT = 0;% z; c" L& U5 \6 |% ]
}
: @/ n9 ]1 X& A- }
/** SWDIO I/O pin: Get Input (used in SWD mode only).8 J+ f0 L# T7 t# P( e( X5 ?& |1 |
\return Current status of the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return (SWDIO_TMS_IN);. G6 D* k5 X+ h* t! P& ?6 j2 @( C
}
/** SWDIO I/O pin: Set Output (used in SWD mode only).+ `) w% b- ^3 o3 W
\param bit Output value for the SWDIO DAP hardware I/O pin.% s8 N; D0 w. y! w
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
SWDIO_TMS_OUT = bit;
}3 l. Z: F- C% O. ~
/** 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& Z8 m* G, L2 ?% _" s2 f" V1 r
called prior \ref PIN_SWDIO_OUT function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {
SWDIO_Output();; s/ @" C% S5 _# x$ b
}+ ^( Z' E& V8 \; a9 v
w, A/ w& t7 j" V% x
/** 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! v1 z3 y: l3 k% V& g( p
called prior \ref PIN_SWDIO_IN function calls.7 o" g7 U* l: v9 h6 J6 l
*/' L6 R) f( h7 w: B! |9 v9 i
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
SWDIO_Input();
}
楼上有的说弄无线,其实无线也就是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驱动的大佬可以尝试一下& d0 ^2 i; n' ?8 p) ?) U
有人将这个工程移植到stm32f4上吗,我在网上找了一个f4的dap工程,但是编译下载后无法使用。