【MCU实战经验】+STM32F103的uCOSII详细移植
游名科技:STM32F103+TMC2160:86步进电机和驱动一体原理图/PCB...
小马哥STM32F103开源小四轴RoboFly全部资料大放送
在高容量 STM32F103xx 微控制器中实现 ADPCM 算法
STM32F103标准库开发---SPI实验---读写 W25Q128 外部 Flash
RT-Thread在STM32F103RC上移植
STM32固件库分享,超全系列整理
【原创】STM32F103的SPI2的配置函数,DMA发送和接收!
【福利】用STM32库的朋友有福了:STM32F10x_StdPeriph_Lib_V3.5.0chm...
基于STM32F103做CAN的收发通信经验分享
我这个是有复位信号输出线nRESET的,不过IDE要懂得向DAP发出复位命令。+ L4 T: A+ z# y1 l: n/ w7 ~, W9 l: I
软件复位是另外一种情况,需要向目标IC发送复位“密码”,Cortex的IC有这样的密码。 这就不需要连接nRESET线了。
nRESET是受使用CMSIS-DAP的IDE的逻辑控制的, 不能随便修改。) l8 i, k# l% o/ m& u5 a
你要的功能应该不是一定需要走nRESET这条线, 随便找一条空闲的GPIO,模拟一下DTR/RTS,很容易的吧。& T/ e; f: {, m
7 T! u/ d, b& ~$ p
你用的功能好像只是用USB转串口,那么就应该使用USB-VCP的程序来改。
或者买一个有DTR/RTS线的USB转UART的小板, 便宜得很, 5~10元一个。
/**
******************************************************************************
* @file usb_endp.c
* @author MCD Application Team7 p. z- |5 @0 C9 p O* o; N
* @version V4.1.0
* @date 26-May-2017& Y! V: X: v2 v! ^* f* W8 @; O
* @brief Endpoint routines
******************************************************************************! w* }" P5 V3 P6 `- M: [
* @attention/ O+ k3 N' [9 k+ E; n2 | W6 \
*0 ^/ `" X; P& h: V
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,1 m- o$ Y" _( |
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,8 m9 o2 V1 E" A. x
* this list of conditions and the following disclaimer." v+ Y, i0 t" d! Z. P- e! c. e+ V4 Q
* 2. Redistributions in binary form must reproduce the above copyright notice,+ S/ _4 e! l: ~) W2 n7 ]
* 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 software3 s- T+ i; w5 G" q! E
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE' Y( \8 M! t& |* X2 }
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE* J- V6 J& M" _5 P
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR n5 b6 ?5 F2 w S% a: v W; }( D
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER" F) L3 Q* P' s& ]
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,0 E) [% e* O) ^+ j8 i% p6 @
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE" B. Z( K% P& C: a
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*6 |3 G2 g0 l' o
******************************************************************************6 @' V* E8 S1 `7 R+ D
*/
5 x0 o" G. R. [: l! ?: P
+ V. o! ^# s- C! e" u
/* Includes ------------------------------------------------------------------*/) d3 R1 j: d# K' A
#include "hw_config.h"
#include "usb_lib.h"
#include "usb_istr.h"5 |; p! N0 O6 \: A4 a5 G0 {
#include "stepper.h"1 S5 F4 O# O9 {" G5 Z
#include "string.h"3 k' }+ n9 b/ ^3 B6 P; G
& u' H# t, c: F. D# x" F
#include "DAP_config.h"6 Y, D3 s; t% F8 k# }3 v
#include "DAP.h" T8 t. e5 o3 t: \3 S8 l Z2 m5 B: p
6 N( I& H( _+ l9 ~
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/( d6 T; |. H0 Y- j, {
/* Private macro -------------------------------------------------------------*/ P, t$ W/ I* d
/* Private variables ---------------------------------------------------------*/% Z, `9 g8 U9 o: u" S
static volatile uint16_t USB_RequestIndexI; // Request Index In8 @- \* z: y: w3 b: v4 X" B
static volatile uint16_t USB_RequestIndexO; // Request Index Out
static volatile uint16_t USB_RequestCountI; // Request Count In4 R) d4 f7 f/ C( i/ x1 k/ Y
static volatile uint16_t USB_RequestCountO; // Request Count Out
static volatile uint8_t USB_RequestIdle; // Request Idle Flag/ D8 v* D Q* B6 b9 |1 v7 L m
3 {3 C, F5 K2 Y. J$ s
static volatile uint16_t USB_ResponseIndexI; // Response Index In
static volatile uint16_t USB_ResponseIndexO; // Response Index Out5 E$ T0 o$ k# g: K' O+ r
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; r2 P4 V: x7 o4 P) e$ F
static volatile uint32_t USB_EventFlags;
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' q" w7 g& l" W. h" V& p
static uint16_t USB_RespSize[DAP_PACKET_COUNT];% S H: V9 n/ o+ n4 S2 Y
% _) Z* l% ^( h" y% }% R" s
/* Private function prototypes -----------------------------------------------*/9 I! A/ v; \. ?# f* p% k
/* Private functions ---------------------------------------------------------*/# f b6 @1 n ?, S
/*******************************************************************************: t0 [4 B9 F( I
* Function Name : EP1_OUT_Callback.0 r* j3 S/ j9 j( h3 V- R. @
* Description : EP1 OUT Callback Routine.
* Input : None.. [; q" B) D8 Q! [; x* ]: u. f$ A
* Output : None.3 t0 ~- }8 n" N6 d. Y9 {
* Return : None.( [6 D. z1 G) N
*******************************************************************************/6 G( j* a, e; c- E9 \0 f/ `+ W$ M
void EP1_OUT_Callback(void)
{
uint16_t n;
9 n# o$ m" E$ Q$ m* {" O
n = GetEPRxCount(ENDP1);; P6 }- X; \8 K* `
PMAToUserBufferCopy(USB_Request[USB_RequestIndexI], ENDP1_RXADDR, n);
if(n !=0){4 d8 C6 P( }6 R, o* l
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {
DAP_TransferAbort = 1U;
} else {$ Y) J! d$ N" N8 R2 O& y0 i% T
USB_RequestIndexI++;) G4 j$ G& j) s
if (USB_RequestIndexI == DAP_PACKET_COUNT) {
USB_RequestIndexI = 0U;1 n* c* M) \5 f" q, R
}
USB_RequestCountI++;
USB_EventFlags = 0x01;- T6 N+ H. c6 T4 a+ S, V# p, L9 Z0 U
}7 j9 Z* s9 Q6 u V1 v
}
// Start reception of next request packet
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {8 F4 Q4 a9 |' a0 V- r
SetEPRxStatus(ENDP1, EP_RX_VALID);; t' {0 W4 s+ ~
} else {' D6 W _7 R: V7 d. b/ I" P
USB_RequestIdle = 1U;
} ! R0 _' E1 u' T, m
}# [+ v% v3 B" E% F7 d6 H
( J9 ^8 Y( {$ b" R+ Z
/*******************************************************************************
* Function Name : EP2_OUT_Callback.6 \6 g2 _4 p! m' b( x: v+ e: O) R
* Description : EP2 OUT Callback Routine.) b. T' K7 I; M( ]$ }& w
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/! H" f. N7 R; c) {& J
static volatile uint32_t TX_n;
static uint8_t *pbuf;
void EP2_IN_Callback(void)
{$ @- B# R# T8 V9 C
uint32_t a;
if(TX_n>0){( c& G- a. K$ [6 r2 Y1 f
pbuf+=64;( b4 Y; D; p6 X' }
if(TX_n>64){! S' ]/ v. [/ ] s
a=64;7 \! X. J2 R; f* {# F3 `: r& C
TX_n-=64;8 H8 y5 M& z7 F- M8 X
}else{
a=TX_n;
TX_n=0;& m) p! w. ?! L! x1 ?
}7 E7 A1 q& W1 }( F6 }3 a3 |% d
6 K, R, Z8 B+ A1 H0 o) o8 T2 B
UserToPMABufferCopy(pbuf,ENDP2_TXADDR,a);
SetEPTxCount(ENDP2,a);
- O, W: D5 S7 S
SetEPTxValid(ENDP2);
}else{
#if (SWO_STREAM != 0)
SWO_TransferComplete();0 I- _7 A( Q8 s V+ z
#endif$ |5 L8 f' A: U* k* G
}9 Q8 A# ^, t4 J- U9 P( z
}
/*******************************************************************************6 J3 i) t* c+ R" F7 g! I
* Function Name : EP1_IN_Callback.
* Description : EP1 IN Callback Routine." m% z- N( e; W( m
* Input : None.! @2 B9 E. C+ R
* Output : None.1 Y* d$ J' ^: A. [
* Return : None.+ ~& W7 F# u5 {
*******************************************************************************/
void EP1_IN_Callback(void)
{
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]); \7 G1 H- E4 f& |
SetEPTxCount(ENDP1,USB_RespSize[USB_ResponseIndexO]);- A6 J( m8 g2 ^' D
SetEPTxValid(ENDP1); % X; f: h0 K" @* ?+ p8 W
USB_ResponseIndexO++;& I- d+ w. K4 n4 [! k. J
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {* [% d6 |; Z; W& Q" G
USB_ResponseIndexO = 0U;
}; }, W* A6 X$ ~$ s
USB_ResponseCountO++;1 W; `! G: |+ X, G/ o: x; J3 X8 D
} else {# t/ u& g0 h0 f5 m
USB_ResponseIdle = 1U;5 f' Q- A1 S9 u3 v R) k
}
}5 g3 `0 A& \6 v% C4 q
// Called during USBD_Initialize to initialize the USB HID class instance.
void DAP_FIFO_Init(void), O" t- B/ c6 Y" A% ?" S+ m
{
// Initialize variables; n' j- d& f# K# {: T k+ U1 E
USB_RequestIndexI = 0U;
USB_RequestIndexO = 0U;6 R. r$ @' j9 O; \! `
USB_RequestCountI = 0U;
USB_RequestCountO = 0U;( a. K( m) u9 p3 Y
USB_ResponseIndexI = 0U;
USB_ResponseIndexO = 0U;
USB_ResponseCountI = 0U;& `. Z- `1 } O( D
USB_ResponseCountO = 0U;6 k5 K6 ?# ^2 Z, L, Y
USB_ResponseIdle = 1U; @% l0 \' n5 t) R
USB_EventFlags = 0U;
}) ~: Z' \" v* f. F2 S" l, ]
uint8_t DAP_Thread (void) {
uint32_t flags;0 I }$ H" B0 F4 n5 T
uint32_t n;
( z5 g+ B' ]# M+ v7 D
//for (;;) {
// osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever);
if((USB_EventFlags & 0x81) == 0)
{' k8 b* u- g) u9 T6 v6 K: w
return 0;- c* u' n! e( W) s& q
}# ]# _$ n; P( v/ n, s& y
USB_EventFlags &= (~0X81);
* Q) R. ~0 Y4 i" Z9 g5 f
! |4 }9 v6 d3 P& F
// Process pending requests& b0 f$ m) G, `3 r: B
while (USB_RequestCountI != USB_RequestCountO) {0 u# z) m* v& E$ j% C$ p
//if (USB_RequestCountI != USB_RequestCountO) {
// Handle Queue Commands* Y6 a$ D% a4 w- {5 e
n = USB_RequestIndexO;
while (USB_Request[n][0] == ID_DAP_QueueCommands) {
//if (USB_Request[n][0] == ID_DAP_QueueCommands) {0 d9 m. S8 q" l$ S
USB_Request[n][0] = ID_DAP_ExecuteCommands;( y3 w+ e, W( x. s+ e: e. I+ d' d, n
n++;
if (n == DAP_PACKET_COUNT) {/ F' U5 A' Q# K, j, O/ z
n = 0U;
}
if (n == USB_RequestIndexI) {, U1 T% c+ y/ b
flags = USB_EventFlags;
if (flags & 0x80U) {0 Y) ^0 P5 m: \2 ~7 G
break;# M r: {1 v: h, N
}& h* S1 d9 R$ a2 \6 c1 e; R$ i
}" z9 b( i& H7 O/ U! G5 o8 _$ r
}
// Execute DAP Command (process request and prepare response)
USB_RespSize[USB_ResponseIndexI] =. r+ n' e. T* T" ^
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);
// Update Request Index and Count
USB_RequestIndexO++;
if (USB_RequestIndexO == DAP_PACKET_COUNT) {
USB_RequestIndexO = 0U;
}
USB_RequestCountO++;
if (USB_RequestIdle) {
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
USB_RequestIdle = 0U;
SetEPRxStatus(ENDP1, EP_RX_VALID);
}) t# G+ h) E. k0 z/ A$ C; J
}$ M" G2 ?- F1 I0 K+ \
3 Z7 p6 `. F0 O0 [" I. O( N
// Update Response Index and Count
USB_ResponseIndexI++;
if (USB_ResponseIndexI == DAP_PACKET_COUNT) {
USB_ResponseIndexI = 0U;
}/ O; v4 R. o2 z) T; J4 N# S, b% K
USB_ResponseCountI++;3 l4 P( q' w! z% _
, N+ Z2 _- c- j8 |! {- q- k& I2 n4 T
if (USB_ResponseIdle) {
if (USB_ResponseCountI != USB_ResponseCountO) {
// Load data from response buffer to be sent back0 t( ]' Y# T' u& z' m
n = USB_ResponseIndexO++;+ A- I- |6 k* X7 T7 s4 u" o( r
if (USB_ResponseIndexO == DAP_PACKET_COUNT) {5 i, \* [' m$ b& X) q1 G, U* ~: `
USB_ResponseIndexO = 0U;
}& Q* h- j( E* l6 y5 |6 i1 j0 g
USB_ResponseCountO++;
USB_ResponseIdle = 0U;
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(1U), USB_Response[n], USB_RespSize[n]);! X) ?* l1 M% M5 e. T
UserToPMABufferCopy(USB_Response[n],ENDP1_TXADDR,USB_RespSize[n]);
SetEPTxCount(ENDP1,USB_RespSize[n]);. r1 J- o/ I9 a( y( L1 c t9 S. j
SetEPTxValid(ENDP1);# S1 S( l5 y6 ^" u! V
}/ ^$ d! m t$ b5 u% Z- O
}
}
return 0;% ^7 X# ~7 w/ J6 k9 M7 w
}
// SWO Data Queue Transfer
// buf: pointer to buffer with data
// num: number of bytes to transfer
void SWO_QueueTransfer (uint8_t *buf, uint32_t num) {
//USBD_EndpointWrite(0U, USB_ENDPOINT_IN(2U), buf, num);
uint32_t a;
! L3 |& A" n& N- ]. n" {2 s
if(num>64)
{
a=64;+ S' {6 M4 z+ x3 l" R) W- _
TX_n=num-64;
pbuf=buf;
}else {
a=num;: W0 M6 w, e0 Z9 i
TX_n=0;
}) D+ D# [+ q: i
UserToPMABufferCopy(buf,ENDP2_TXADDR,a);! g6 s! P1 ^* ` M
SetEPTxCount(ENDP2,a);
SetEPTxValid(ENDP2);
}7 y4 e# }1 Q/ v# o7 x2 y8 ~ z
// SWO Data Abort Transfer) J& i5 v9 m' q9 a0 _
void SWO_AbortTransfer (void) {- V* ?4 m$ U$ M w
//USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U));
//SetEPTxStatus(ENDP2, EP_TX_NAK);" D, T Q+ l. |. O, _& ?" l7 _
SetEPTxStatus(ENDP2, EP_TX_DIS);$ f% R7 @5 _9 ^& K
SetEPTxCount(ENDP2,0);2 P, `4 H j- C6 F' Q
//TX_n=0;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/: D. `4 I& s: B J: @5 h$ [
移植大概是这样的,利用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) {, W1 J9 C* z: X4 D' A, \& e
return (DWT->CYCCNT);
}' k; ~& M2 ?& @6 P* F
: ^. d) X" D G
void DWT_Init(void)# p0 q5 D! i4 v4 O, c
{( H! v) w! r, ?1 U
/* 使能DWT外设 */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
$ ]. X, O) v* K S/ P5 z
/* DWT CYCCNT寄存器计数清0 */& g9 @. E$ J* J3 `
DWT->CYCCNT = (uint32_t)0u;
" @. a4 R5 S" u* o* X, z
/* 使能Cortex-M DWT CYCCNT寄存器 */
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;* o4 S7 E( I% M. s
}( `. c6 v3 E. O. n z2 O/ ~
9 {( o! W; ]! S+ L" Q! [ M! m
4 W; M( n7 m0 N) o2 }! q
然后加入了SWO,SWO有个SWO_STREAM传输方式,在不使用这种方式时,开启了SWO调试后单步调试时能正常打印信息了,但是当点全速运行后感觉像卡住了一样,要等非常长的时间才会在断点处停下,如果程序没有下过断点,点全速后就会出现Keil卡死,也不知道什么原因,看程序代码像是在调用SWO_Data时被阻塞住了一样,而且在等待的时间里操作Keil像是也没法动一样了,非常慢一卡一卡的,进入了断点停下后就没这现象了,此时单步也是正常的,也就是说全速下,SWO有问题了,但在没开启SWO时调试和响应速度哪叫一个爽的啊,SWO部分的串口是直接搬了DAP例子工程里的串口驱动代码进去实现的,不知道是不是这个原因导致SWO被阻塞,或者自己另外写串口驱动提供给SWO,另外串口波特率最高只能2MHZ,超过这频率,SWO打印信息打印不出来的,串口波特率就是在Trace设置页面里看到的SWO 频率
% [; x5 D- a' L* ^, } Y0 O3 _
然后改为使用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的地方都改为如:2 g/ j3 N; `/ B! R& _
//osThreadFlagsSet(SWO_ThreadId, 1U);
SWO_EventFlags = 1U;
// SWO Thread
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {- j$ r0 r1 Q" J% o3 Z( @! _5 v9 q
//uint32_t timeout;
uint32_t flags;
uint32_t count;
uint32_t index;
uint32_t i, n;" l7 j* A }2 N1 \% a
//(void) argument;1 c5 n+ C X4 U$ [4 M7 Z% h
//timeout = osWaitForever;
//for (;;) {! R) J4 B, V: w$ U0 B5 K- R
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if((SWO_EventFlags & 0x01)==0)return 0;
8 f& ~. c2 s- q) {% R8 P1 l
flags = SWO_EventFlags;
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {% k Z; p- K# p: t9 S6 u1 A
//timeout = SWO_STREAM_TIMEOUT; 这里是对于进入了SWO_CAPTURE_ACTIVE状态时就把线程超时设置为50毫秒,大概意思应该是osThreadFlagsWait到达这个超时时间后,不管标志是否切换为1U,都放行SWO_Thread调用一次,timeout = osWaitForever时相当于无限长的超时等待1U标志,对RTX不熟悉,不知道是不是这样子* [3 P! f( c. X( h7 L
;, ?/ F7 I& k! Q; \; z% P6 C
} else {+ X3 o8 l- v: F' Q+ S
//timeout = osWaitForever;- E5 E5 i1 B& V' B, C
flags = osFlagsErrorTimeout;
}
if (TransferBusy == 0U) { d" `' x' t2 h( }# \2 V) s
count = GetTraceCount();5 q: v( ^6 j7 P3 z$ ]% Q
if (count != 0U) {# r$ I% C3 U1 X; t# H) b: g* Z
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);$ p R' e* V+ d
n = SWO_BUFFER_SIZE - index;% X( f& x4 C# _- ~2 P
if (count > n) {
count = n;. {: j& t! `7 U! p% \" K
3 t+ @0 `: [$ p! x% n8 J; ` v7 ^0 l; [3 z
}5 }6 _1 T- t- g% j n, f( N
if(count>USB_BLOCK_SIZE)
count=USB_BLOCK_SIZE;4 P" T+ [: Z8 {
if (flags != osFlagsErrorTimeout) {0 { }0 @+ |5 l# P8 T! J) l
i = index & (USB_BLOCK_SIZE - 1U);. v# w0 H& s- a1 d
if (i == 0U) {) V: j3 I! J8 s1 F# Y) U9 S
count &= ~(USB_BLOCK_SIZE - 1U);
} else {$ ?; O! Y: k0 E/ ^( B- B& @
n = USB_BLOCK_SIZE - i;8 `* ]+ c6 f0 J* M# A
if (count >= n) {
count = n;
} else {3 a# k" R0 C9 w7 R# ^
count = 0U;
}
}7 |! z+ g! U: b+ T* u
}
if (count != 0U) {$ Z& ~ n& G! W* `- b
TransferSize = count;' P/ u/ ]: C* R) M; ~( [; n+ M$ ^
TransferBusy = 1U;: l8 G$ H/ z2 g# M( ~( V
SWO_QueueTransfer(&TraceBuf[index], count);3 h8 E2 v8 m) N6 F5 A- e& p3 y
}
}: k! M- E, ~ H0 q$ }* P4 t, T
}3 T* H+ q5 E7 x$ R# g
//}
return 0;
}
利用DWT增加超时等待,先声明变量timeout也在外面声明#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).$ B( n/ y. b7 V! t4 z
static volatile uint32_t SWO_EventFlags=0;
static volatile uint32_t timeout=osWaitForever;6 {/ r! \- H# P' e W
static volatile uint32_t timeWait;
函数改为这样
/*__NO_RETURN void*/uint8_t SWO_Thread (void ) {
//uint32_t timeout;; R, }% J0 r" C3 d* C$ |
uint32_t flags;
uint32_t count;
uint32_t index;
uint32_t i, n;
//(void) argument;* ~8 G7 a) C; n8 x
% K: F% P T B+ V4 t: a
//timeout = osWaitForever;
: p3 e4 |0 Q! _* F4 P M0 U1 X+ X
//for (;;) {: Q- O0 A4 b9 e; R" E9 ^
//flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if((SWO_EventFlags & 0x01)==0)
{
if((timeWait-=DWT->CYCCNT)/72000 < timeout) //少于timeout时间值直接返回,DWT->CYCCNT由于这计数值是按72M时钟计数的,所以72000就为1毫秒,0.001*72000000=72000,由于是与DAP处理是顺序执行,这个时间无法准确在50毫秒,但总来说与跑RTX系统 的超时等待差不多原理了 x$ ^9 k9 o% M
return 0;
B) U! H# K J y8 a
}/ V6 d& t7 ^8 K9 n7 ]& s8 c
flags = SWO_EventFlags;& q" ^/ l" B. C7 X) ]
SWO_EventFlags = 0U;
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {' Q. a3 p7 G4 c- B8 ]
timeout = SWO_STREAM_TIMEOUT;
timeWait=DWT->CYCCNT;
} else {
timeout = osWaitForever;* Y- A2 B" n _- }
flags = osFlagsErrorTimeout;5 t& A% n! m+ m
}. E' q1 j( }4 Z4 ]: s$ C4 k
if (TransferBusy == 0U) {
count = GetTraceCount();
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);! p$ t( w7 s6 z" c ?
n = SWO_BUFFER_SIZE - index;
if (count > n) {$ w& Z9 ^5 D! c) \
count = n; u v1 L$ c4 A1 v6 W4 f9 t
}
if(count>USB_BLOCK_SIZE)* U \2 i; c. q( H" e; `4 |
count=USB_BLOCK_SIZE;
if (flags != osFlagsErrorTimeout) {$ Z* r* w: R2 Q
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {) z9 D8 y) F# D
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;+ j7 N/ O; A, j1 l+ t+ M* }
if (count >= n) {
count = n;: B9 r/ z; w' m& L4 _1 A
} else {( J" q& o; k ^+ s# m, O
count = 0U;- K. i& e. B& b. |! j) V
}
}
}: ]0 z, i7 t. Y+ y5 c" Q) k4 @, K
if (count != 0U) {( a* w" t% @% x, H* u
TransferSize = count;2 K8 ]" n) L. K. R. q* o
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);" Z9 u/ K3 ~. R+ S/ f' p, D! B; M1 I
}6 x1 |5 s6 c- C) x# l. t7 w8 |, C
}3 D6 Q$ I8 r; K; O2 g% X
}
//}
return 0;
}这样修改后也不知道能否解决Trace:dataOVERFLOW,也是刚想到的,试了才能知道了,另外还要说明一下,USB_BLOCK_SIZE是声明为512字节的,即SWO_QueueTransfer(&TraceBuf[index], count);时,如果count超过64字节后就得要分包发送了,这个USB库发送部分得自己分包发送,上面的SWO_QueueTransfer发送代码和端点回调处EP2_IN_Callback已经加入发分发送了
CDC部分暂时还没加入,SWD现在是非常稳定的,而且速度感觉也是不差,就是SWO的问题不知道如何弄,另外看到其它人弄DAP,把SWD读写部分改为SPI,看了一些SWD读写协议,它好像有一个8位一组和32位一组的部分,如果换为SPI是不是就可以更快的速度读写了,另外DAP与USB之间的FIFO部分它有一个队列等待,看意思就是当有标志着队列的包时,就等待接收更多的包缓存后再执行处理,对于批量端点,连续的传输大量数据确实是批量端点的长处,因为批量数据时,端点接收完一包后不会NAK,端点会接着接收下一包,少了一些中间商的处理,也尝试过这个队列等待修改为不等待,即接收一个包,执行一次DAP处理,它同样是能正常运行的,对于批量传输来来说,感觉应该队列等待会提高USB传输的速度,比如下载程序时,Keil 一次性下发多个命令包,比如达到1K或者2K字节或者更多,DAP先全部利用批量端点的优势一次性接收下来缓存,然后DAP才执行一个个命令包的响应处理,对于读写部分构成字节为一组的就使用SPI读写数据,零散的位部分像ACK,SWD复位等待部分用IO模拟来处理,SWO部分感觉如果能修改为SPI接收估计时钟频率可以更高,这样响应速度更快,另外STM32_USB-FS-Device_Lib_V4.1.0固件库的USB端点没有FIFO,不像OTG USB FS 库哪样端点都带有FIFO,但是提供双缓存端点,准备把端点修改为双缓存的,这样当连续多包传输时,端点就不会NAK,少了这个等待时间,能增加端点的传输速率1 R8 i' \( q3 k/ O8 V
int main(void): x6 ^" X% u9 ^
{2 Z% I% D }; D$ T( y( r3 L, Y
DWT_Init();
DAP_Setup();
USB_Interrupts_Config();
Set_USBClock();4 {1 _! [6 ^- }/ h! U3 F& [3 l4 {& o
USB_Init();
//TIM3_Init(35999,0);
//TIM_Cmd(TIM3,ENABLE);, }& b( H3 j" e; E: [9 g+ a8 v
- k& C* o3 s l9 ]8 I" a
$ [8 h2 E( v. q, U6 l; S7 W
while (1)
{
DAP_Thread();# q! w, a/ D( T1 R/ @5 z C
#if (SWO_STREAM != 0)8 b- Z/ u7 P( l0 u
SWO_Thread();$ C# `- n5 I8 p/ \1 H5 T) x9 e
#endif
}
}
对于DAP_config.h的IO配置我是这样弄的
///@}- i6 b3 {% O f4 p
// Debug Port I/O Pins
// SWCLK/TCK Pin GPIOA[6]# B6 X* ]7 n2 f
#define SWCLK_TCK_OUT *( uint32_t*)0x42210198" t& D. q$ Y% `3 B+ Q
#define SWCLK_TCK_IN *( uint32_t*)0x42210118
// SWDIO/TMS Pin GPIOA[7]
#define SWDIO_TMS_OUT *( uint32_t*)0x4221019C
#define SWDIO_TMS_IN *( uint32_t*)0x4221011C
3 D9 _0 F3 Z: b; g6 a7 w
// SWDIO Output Enable Pin GPIOA[7]
#define SWDIO_Output() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 1; \
*(uint32_t*)0x42210074 = 1; \) A0 y; J7 p) F" n; o) P5 N
*(uint32_t*)0x42210078 = 0; \; D# x, u9 b/ d& m
*(uint32_t*)0x4221007C = 0;}5 H! q9 Q$ a D/ s' O1 ]4 [
7 V J! M$ O2 g$ [/ j
#define SWDIO_Input() {*(uint32_t*)0x4221021C = 1; \
*(uint32_t*)0x42210070 = 0; \
*(uint32_t*)0x42210074 = 0; \
*(uint32_t*)0x42210078 = 0; \1 H& U' d& ~- k0 P( i/ N1 ^
*(uint32_t*)0x4221007C = 1; }8 ?2 l; W( m- g4 b/ s
// TDI Pin GPIOA[8]
#define TDI_OUT *(volatile uint32_t*)0x422101A0 e1 f/ l B, D4 Y0 [
#define TDI_IN *(volatile uint32_t*)0x42210120
// TDO Pin GPIOA[10]' v% J4 |4 u- ^0 d
#define TDO_OUT *(volatile uint32_t*)0x422101A8
#define TDO_IN *(volatile uint32_t*)0x42210128
// nTRST Pin GPIOB[3]
#define nTRST_OUT *(volatile uint32_t*)0x4221818C
#define nTRST_IN *(volatile uint32_t*)0x4221010C' @6 `( M t0 Z7 K
+ Z% d8 A3 N" ]) [. L' T* C5 b" X
// nRESET Pin GPIOB[4]8 H0 t+ k9 K; D, ^
#define nRESET_OUT *(volatile uint32_t*)0x42218190& [7 R7 ?/ w% T6 v" E6 L
#define nRESET_IN *(volatile uint32_t*)0x42218110
// nRESET Output Enable Pin GPIOB[4]+ p8 s$ Y9 v4 a f8 }. i+ g. `/ V
#define nRESET_Output() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 1; \
*(uint32_t*)0x42218044 = 1; \. d$ n0 E. p7 P0 ~
*(uint32_t*)0x42218048 = 0; \ |$ o7 s0 ^) b3 t
*(uint32_t*)0x4221804C = 0; } ; i6 K! j! I/ @ P8 {6 t# t$ a Q
7 e% Z$ G2 E$ R8 L/ i
#define nRESET_Intput() {*(uint32_t*)0x42218210 = 1; \
*(uint32_t*)0x42218040 = 0; \% D7 b, ^& k. K0 w1 _: a
*(uint32_t*)0x42218044 = 0; \
*(uint32_t*)0x42218048 = 0;\
*(uint32_t*)0x4221804C = 1; }
8 d4 z3 p4 t/ r( ] U" a- t
$ T0 @( t+ u W
// Debug Unit LEDs* @0 z& \+ T- T: ~% q- h
// Connected LED GPIOC[13]3 ?) x7 e) U5 T; s" p! G
#define LED_OUT *(volatile uint32_t*)0x422201B4
#define LED_IN *(volatile uint32_t*)0x42220134
#define LED_Intput() {*(uint32_t*)0x42220234 = 1; \! G; v8 b( L0 A
*(uint32_t*)0x422200D0 = 0; \
*(uint32_t*)0x422200D4 = 0; \
*(uint32_t*)0x422200D8 = 0; \% v( l/ c4 ^! B
*(uint32_t*)0x422200DC = 1; }3 T1 U8 {9 p5 v: O& P. _7 A
// Target Running LED Not available c" v1 e3 z1 d
) K& T( N5 ~4 o+ R ~- N
// SWCLK/TCK I/O pin -------------------------------------) _, m( N F8 Q3 x+ w
/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/" u) I' n/ G6 \9 ^1 G' A/ i* ~2 h5 w6 }
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {0 Y; ]4 k3 x R4 x' d
return (SWCLK_TCK_IN);4 v$ a8 h7 l8 y
}
& v" `2 ~! Z/ v4 F
/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {; Q1 r, T: [# Q! a& ^4 Z5 P
SWCLK_TCK_OUT = 1;
}
" A7 k9 u: L0 h1 j; n( W" x$ `
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*// e: |; O3 p! K# }" s+ p: H
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) { j: v& d$ t) z
SWCLK_TCK_OUT = 0;
}
! @7 \9 j5 \5 _7 Y
// SWDIO/TMS Pin I/O --------------------------------------
* w7 h4 l3 D; N- D3 ~9 b$ [
/** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (SWDIO_TMS_IN);
}$ G; `, p9 E. Y6 a
/** SWDIO/TMS I/O pin: Set Output to High.' ?7 H- f1 R e" f: {% q
Set the SWDIO/TMS DAP hardware I/O pin to high level.+ h! `2 _2 N& T# O4 N. f
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {
SWDIO_TMS_OUT = 1;7 I, k s- U1 f: h' g
}$ Z- c3 b7 P! V% R2 k
9 w B2 I- Y% m4 q2 h. m) [
/** SWDIO/TMS I/O pin: Set Output to Low.) R% m' L, Z7 B! O
Set the SWDIO/TMS DAP hardware I/O pin to low level.
*/ y; p! \- ^& Y, E# ^1 B. t( G
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {. d2 t5 J) D4 l0 ]
SWDIO_TMS_OUT = 0;
}. f N1 w6 ]& G3 n: Z6 C
/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin.6 b/ O6 a7 Y$ A! a t; L
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return (SWDIO_TMS_IN);% I# P5 t5 z( c( W/ ?( K* t
}# N4 {& ?2 b8 Q- r+ v) W9 K
$ g6 H; r3 f3 S2 l7 c1 S7 \
/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin.. K: ^$ \$ U! M& P
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
SWDIO_TMS_OUT = bit;
}/ _4 W5 D' Z; A4 v
; Q. l; F# [. W$ M, P4 x3 ]
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {
SWDIO_Output();9 {2 p1 h9 e) G; d, s
}
/** 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- w; m! r7 m6 O$ E
called prior \ref PIN_SWDIO_IN function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
SWDIO_Input();% U1 f: e) b: W) _# t0 d; Z
}
/ @( z. f! ]/ l$ z7 ]/ C
楼上有的说弄无线,其实无线也就是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驱动的大佬可以尝试一下
有人将这个工程移植到stm32f4上吗,我在网上找了一个f4的dap工程,但是编译下载后无法使用。