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发出复位命令。
2 c% ]* P5 b# ~
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。, p: ^0 u. [& `9 x8 r: h7 L2 i
; Z5 F/ @7 v2 Z
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。
7 w l* C( @5 |+ r6 j( U
/**
******************************************************************************2 |" Y( Z6 w. A
* @file usb_endp.c r7 ^3 V2 q' }" K6 f6 e& }8 T
* @author MCD Application Team
* @version V4.1.0
* @date 26-May-2017
* @brief Endpoint routines
******************************************************************************
* @attention" ?& g- C" D4 Y* I. s2 e# R V |( {
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*3 {( W1 y8 x* p, P4 y
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:: D7 O* c2 r$ ~% `' `# R
* 1. Redistributions of source code must retain the above copyright notice,: E+ {! {8 ~- z) I+ q
* this list of conditions and the following disclaimer.* W8 r d/ Z9 m+ N1 f
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation" a% T! B' i, H9 U2 ]
* and/or other materials provided with the distribution.3 S) C, Y0 V8 \. t4 G
* 3. Neither the name of STMicroelectronics nor the names of its contributors: ^7 n) N- G* G6 a
* may be used to endorse or promote products derived from this software2 C+ z f* ~! c, Z
* without specific prior written permission.
*. Q' v1 a- I3 @2 @: e( Z5 y2 P
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", W" G. V* L4 v8 c) a/ S# t9 n$ l- k
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE0 u7 P% t4 |/ z9 f9 c# g4 |' |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE$ [& K; N" l* a: ?$ y, O, s$ w
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE [2 L8 g3 n8 D* H7 f+ D# g
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL2 C9 |+ \$ T& P8 V9 B
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR& g+ Y% P. K& T
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,' B& i1 s3 C! A" q+ f4 r2 K
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE8 h! S* U2 P8 l" z2 Z9 E6 N
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*8 J& D8 G( M/ K( I, r" e* f
******************************************************************************
*/
" m' Q- [* ?2 F1 c1 R& c& J
9 Z4 |# j* |- k/ M; c
/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"
#include "usb_lib.h"
#include "usb_istr.h"
#include "stepper.h"- e/ ^6 e! k' g% Y$ f
#include "string.h"7 o- y" Y' ^: B- M- O
0 Z( a- E. N: \
#include "DAP_config.h"
#include "DAP.h"
- V- @% _% i3 t
$ x" k0 ]+ l% p! }+ n( g) U$ S4 j
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/' M& Y/ j9 e n; L" ]1 w
static volatile uint16_t USB_RequestIndexI; // Request Index In
static volatile uint16_t USB_RequestIndexO; // Request Index Out: t. q. S; \* S" q5 E
static volatile uint16_t USB_RequestCountI; // Request Count In c7 k/ g1 s$ l& c3 B" \
static volatile uint16_t USB_RequestCountO; // Request Count Out5 z* d% }; W5 r! @
static volatile uint8_t USB_RequestIdle; // Request Idle Flag
static volatile uint16_t USB_ResponseIndexI; // Response Index In) r7 [6 r1 s% \1 _% k4 U6 N
static volatile uint16_t USB_ResponseIndexO; // Response Index Out* r3 g+ C' ]$ N- B
static volatile uint16_t USB_ResponseCountI; // Response Count In/ t8 ?; R% i/ A1 M
static volatile uint16_t USB_ResponseCountO; // Response Count Out
static volatile uint8_t USB_ResponseIdle; // Response Idle Flag& B9 }# R A" F6 i) U2 H7 ]
static volatile uint32_t USB_EventFlags;
static uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE] __attribute__((section(".bss.USB_IO"))); // Request Buffer6 w- k% g$ g \) q5 M+ @ R
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];2 D: W9 V( B0 k$ r) B$ z4 R
' P. G3 h1 ]9 e' U; Y- q, g" R
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/# R& g* \5 ~5 n+ F
/*******************************************************************************
* Function Name : EP1_OUT_Callback.8 m/ k! p1 i* T& H0 V+ v
* Description : EP1 OUT Callback Routine.
* Input : None.$ p9 x) D, ]! s! o: ^" H. X" J
* Output : None.
* Return : None.# `2 V, `' Y: u2 d4 u- D
*******************************************************************************/
void EP1_OUT_Callback(void)
{
uint16_t n;; `( t2 l% b" h1 h$ [: N z6 |
n = GetEPRxCount(ENDP1);* O1 s& t% R& v. \ {
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);; b6 b4 l4 n. u8 T% Y: y
if(n !=0){
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {% i5 B5 h. W9 c/ d% Y
DAP_TransferAbort = 1U;
} else {
USB_RequestIndexI++;* a6 ?' ~, m5 C7 A/ R$ h+ n
if (USB_RequestIndexI == DAP_PACKET_COUNT) {
USB_RequestIndexI = 0U;% a! n V8 H. \, B, T% x
}* Y6 o. ^1 f. L5 S' \4 n: }
USB_RequestCountI++;2 R+ N7 a b/ ]+ D W4 T7 N
USB_EventFlags = 0x01;' K o' y& z, X# ^* U; J4 Q
}8 K5 V1 [5 {! p& D
}
// Start reception of next request packet# V! }% Q( s, Q6 q
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
SetEPRxStatus(ENDP1, EP_RX_VALID);
} else {& N6 d5 e" V! f' ]; [. K
USB_RequestIdle = 1U;& G7 k* J4 G0 s7 B- I8 }
} 2 W( _' z, X- y( Q" Q8 T5 Y, z
}. d2 F9 f: ]* B4 K# v h' Y
/*******************************************************************************
* Function Name : EP2_OUT_Callback.4 ^5 v4 F7 |1 i( v) d
* Description : EP2 OUT Callback Routine.
* Input : None.
* Output : None.1 X1 `3 r7 n" S C: v
* Return : None.; F- A% C9 _0 b( h! A7 f
*******************************************************************************/
static volatile uint32_t TX_n;
static uint8_t *pbuf;7 s! p! R& k: q
void EP2_IN_Callback(void)
{
uint32_t a;
if(TX_n>0){: X8 C8 O: _( f9 [" U
pbuf+=64;
if(TX_n>64){) o. G) z7 k- ~& j c- r" T2 m
a=64;
TX_n-=64;
}else{
a=TX_n;
TX_n=0;
}
4 E: ?* y' l/ v' k5 W# m
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);* }* L7 S' G* u- @
SetEPTxCount(ENDP2,a);3 e2 I7 t ], t+ J2 H' d7 p1 ?
5 w/ n' X6 R+ L; K8 [0 ?" a
SetEPTxValid(ENDP2);
}else{
#if (SWO_STREAM != 0)
SWO_TransferComplete();
#endif
}
}7 D" j# W3 d* N
" J" Y, |* R' H* R2 |6 X/ h9 }
/*******************************************************************************
* Function Name : EP1_IN_Callback.: ^! {) O& Z) u7 ^3 T! D
* Description : EP1 IN Callback Routine.! e9 ~7 B- l4 \. o& Q
* Input : None.
* Output : None.
* Return : None." j+ C( O3 k+ O6 `
*******************************************************************************/
void EP1_IN_Callback(void)
{
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back2 q2 W) N/ J9 n- N5 S& f
UserToPMABufferCopy(USB_Response[USB_ResponseIndexO],ENDP1_TXADDR,USB_RespSize[USB_ResponseIndexO]);
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);2 H* K: z. v3 E2 k. g+ r+ q/ g
SetEPTxValid(ENDP1); 6 t0 I( _* l: m" n W& V
USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;
}+ K( T2 f& c7 w/ L# W& H' e) Y
USB_ResponseCountO++;
} else {) Q' H0 R0 o `
USB_ResponseIdle = 1U;
}
}1 w( }& @' i( Q" U# I. o
, l. v1 D. @) q& R Q# i$ B
// Called during USBD_Initialize to initialize the USB HID class instance.
void DAP_FIFO_Init(void)
{
// Initialize variables# Z$ P$ v8 w. o7 O+ x& q
USB_RequestIndexI = 0U;
USB_RequestIndexO = 0U;
USB_RequestCountI = 0U;# Z" V* C3 r; Q0 t$ W; x
USB_RequestCountO = 0U;; X9 D X! n; V: |; d; u, y6 L
USB_ResponseIndexI = 0U;; u: O" A) N, b- I" \) J( ^
USB_ResponseIndexO = 0U;$ d5 {* Q; g/ _! F; n8 J( C
USB_ResponseCountI = 0U;& H1 L1 U3 C( W2 `+ b
USB_ResponseCountO = 0U;$ L) s8 n, {8 y
USB_ResponseIdle = 1U;9 K& c" I) U* n$ g \$ G6 X
USB_EventFlags = 0U;
}7 x5 w" E' p% y& C
6 f# l/ e' X6 X, X7 i
uint8_t DAP_Thread (void) {6 q" |& L3 G8 n7 ^8 y
uint32_t flags;
uint32_t n;. r" R! G2 l! r
//for (;;) {
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);% M/ Y9 w6 M3 L/ i4 Z) d& n5 c& X
if((USB_EventFlags & 0x81) == 0)& l4 B, x/ e/ h" C7 F; H
{+ v- l1 C6 H/ m' ^
return 0;
}
USB_EventFlags &= (~0X81);
- T- Z; z1 j; b2 `7 i; f& y ?
0 j) z; M. E# I+ z6 z* l& z2 \
// Process pending requests, G3 k1 w% L) G2 H I8 A& J
while (USB_RequestCountI != USB_RequestCountO) {
//if (USB_RequestCountI != USB_RequestCountO) {
// Handle Queue Commands
n = USB_RequestIndexO;
while (USB_Request[n][0] == ID_DAP_QueueCommands) {
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {% V, f" h6 @ B+ @
USB_Request[n][0] = ID_DAP_ExecuteCommands;+ x1 [, I7 G, |0 K1 e! g0 h1 D, b! B
n++;
if (n == DAP_PACKET_COUNT) {
n = 0U;7 a( {! K$ h' U; H" l/ I& t
}5 Z4 L: j$ c7 ~7 m% d2 y
if (n == USB_RequestIndexI) {2 J! T( ?- _4 m& k* ~0 ?
flags = USB_EventFlags;
if (flags & 0x80U) {5 ^# Q; A1 i' \* S2 B `
break;) g/ M$ O& z" e
}
}+ A1 n0 @% [* S- h! t# v7 U& V
}
// Execute DAP Command (process request and prepare response)
USB_RespSize[USB_ResponseIndexI] =
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);
// Update Request Index and Count( h$ ?) T8 O0 Y, w. ]! S. u
USB_RequestIndexO++;
if (USB_RequestIndexO == DAP_PACKET_COUNT) {
USB_RequestIndexO = 0U;& }, e! X( I3 b; W! G. C
}
USB_RequestCountO++;& s& }3 U: [. e- k3 I/ j; V
if (USB_RequestIdle) {
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {8 e# O/ i7 P4 S/ n, I. p
USB_RequestIdle = 0U;
SetEPRxStatus(ENDP1, EP_RX_VALID);6 v V. j T5 @& X& }
}$ ~; R7 K/ k$ R
}
: P, w6 S5 @' _+ L6 m
// Update Response Index and Count
USB_ResponseIndexI++;* L0 F7 g" ?2 M% p
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {' n/ }$ E" E* `, g6 ~1 x
USB_ResponseIndexI = 0U;
}* b- T# K4 n2 c; R' |/ I( ?
USB_ResponseCountI++;
if (USB_ResponseIdle) {
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back
n = USB_ResponseIndexO++;
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {
USB_ResponseIndexO = 0U;
}( c$ p- y9 D5 f- {6 k0 ~7 f
USB_ResponseCountO++;5 Z, ^7 h5 c7 f7 l" ^
USB_ResponseIdle = 0U;' |1 j/ L6 t7 x5 @% D
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);
UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);- x# Y; @: {7 o. H# X
SetEPTxCount(ENDP1,USB_RespSize[n]);$ X* h3 |4 n. Z( ]$ g: q8 y
SetEPTxValid(ENDP1);
}
}
}
return 0;
}; w% g, J- @; v1 a3 n+ p
// SWO Data Queue Transfer0 }$ ^# g4 ~7 {7 j7 q4 j
// buf: pointer to buffer with data) ?. M( ?' ?* k( G* V7 F
// num: number of bytes to transfer
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {2 r$ t+ i" s& p! y$ q7 r
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);6 L r7 B* ]1 ^3 \
uint32_t a;! a& e. @2 q/ d$ Z I
if(num>64)
{
a=64;
TX_n=num-64;% ]8 w) r# I9 t0 P
pbuf=buf;
$ T9 e' F0 S8 G. L# F- |+ f2 O- Q: t0 d- o
}else {: V5 y- @/ G1 U A
a=num;- F) X# `1 D( D; w! A
TX_n=0;5 B k+ h: m' d1 [* _; Q
}
UserToPMABufferCopy(buf,ENDP2_TXADDR,a); ?9 k* h; j# N4 K# ?8 q3 v
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);! {7 Z2 T; M h7 U$ P3 [
}
0 d# v. [9 z" v2 e; T
// SWO Data Abort Transfer
void SWO_AbortTransfer (void) {
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));
//SetEPTxStatus(ENDP2, EP_TX_NAK);; Q' L) [, F0 r. W& y! {
SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxCount(ENDP2,0);7 \( ]' M; W _' }
//TX_n=0;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
m( S0 G* R; _8 d
移植大概是这样的,利用STM32_USB-FS-Device_Lib_V4.1.0里面的例程Custom_HID修改为自定义USB设备,3个批量端点,OUT,IN,IN,由于批量端点不像HID哪样要使用报告描述符号,但要让WIN识别出驱动,添加了WINUSB相关的描述符号,在端点回调里实现DAP的FIFO处理,然后把DAP_Thread里面的线程调度修改为标志通过,放MAIN主循环里调用,测试SWD下载程序,调试都完全没问题,时钟设置为10M时感觉速度还是可以的,这能体现批量端点的好处
DWT部分即TIMESTAMP的时间参考,由于没使用Keil的核心库,得自己对相应的寄存器进行开启,而且3.5库的core_cm3.h里面没声明这个寄存器,只得自己定义一下了
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {
return (DWT->CYCCNT);, \* E( w2 R) S d
}
void DWT_Init(void)
{' D6 e$ c, g* I5 B6 ^" M$ z' R
/* 使能DWT外设 */% w3 k$ Y# V" w! f; w- R$ U
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
/ _" Q; N! d! v2 O* h, @6 H3 G+ h
/* DWT CYCCNT寄存器计数清0 */6 U+ g5 Z2 V' S+ T& R D( D& }
DWT->CYCCNT = (uint32_t)0u;; a- y4 J& h& ~) s
/* 使能Cortex-M DWT CYCCNT寄存器 */
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}" G M4 Q# F+ Q0 P+ q2 U
8 E/ h+ N5 h6 R
然后加入了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;" s% v, ~- l* R- ^" ]" s1 ]* \6 L, G
在SWO里每一处调用osThreadFlagsSet的地方都改为如:- A6 f2 U: i, p$ h) J; |& t
//osThreadFlagsSet(SWO_ThreadId, 1U);
SWO_EventFlags = 1U;- M: P2 w" T$ O5 L6 f
4 N; S4 p p0 K7 g C% @- G
// SWO Thread8 [) d) V5 z# w5 F8 y( A
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {) w% x, B4 ?# N. W- b/ C
//uint32_t timeout;
uint32_t flags;3 m8 X% v2 ]% _9 M$ l4 W! I- [
uint32_t count;1 B- V7 G- c3 d3 W8 E
uint32_t index;& l9 v/ }8 F* X: a7 f
uint32_t i, n;
//(void) argument;
//timeout = osWaitForever;. Q/ v6 Q" g" s: r8 r z2 d
3 T4 f9 t/ J# q- l" r* P
//for (;;) {) z6 U' g1 X& W$ O$ v: L$ C
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if((SWO_EventFlags & 0x01)==0)return 0;7 J( B. z2 l3 E- E* `
2 h! y! g b* R9 z
flags = SWO_EventFlags;0 n8 s% w# g" B7 Y" w
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {# j5 Q1 y" [% j1 \% A# j- R# Z
//timeout = SWO_STREAM_TIMEOUT; 这里是对于进入了SWO_CAPTURE_ACTIVE状态时就把线程超时设置为50毫秒,大概意思应该是osThreadFlagsWait到达这个超时时间后,不管标志是否切换为1U,都放行SWO_Thread调用一次,timeout = osWaitForever时相当于无限长的超时等待1U标志,对RTX不熟悉,不知道是不是这样子& l2 k4 A( E8 A G& m r: Q+ j
;5 N( ]- \6 a+ S' d: a" m
} else {
//timeout = osWaitForever;+ P! y6 t" g2 v) t; I% x x( x6 a2 F
flags = osFlagsErrorTimeout;1 [3 l+ g6 |+ @ h% Y" ^9 Y9 o
}: Z- B2 Y/ Z# K& _
if (TransferBusy == 0U) { n1 u' K- |% O# L
count = GetTraceCount();
if (count != 0U) {0 J9 g/ _( C1 k
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;+ \5 L; ?4 {+ \/ n- ^
if (count > n) {
count = n;9 [* D: {4 h8 A* S& m- ~: h) v
}
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;$ p3 d( A- ?# W5 o1 j! N3 f
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);* W5 W1 s) D: z8 [% t9 l
if (i == 0U) {/ D- K) c! G3 }# _
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;: d4 ^& Z& s1 Z' ]8 d% l
if (count >= n) {2 w# q) U; [; N. f% h) Y1 b- h
count = n;
} else {
count = 0U;
}
}9 i% U/ g. g9 @% k ~9 {' A7 D4 ~
}
if (count != 0U) {
TransferSize = count;
TransferBusy = 1U;/ V% s" ?+ W- f" O, z1 B
SWO_QueueTransfer(&TraceBuf[index], count);8 D' E3 c+ m- A- p& N4 C0 u# c0 j2 H! p
}
}3 f- z) ]# j) y+ ?
}
//}& z+ w6 c, w/ F
return 0;3 ~5 O! V4 _( ?& [ L# F
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.- W& P Z6 w0 v* E
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).' } G/ p: _+ d1 C
static volatile uint32_t SWO_EventFlags=0;; S- z# I G2 S6 V% t) @+ G, w% I. `
static volatile uint32_t timeout=osWaitForever;5 z; e# h( r2 G2 \3 D% D
static volatile uint32_t timeWait;
函数改为这样+ X- Q8 ^0 |5 C6 t3 U$ }
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {1 x4 p( \/ N7 S, E
//uint32_t timeout;
uint32_t flags;
uint32_t count;! P2 ]' D( O! r$ O0 R# }+ w
uint32_t index;
uint32_t i, n;
//(void) argument;: t1 D' K7 ^7 ~; |/ L4 t+ x
2 G9 z z1 v% \- v1 ~) v5 o
//timeout = osWaitForever;
8 N$ O5 N7 w$ \9 m) i, n* W
//for (;;) {
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);! U3 O- m1 ]: O: _( n* b2 T
if((SWO_EventFlags & 0x01)==0)6 U4 _ y7 P: E3 B" P
{
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了# Z: K9 P1 r# P6 h7 @( p5 c
return 0;- w" d. G8 w9 M! p0 w, _
}' E. ^2 X. `/ u% P( d
7 f! I- I* n6 v' B
flags = SWO_EventFlags;
SWO_EventFlags = 0U; 2 D/ c K6 l4 ?, H6 |
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {* B9 O! _) u4 ^
timeout = SWO_STREAM_TIMEOUT;
timeWait=DWT->CYCCNT;* ?- u# ^6 l0 o" q2 A& Z
} else {, r$ u! |3 L0 J% @
timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}: C# H! ]: N3 U4 O5 v* ~
if (TransferBusy == 0U) {
count = GetTraceCount();
if (count != 0U) { a5 z8 T3 [# W" k
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;5 l, _1 ^; Q3 N; O s1 z
if (count > n) {
count = n;5 U4 a* J3 S+ V7 w
}6 ]+ \# U. r( Z3 Q7 T3 [
if(count>USB_BLOCK_SIZE). c/ Z$ C& p; J* G$ w, `% x5 a- q
count=USB_BLOCK_SIZE;
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {3 w/ ^2 c2 u% [! D1 o' h" Q
count &= ~(USB_BLOCK_SIZE - 1U);- R- M' l; m$ r/ g2 c8 p! m
} else {
n = USB_BLOCK_SIZE - i;
if (count >= n) {
count = n;
} else {
count = 0U;
}6 p' ?0 ^9 Y& y; Q
}
}
if (count != 0U) {
TransferSize = count;
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);
}' O1 P4 z K, W. B$ i
}
}% h8 K& k2 w1 q
//}, c1 M, ~. k5 ], P- d6 X/ @
return 0;
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了4 a2 u/ n3 n; O' v j
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,少了这个等待时间,能增加端点的传输速率( R7 Z% }% `. Y) x3 p9 [& b4 i$ n
+ c. j0 Z; _0 Z
$ w8 q% a' d8 I
int main(void); k8 ?1 W+ d5 y% l$ A6 U
{) j7 m/ Z0 R( g$ z7 t1 l% M
DWT_Init();
DAP_Setup();: v8 Q. V* R2 ^9 O% a/ E
USB_Interrupts_Config();
Set_USBClock();
USB_Init();1 m* C, E7 Y7 R$ U$ \
//TIM3_Init(35999,0);- @, ^1 P, [+ q$ m5 C! T3 T' `3 q/ n
//TIM_Cmd(TIM3,ENABLE);$ ?8 Z: d% }; m6 f
/ r' s7 l6 O9 o
while (1)3 W: U" q) v0 N4 `- x
{
DAP_Thread();
#if (SWO_STREAM != 0)
SWO_Thread();
#endif
}
}
$ K2 y1 X* I2 c2 l9 [' _5 O3 j- M
对于DAP_config.h的IO配置我是这样弄的: X+ A% `( I4 Z! Y; d! \1 | d% N) X
///@}3 h6 t: g- S2 ~) u
// Debug Port I/O Pins! N8 d5 ]: @) w; O* B
// SWCLK/TCK Pin GPIOA[6]
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198
#define SWCLK_TCK_IN *( uint32_t*)0x42210118
4 z; q( { `; _
// SWDIO/TMS Pin GPIOA[7], c+ [; y7 c7 e" w Z* ^
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C# {% ~, T! g1 P$ { a4 p
// SWDIO Output Enable Pin GPIOA[7]
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 1; \
*(uint32_t*)0x42210074 = 1; \
*(uint32_t*)0x42210078 = 0; \
*(uint32_t*)0x4221007C = 0;}0 }# Y p7 I; `! _( l( x
8 W A4 F& G) i& \
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 0; \+ ]# ^ V2 Z. z( Y# l3 K% c0 v' x8 E
*(uint32_t*)0x42210074 = 0; \
*(uint32_t*)0x42210078 = 0; \5 D6 U$ l# U# n6 q$ m7 h5 L
*(uint32_t*)0x4221007C = 1; }! T0 P0 z! @/ C2 a( ]8 k
, g1 b$ d4 h3 h8 H4 x. \) S5 ^
// TDI Pin GPIOA[8]- c" G5 x1 t- d' |# t' f
#define TDI_OUT *(volatile uint32_t*)0x422101A02 p0 N/ A% p9 E
#define TDI_IN *(volatile uint32_t*)0x42210120( H. L& c, B8 F& P, a" F% l( U: @$ [
. {$ q: l! O: G k& i% P
// TDO Pin GPIOA[10]( m3 D) y. I: A/ F3 z) d
#define TDO_OUT *(volatile uint32_t*)0x422101A8. ]1 J* T) ^; x% E
#define TDO_IN *(volatile uint32_t*)0x42210128
// nTRST Pin GPIOB[3]! E! S; l+ i/ X/ v1 ^
#define nTRST_OUT *(volatile uint32_t*)0x4221818C
#define nTRST_IN *(volatile uint32_t*)0x4221010C( ~4 \. Y6 h0 I, a. ]
- N5 s/ C" W8 E) N0 s3 W9 Q
// nRESET Pin GPIOB[4]
#define nRESET_OUT *(volatile uint32_t*)0x42218190
#define nRESET_IN *(volatile uint32_t*)0x42218110
// nRESET Output Enable Pin GPIOB[4]) ?& B' H6 g/ e" U( \
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \" |$ q" T, L* S+ p5 E
*(uint32_t*)0x42218040 = 1; \" B8 ^6 S' g. y( ^: f5 Y% h. q& B
*(uint32_t*)0x42218044 = 1; \* s* C' @, X6 E0 s: @( e; z$ V2 Q2 V
*(uint32_t*)0x42218048 = 0; \
*(uint32_t*)0x4221804C = 0; } 4 a, g6 s# e. n! `3 w! i
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 0; \3 S8 e: `- h) H( i7 ]) x, p
*(uint32_t*)0x42218044 = 0; \
*(uint32_t*)0x42218048 = 0;\9 B% g9 l! e2 W
*(uint32_t*)0x4221804C = 1; }
9 n7 ^7 P( |1 q( |7 c+ N* B# V
// Debug Unit LEDs! ~6 P3 C, G0 P
3 Q9 o7 U/ n; r
// Connected LED GPIOC[13]1 | J, U6 e Q2 C" o
#define LED_OUT *(volatile uint32_t*)0x422201B4( S2 d6 S0 B% d$ |3 a
#define LED_IN *(volatile uint32_t*)0x42220134
- |' p, |+ l6 s4 z: ^( }
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \
*(uint32_t*)0x422200D0 = 0; \* h% ?0 S+ B# ~, u% f
*(uint32_t*)0x422200D4 = 0; \3 g0 W" b e5 ~) l: k- C, ~+ T
*(uint32_t*)0x422200D8 = 0; \
*(uint32_t*)0x422200DC = 1; }6 |: b. Q# Y( S' Q/ m' |" z
// Target Running LED Not available0 Y6 r& Z. A0 |$ f# X7 b
// SWCLK/TCK I/O pin -------------------------------------( o! p2 n$ c) Z& ]
. I* |1 V4 P% ], f
/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.: P0 J* S/ P; r, N8 F" U
*/- ^. L/ Z4 k) @8 X3 h/ D
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return (SWCLK_TCK_IN);
}
9 M: V" e' E6 N8 z
/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level./ c2 H3 Z9 s @. Z& f. {( V# `
*/; z* }4 i2 S! \; _
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {2 ]7 Q8 Y5 Q; y
SWCLK_TCK_OUT = 1;0 R! a* B# E4 u, T2 h. K
}
8 x- r R+ V/ T& A& n' [* ?
/** SWCLK/TCK I/O pin: Set Output to Low.0 o- z! ?# Z" o, t
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/* p6 R3 w* I( p7 [( B( ^
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {& l0 f$ t& ]% l, W
SWCLK_TCK_OUT = 0;
}
/ n& _# m, V& K* J* w! t% }
// SWDIO/TMS Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input.6 x' P6 E+ F" R7 h) g4 w c
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/9 B7 ]2 u L7 ^, o9 i
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {7 R0 F& J$ a9 V6 M% z0 h
return (SWDIO_TMS_IN);7 S) R5 l r8 i+ @7 O2 O
}
9 ~% Y- d) M$ {0 D; A, W3 W
/** SWDIO/TMS I/O pin: Set Output to High." n9 k! u# b) i0 f) H0 M {6 g
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/6 K N1 S: j) s2 R1 @* S
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {4 ~2 r7 y1 G) f. K
SWDIO_TMS_OUT = 1;
}
3 s# T) d8 `% Z7 ?: r2 T5 F W: W
/** SWDIO/TMS I/O pin: Set Output to Low.# z9 n4 ]0 z0 K5 Z6 z( z
Set the SWDIO/TMS DAP hardware I/O pin to low level.5 b5 ]$ |# U' q1 F9 W5 Z4 ?5 H" {' @$ W+ i
*// @/ U6 m( f' M9 g( d3 @0 Y0 z. c
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {2 r0 W5 }0 U# F5 | T8 x
SWDIO_TMS_OUT = 0;! x$ E8 R( I a8 i7 C; e* A
}) V4 Q$ f3 y+ B* ]" s: R; a
/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin.* f) ?7 {8 f% {
*/3 _: ^5 n7 z& J% L
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {! ^+ v' i- {5 b" b
return (SWDIO_TMS_IN);
}7 i. T" ?) y8 q/ Y; g& q3 W- A% k
- h" S- P. @- a3 `
/** SWDIO I/O pin: Set Output (used in SWD mode only).( t% h8 i6 I) U, {* R
\param bit Output value for the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
SWDIO_TMS_OUT = bit;- t& U" i" F1 @: x3 t5 Z1 Z
} Q* B9 z2 |0 `1 x# O
/ U7 I, C; S% p* U9 h
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).3 K5 B( q8 \: q2 m/ l. G k; q
Configure the SWDIO DAP hardware I/O pin to output mode. This function is# l$ D0 n! @. M0 w8 I
called prior \ref PIN_SWDIO_OUT function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {
SWDIO_Output();3 k T2 B" p: {2 c1 \) A: q% O
}
6 i' j8 b( C- p: j
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).4 u3 \3 h7 D% C5 r. V8 @; [/ B5 y
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) {4 P) V8 P, ]0 J. `* v& o
SWDIO_Input();+ B$ l* N9 w, Y' `1 I7 A1 y5 D- r% n% m
}
楼上有的说弄无线,其实无线也就是PC<->USB<->无线模块A<->无线模块B-DAP,数据传输的速率主要是无线模块之间的速率限制了,也是非常简单的* C0 L! g% i5 F8 R6 M) M- e& F) L$ @
即单片机先做好USB接口部分,OUT端点收到的数据发送到无线模块A,无线模块B接收到数据后,推给DAP处理,DAP响应的数据再让无线模块B发送回无线模块A,再通过USB发送回PC,也就是说USB与DAP之间也就多了两个无线模块作为数据的交换,要是会写USB驱动,写个虚拟WINUSB设备的驱动,让Keil的DAP驱动能识别到这个虚拟USB设备,通过ESP32利用WIFI通信应该比使用这种无线模块更快,而且ESP32主频更高,即使IO模拟 SWD接口,都会更快,会写USB驱动的大佬可以尝试一下
有人将这个工程移植到stm32f4上吗,我在网上找了一个f4的dap工程,但是编译下载后无法使用。