Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
CherryUSB
RT-Thread一般讨论
ART-Pi2移植CMSIS-DAP(基于CherryUSB协议栈)
发布于 2025-02-21 13:05:56 浏览:150
订阅该版
[tocm] ### 内容分三节,第一节使用cubemx生成点灯程序,第二节添加cherryusb源代码运行winusb demo,第三节添加cmsis-dap源代码并修改运行。 ### 交流群:ART-Pi2 1016035998,CherryUSB 642693751,CMSIS-DAP 975779851 ### 仓库地址:[https://gitee.com/lizimu2020/cmsis-dap_for_-art-pi2](https://gitee.com/lizimu2020/cmsis-dap_for_-art-pi2 "https://gitee.com/lizimu2020/cmsis-dap_for_-art-pi2") ## 一、点灯 拿到新板子点灯和串口输出hello world,然后吃灰一气呵成。 ART-Pi2的led对应的引脚是po5,串口对应的uart4(引脚为PD0 PD1)已经和板载f103(stlink或jlinkob)连接。 为了减少内部flash擦写次数,所以我是用sram运行demo,所以每次都需要板载stlink配合keil脚本启动。 ### 1、RCC、Tick配置(artpi2使用的stm32h7r7h晶振使用的24Mhz,SYSCLK最高600Mhz)    ### 2、uart配置(单纯点灯这里可以后续使用时在配置)  ### 3、usb配置(usb phy使用hse的24mhz时钟)(cubemx生成的代码是没有usb pin初始化的,不用怀疑有问题)(单纯点灯这里可以后续使用时在配置)   ### 4、SWD配置(pa13 pa14已经通过底板和板载调试器的swtck swdio连接)  ### 5、led配置(h7r7系列的cubemx工程和以前的h7有点差异,可以一次生成boot app等类型项目,所以在配置gpio时就需要勾选选项,确保当前配置在boot app那个项目中有效,或者都有效)  ### 6、生成keil项目   ### 7、keil配置    ```c // debug_sram.ini FUNC void Setup (void) { SP = _RDWORD(0x24050000); // 设置栈指针SP,把0x24050000地址中的内容赋值到SP。 PC = _RDWORD(0x24050004); // 设置程序指针PC,把0x24050004地址中的内容赋值到PC。 XPSR = 0x01000000; // 设置状态寄存器指针xPSR _WDWORD(0xE000ED08, 0x24050000); // Setup Vector Table Offset Register } LOAD %L INCREMENTAL // 下载axf文件到RAM Setup(); // 调用上面定义的setup函数设置运行环境 //g, main //跳转到main函数 ``` ### 8、启动程序(如果前面配置了usb,那么点灯时先注释掉main.c中的MX_USB_OTG_HS_PCD_Init();) ```c // main.c /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_UART4_Init(); // MX_USB_OTG_HS_PCD_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); HAL_Delay(500); HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); HAL_Delay(500); } /* USER CODE END 3 */ ```  ## 二、添加CherryUSB ### 1、下载cherryusb [https://github.com/cherry-embedded/CherryUSB/archive/refs/tags/v1.4.2.zip](https://github.com/cherry-embedded/CherryUSB/archive/refs/tags/v1.4.2.zip "https://github.com/cherry-embedded/CherryUSB/archive/refs/tags/v1.4.2.zip") ### 2、添加源代码和头文件搜索路径  ### 3、配置demo 从cherryusb源代码目录树的demo文件夹复制一份 "winusb2.0_cdc_template.c" 从cherryusb源代码根目录复制一份 "cherryusb_config_template.h" 并改名为 "usb_config.h" uart.c添加如下代码: ```c /* USER CODE BEGIN 1 */ #include
#include
#include
__asm(".global __use_no_semihosting"); //struct __FILE { int handle; /* Add whatever you need here */ }; FILE __stdout; FILE __stdin; int fputc(int c, FILE *f) { HAL_UART_Transmit(&huart4, (uint8_t *)&c, 1, 1000); return (c); } int fgetc(FILE *f) { return EOF; } int ferror(FILE *f) { /* Your implementation of ferror */ return EOF; } void _ttywrch(int c) { HAL_UART_Transmit(&huart4, (uint8_t *)&c, 1, 1000); } void _sys_exit(int return_code) { label: goto label; /* endless loop */ } /* USER CODE END 1 */ ``` stm32h7rsxx_it.c添加usb中断: ```c /* USER CODE BEGIN 1 */ void OTG_HS_IRQHandler(void) { /* USER CODE BEGIN OTG_HS_IRQn 0 */ /* USER CODE END OTG_HS_IRQn 0 */ // HAL_PCD_IRQHandler(&hpcd_USB_OTG_HS); /* USER CODE BEGIN OTG_HS_IRQn 1 */ extern void USBD_IRQHandler(uint8_t busid); USBD_IRQHandler(0); /* USER CODE END OTG_HS_IRQn 1 */ } /* USER CODE END 1 */ ``` usb_otg.c添加cherryusb底层初始化代码: ```c /* USER CODE BEGIN 1 */ void usb_dc_low_level_init(uint8_t busid) { // MX_USB_OTG_HS_PCD_Init(); RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USBPHYC; PeriphClkInit.UsbPhycClockSelection = RCC_USBPHYCCLKSOURCE_HSE; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } HAL_PWREx_EnableUSBVoltageDetector(); /* Enable the USB HS regulator. */ HAL_PWREx_EnableUSBHSregulator(); /* USB_OTG_HS clock enable */ __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); __HAL_RCC_USBPHYC_CLK_ENABLE(); /* USB_OTG_HS interrupt Init */ HAL_NVIC_SetPriority(OTG_HS_IRQn, 0, 0); HAL_NVIC_EnableIRQ(OTG_HS_IRQn); } void usb_dc_low_level_deinit(uint8_t busid) { HAL_PCD_DeInit(&hpcd_USB_OTG_HS); } /* USER CODE END 1 */ ``` usb_config.h修改宏定义: ```c /* ---------------- DWC2 Configuration ---------------- */ /* (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for * status information) + (2 * number of OUT endpoints) + 1 for Global NAK */ #define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4) /* IN Endpoints Max packet Size / 4 */ // #define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4) #define CONFIG_USB_DWC2_TX1_FIFO_SIZE (512 / 4) #define CONFIG_USB_DWC2_TX2_FIFO_SIZE (512 / 4) #define CONFIG_USB_DWC2_TX3_FIFO_SIZE (512 / 4) #define CONFIG_USB_DWC2_TX4_FIFO_SIZE (512 / 4) // #define CONFIG_USB_DWC2_TX5_FIFO_SIZE (0 / 4) // #define CONFIG_USB_DWC2_TX6_FIFO_SIZE (0 / 4) // #define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4) // #define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4) // #define CONFIG_USB_DWC2_DMA_ENABLE #define CONFIG_USB_HS ``` main.c修改: ```c /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_UART4_Init(); // MX_USB_OTG_HS_PCD_Init(); /* USER CODE BEGIN 2 */ printf("CMSIS-DAP for ART-Pi2(CherryUSB).\r\n"); extern void winusbv2_init(uint8_t busid, uintptr_t reg_base); winusbv2_init(0, USB_OTG_HS_PERIPH_BASE); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ //HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); //HAL_Delay(500); //HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); //HAL_Delay(500); } /* USER CODE END 3 */ ``` ### 4、加载运行(参考第一节点灯)(在windows的设备管理器能看到winusb 和 cdc两个usb设备)  demo运行成功,后面会在这个demo上添加cmsis-dap 我前面写过一篇stm32h7r7h移植cherryusb的文章,其中提到修改usb_glue_st.c文件,cherryusb 1.4.2已经适配好了artpi2所以已经不需要在修改,如果你的stm32h7r7h usb硬件不一样可能还是需要自己修改。 ## 三、添加CMSIS-DAP ### 1、下载CMSIS-DAP源代码 [https://github.com/ARM-software/CMSIS-DAP/archive/refs/tags/v2.1.2.zip](https://github.com/ARM-software/CMSIS-DAP/archive/refs/tags/v2.1.2.zip "https://github.com/ARM-software/CMSIS-DAP/archive/refs/tags/v2.1.2.zip") ### 2、添加源代码和搜索路径  ### 3、添加和修改代码 为了提高IO操作速度使用了LL库 jtag对应的引脚: ```c #define RESET_Pin LL_GPIO_PIN_7 #define RESET_GPIO_Port GPIOB #define SWTCK_Pin LL_GPIO_PIN_6 #define SWTCK_GPIO_Port GPIOC #define SWDIO_Pin LL_GPIO_PIN_7 #define SWDIO_GPIO_Port GPIOC #define TDI_Pin LL_GPIO_PIN_0 #define TDI_GPIO_Port GPIOE #define TDO_Pin LL_GPIO_PIN_5 #define TDO_GPIO_Port GPIOE #define TRST_Pin LL_GPIO_PIN_14 #define TRST_GPIO_Port GPIOD ```  DAP_config.h修改: ```c /* * Copyright (c) 2013-2021 ARM Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * ---------------------------------------------------------------------- * * $Date: 16. June 2021 * $Revision: V2.1.0 * * Project: CMSIS-DAP Configuration * Title: DAP_config.h CMSIS-DAP Configuration File (Template) * *---------------------------------------------------------------------------*/ #ifndef __DAP_CONFIG_H__ #define __DAP_CONFIG_H__ //************************************************************************************************** /** \defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information \ingroup DAP_ConfigIO_gr @{ Provides definitions about the hardware and configuration of the Debug Unit. This information includes: - Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit. - Debug Unit Identification strings (Vendor, Product, Serial Number). - Debug Unit communication packet size. - Debug Access Port supported modes and settings (JTAG/SWD and SWO). - Optional information about a connected Target Device (for Evaluation Boards). */ #ifdef _RTE_ #include "RTE_Components.h" #include "main.h" #include
#else #include "device.h" // Debug Unit Cortex-M Processor Header File #endif /// Processor Clock of the Cortex-M MCU used in the Debug Unit. /// This value is used to calculate the SWD/JTAG clock speed. #define CPU_CLOCK 600000000U ///< Specifies the CPU Clock in Hz. /// Number of processor cycles for I/O Port write operations. /// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O /// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors /// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses /// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be /// required. #define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0. /// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. /// This information is returned by the command \ref DAP_Info as part of
Capabilities
. #define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available. /// Indicate that JTAG communication mode is available at the Debug Port. /// This information is returned by the command \ref DAP_Info as part of
Capabilities
. #define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. /// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. /// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. #define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain. /// Default communication mode on the Debug Access Port. /// Used for the command \ref DAP_Connect when Port Default mode is selected. #define DAP_DEFAULT_PORT 1U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. /// Default communication speed on the Debug Access Port for SWD and JTAG mode. /// Used to initialize the default SWD/JTAG clock frequency. /// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. #define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz. /// Maximum Package Size for Command and Response data. /// This configuration settings is used to optimize the communication performance with the /// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, /// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. #define DAP_PACKET_SIZE 512U ///< Specifies Packet Size in bytes. /// Maximum Package Buffers for Command and Response data. /// This configuration settings is used to optimize the communication performance with the /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the /// setting can be reduced (valid range is 1 .. 255). #define DAP_PACKET_COUNT 8U ///< Specifies number of packets buffered. /// Indicate that UART Serial Wire Output (SWO) trace is available. /// This information is returned by the command \ref DAP_Info as part of
Capabilities
. #define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available. /// USART Driver instance number for the UART SWO. #define SWO_UART_DRIVER 0 ///< USART Driver instance number (Driver_USART#). /// Maximum SWO UART Baudrate. #define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz. /// Indicate that Manchester Serial Wire Output (SWO) trace is available. /// This information is returned by the command \ref DAP_Info as part of
Capabilities
. #define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available. /// SWO Trace Buffer Size. #define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n). /// SWO Streaming Trace. #define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available. /// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. #define TIMESTAMP_CLOCK 100000000U ///< Timestamp clock in Hz (0 = timestamps not supported). /// Indicate that UART Communication Port is available. /// This information is returned by the command \ref DAP_Info as part of
Capabilities
. #define DAP_UART 0 ///< DAP UART: 1 = available, 0 = not available. /// USART Driver instance number for the UART Communication Port. #define DAP_UART_DRIVER 1 ///< USART Driver instance number (Driver_USART#). /// UART Receive Buffer Size. #define DAP_UART_RX_BUFFER_SIZE 1024U ///< Uart Receive Buffer Size in bytes (must be 2^n). /// UART Transmit Buffer Size. #define DAP_UART_TX_BUFFER_SIZE 1024U ///< Uart Transmit Buffer Size in bytes (must be 2^n). /// Indicate that UART Communication via USB COM Port is available. /// This information is returned by the command \ref DAP_Info as part of
Capabilities
. #define DAP_UART_USB_COM_PORT 0 ///< USB COM Port: 1 = available, 0 = not available. /// Debug Unit is connected to fixed Target Device. /// The Debug Unit may be part of an evaluation board and always connected to a fixed /// known device. In this case a Device Vendor, Device Name, Board Vendor and Board Name strings /// are stored and may be used by the debugger or IDE to configure device parameters. #define TARGET_FIXED 0 ///< Target: 1 = known, 0 = unknown; #define TARGET_DEVICE_VENDOR "Arm" ///< String indicating the Silicon Vendor #define TARGET_DEVICE_NAME "Cortex-M" ///< String indicating the Target Device #define TARGET_BOARD_VENDOR "Arm" ///< String indicating the Board Vendor #define TARGET_BOARD_NAME "Arm board" ///< String indicating the Board Name #if TARGET_FIXED != 0 #include
static const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR; static const char TargetDeviceName [] = TARGET_DEVICE_NAME; static const char TargetBoardVendor [] = TARGET_BOARD_VENDOR; static const char TargetBoardName [] = TARGET_BOARD_NAME; #endif /** Get Vendor Name string. \param str Pointer to buffer to store the string (max 60 characters). \return String length (including terminating NULL character) or 0 (no string). */ __STATIC_INLINE uint8_t DAP_GetVendorString (char *str) { (void)str; return (0U); } /** Get Product Name string. \param str Pointer to buffer to store the string (max 60 characters). \return String length (including terminating NULL character) or 0 (no string). */ __STATIC_INLINE uint8_t DAP_GetProductString (char *str) { (void)str; return (0U); } /** Get Serial Number string. \param str Pointer to buffer to store the string (max 60 characters). \return String length (including terminating NULL character) or 0 (no string). */ __STATIC_INLINE uint8_t DAP_GetSerNumString (char *str) { (void)str; return (0U); } /** Get Target Device Vendor string. \param str Pointer to buffer to store the string (max 60 characters). \return String length (including terminating NULL character) or 0 (no string). */ __STATIC_INLINE uint8_t DAP_GetTargetDeviceVendorString (char *str) { #if TARGET_FIXED != 0 uint8_t len; strcpy(str, TargetDeviceVendor); len = (uint8_t)(strlen(TargetDeviceVendor) + 1U); return (len); #else (void)str; return (0U); #endif } /** Get Target Device Name string. \param str Pointer to buffer to store the string (max 60 characters). \return String length (including terminating NULL character) or 0 (no string). */ __STATIC_INLINE uint8_t DAP_GetTargetDeviceNameString (char *str) { #if TARGET_FIXED != 0 uint8_t len; strcpy(str, TargetDeviceName); len = (uint8_t)(strlen(TargetDeviceName) + 1U); return (len); #else (void)str; return (0U); #endif } /** Get Target Board Vendor string. \param str Pointer to buffer to store the string (max 60 characters). \return String length (including terminating NULL character) or 0 (no string). */ __STATIC_INLINE uint8_t DAP_GetTargetBoardVendorString (char *str) { #if TARGET_FIXED != 0 uint8_t len; strcpy(str, TargetBoardVendor); len = (uint8_t)(strlen(TargetBoardVendor) + 1U); return (len); #else (void)str; return (0U); #endif } /** Get Target Board Name string. \param str Pointer to buffer to store the string (max 60 characters). \return String length (including terminating NULL character) or 0 (no string). */ __STATIC_INLINE uint8_t DAP_GetTargetBoardNameString (char *str) { #if TARGET_FIXED != 0 uint8_t len; strcpy(str, TargetBoardName); len = (uint8_t)(strlen(TargetBoardName) + 1U); return (len); #else (void)str; return (0U); #endif } /** Get Product Firmware Version string. \param str Pointer to buffer to store the string (max 60 characters). \return String length (including terminating NULL character) or 0 (no string). */ __STATIC_INLINE uint8_t DAP_GetProductFirmwareVersionString (char *str) { (void)str; return (0U); } ///@} //************************************************************************************************** /** \defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access \ingroup DAP_ConfigIO_gr @{ Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug interface of a device. The following I/O Pins are provided: JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode ---------------------------- | -------------------- | --------------------------------------------- TCK: Test Clock | SWCLK: Clock | Output Push/Pull TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) TDI: Test Data Input | | Output Push/Pull TDO: Test Data Output | | Input nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor DAP Hardware I/O Pin Access Functions ------------------------------------- The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to these I/O Pins. For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. This functions are provided to achieve faster I/O that is possible with some advanced GPIO peripherals that can independently write/read a single I/O pin without affecting any other pins of the same I/O port. The following SWDIO I/O Pin functions are provided: - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. */ // Configure DAP I/O pins ------------------------------ /** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. Configures the DAP Hardware I/O pins for JTAG mode: - TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level. - TDO to input mode. */ __STATIC_INLINE void PORT_JTAG_SETUP (void) { LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOD); LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB); LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOC); LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOE); LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; LL_GPIO_SetOutputPin(RESET_GPIO_Port, RESET_Pin); LL_GPIO_SetOutputPin(TRST_GPIO_Port, TRST_Pin); LL_GPIO_SetOutputPin(SWTCK_GPIO_Port, SWTCK_Pin); LL_GPIO_SetOutputPin(SWDIO_GPIO_Port, SWDIO_Pin); LL_GPIO_SetOutputPin(TDI_GPIO_Port, TDI_Pin); GPIO_InitStruct.Pin = RESET_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; LL_GPIO_Init(RESET_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = TRST_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; LL_GPIO_Init(TRST_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = SWTCK_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(SWTCK_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = SWDIO_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(SWDIO_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = TDI_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(TDI_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = TDO_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(TDO_GPIO_Port, &GPIO_InitStruct); } /** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: - SWCLK, SWDIO, nRESET to output mode and set to default high level. - TDI, nTRST to HighZ mode (pins are unused in SWD mode). */ __STATIC_INLINE void PORT_SWD_SETUP (void) { LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB); LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOC); LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOE); LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; LL_GPIO_SetOutputPin(RESET_GPIO_Port, RESET_Pin); LL_GPIO_SetOutputPin(SWTCK_GPIO_Port, SWTCK_Pin); LL_GPIO_SetOutputPin(SWDIO_GPIO_Port, SWDIO_Pin); GPIO_InitStruct.Pin = RESET_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; LL_GPIO_Init(RESET_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = SWTCK_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(SWTCK_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = SWDIO_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(SWDIO_GPIO_Port, &GPIO_InitStruct); // printf("PORT_SWD_SETUP \r\n"); } /** Disable JTAG/SWD I/O Pins. Disables the DAP Hardware I/O pins which configures: - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. */ __STATIC_INLINE void PORT_OFF (void) { ; } // SWCLK/TCK I/O pin ------------------------------------- /** SWCLK/TCK I/O pin: Get Input. \return Current status of the SWCLK/TCK DAP hardware I/O pin. */ __STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) { return (LL_GPIO_IsOutputPinSet(SWTCK_GPIO_Port, SWTCK_Pin)); } /** 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) { LL_GPIO_SetOutputPin(SWTCK_GPIO_Port, SWTCK_Pin); } /** SWCLK/TCK I/O pin: Set Output to Low. Set the SWCLK/TCK DAP hardware I/O pin to low level. */ __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) { LL_GPIO_ResetOutputPin(SWTCK_GPIO_Port, SWTCK_Pin); } // SWDIO/TMS Pin I/O -------------------------------------- /** 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 (LL_GPIO_IsOutputPinSet(SWDIO_GPIO_Port, SWDIO_Pin)); } /** 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) { LL_GPIO_SetOutputPin(SWDIO_GPIO_Port, SWDIO_Pin); } /** SWDIO/TMS I/O pin: Set Output to Low. Set the SWDIO/TMS DAP hardware I/O pin to low level. */ __STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) { LL_GPIO_ResetOutputPin(SWDIO_GPIO_Port, SWDIO_Pin); } /** SWDIO I/O pin: Get Input (used in SWD mode only). \return Current status of the SWDIO DAP hardware I/O pin. */ __STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) { return (LL_GPIO_IsInputPinSet(SWDIO_GPIO_Port, SWDIO_Pin)); } /** SWDIO I/O pin: Set Output (used in SWD mode only). \param bit Output value for the SWDIO DAP hardware I/O pin. */ __STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) { if (bit & 1) LL_GPIO_SetOutputPin(SWDIO_GPIO_Port, SWDIO_Pin); else LL_GPIO_ResetOutputPin(SWDIO_GPIO_Port, SWDIO_Pin); } /** 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) { LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = SWDIO_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(SWDIO_GPIO_Port, &GPIO_InitStruct); // printf("PIN_SWDIO_OUT_ENABLE \r\n"); } /** 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 called prior \ref PIN_SWDIO_IN function calls. */ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) { LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = SWDIO_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(SWDIO_GPIO_Port, &GPIO_InitStruct); // printf("PIN_SWDIO_OUT_DISABLE \r\n"); } // TDI Pin I/O --------------------------------------------- /** TDI I/O pin: Get Input. \return Current status of the TDI DAP hardware I/O pin. */ __STATIC_FORCEINLINE uint32_t PIN_TDI_IN (void) { return (0U); } /** TDI I/O pin: Set Output. \param bit Output value for the TDI DAP hardware I/O pin. */ __STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) { ; } // TDO Pin I/O --------------------------------------------- /** TDO I/O pin: Get Input. \return Current status of the TDO DAP hardware I/O pin. */ __STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) { return (0U); } // nTRST Pin I/O ------------------------------------------- /** nTRST I/O pin: Get Input. \return Current status of the nTRST DAP hardware I/O pin. */ __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) { return (0U); } /** nTRST I/O pin: Set Output. \param bit JTAG TRST Test Reset pin status: - 0: issue a JTAG TRST Test Reset. - 1: release JTAG TRST Test Reset. */ __STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) { ; } // nRESET Pin I/O------------------------------------------ /** nRESET I/O pin: Get Input. \return Current status of the nRESET DAP hardware I/O pin. */ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) { return (0U); } /** nRESET I/O pin: Set Output. \param bit target device hardware reset pin status: - 0: issue a device hardware reset. - 1: release device hardware reset. */ __STATIC_FORCEINLINE void PIN_nRESET_OUT (uint32_t bit) { ; } ///@} //************************************************************************************************** /** \defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs \ingroup DAP_ConfigIO_gr @{ CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. It is recommended to provide the following LEDs for status indication: - Connect LED: is active when the DAP hardware is connected to a debugger. - Running LED: is active when the debugger has put the target device into running state. */ /** Debug Unit: Set status of Connected LED. \param bit status of the Connect LED. - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. */ __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {} /** Debug Unit: Set status Target Running LED. \param bit status of the Target Running LED. - 1: Target Running LED ON: program execution in target started. - 0: Target Running LED OFF: program execution in target stopped. */ __STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {} ///@} //************************************************************************************************** /** \defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp \ingroup DAP_ConfigIO_gr @{ Access function for Test Domain Timer. The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. */ /** Get timestamp of Test Domain Timer. \return Current timestamp value. */ __STATIC_INLINE uint32_t TIMESTAMP_GET (void) { return (DWT->CYCCNT); } ///@} //************************************************************************************************** /** \defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization \ingroup DAP_ConfigIO_gr @{ CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. */ /** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: - I/O clock system enabled. - all I/O pins: input buffer enabled, output pins are set to HighZ mode. - for nTRST, nRESET a weak pull-up (if available) is enabled. - LED output pins are enabled and LEDs are turned off. */ __STATIC_INLINE void DAP_SETUP (void) { ; } /** Reset Target Device with custom specific I/O pin or command sequence. This function allows the optional implementation of a device specific reset sequence. It is called when the command \ref DAP_ResetTarget and is for example required when a device needs a time-critical unlock sequence that enables the debug port. \return 0 = no device specific reset sequence is implemented.\n 1 = a device specific reset sequence is implemented. */ __STATIC_INLINE uint8_t RESET_TARGET (void) { return (0U); // change to '1' when a device reset sequence is implemented } ///@} #endif /* __DAP_CONFIG_H__ */ ``` winusb2.0_cdc.c修改: 添加头文件: ```c /* * Copyright (c) 2024, sakumisu * * SPDX-License-Identifier: Apache-2.0 */ #include "usbd_core.h" #include "usbd_cdc_acm.h" #include "queue.h" #include "DAP.h" ``` 修改描述符:(这里需要注意两点,一描述符ep WINUSB_OUT_EP必须在WINUSB_IN_EP之前,keil强制要求,二是USB_DESCRIPTOR_TYPE_STRING描述符中必须要有 CMSIS-DAP字样) ```c const uint8_t winusbv2_descriptor[] = { USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), /* Configuration 0 */ USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), /* Interface 0 */ USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02), /* Endpoint OUT 2 */ USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00), /* Endpoint IN 1 */ USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00), CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 0x00), /* String 0 (LANGID) */ USB_LANGID_INIT(USBD_LANGID_STRING), /* String 1 (Manufacturer) */ 0x14, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 'C', 0x00, /* wcChar0 */ 'h', 0x00, /* wcChar1 */ 'e', 0x00, /* wcChar2 */ 'r', 0x00, /* wcChar3 */ 'r', 0x00, /* wcChar4 */ 'y', 0x00, /* wcChar5 */ 'U', 0x00, /* wcChar6 */ 'S', 0x00, /* wcChar7 */ 'B', 0x00, /* wcChar8 */ /* String 2 (Product) */ 0x2C, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 'C', 0x00, /* wcChar0 */ 'M', 0x00, /* wcChar1 */ 'S', 0x00, /* wcChar2 */ 'I', 0x00, /* wcChar3 */ 'S', 0x00, /* wcChar4 */ '-', 0x00, /* wcChar5 */ 'D', 0x00, /* wcChar6 */ 'A', 0x00, /* wcChar7 */ 'P', 0x00, /* wcChar8 */ ' ', 0x00, /* wcChar9 */ 't', 0x00, /* wcChar10 */ 'o', 0x00, /* wcChar11 */ ' ', 0x00, /* wcChar12 */ 'A', 0x00, /* wcChar13 */ 'R', 0x00, /* wcChar14 */ 'T', 0x00, /* wcChar15 */ '-', 0x00, /* wcChar16 */ 'P', 0x00, /* wcChar17 */ 'i', 0x00, /* wcChar18 */ '2', 0x00, /* wcChar19 */ ' ', 0x00, /* wcChar20 */ /* String 3 (Serial Number) */ 0x1A, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType '0', 0, // wcChar0 '1', 0, // wcChar1 '2', 0, // wcChar2 '3', 0, // wcChar3 '4', 0, // wcChar4 '5', 0, // wcChar5 'A', 0, // wcChar6 'B', 0, // wcChar7 'C', 0, // wcChar8 'D', 0, // wcChar9 'E', 0, // wcChar10 'F', 0, // wcChar11 #ifdef CONFIG_USB_HS /* Device Qualifier */ 0x0a, USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, 0x10, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, #endif /* End */ 0x00 }; ``` 修改消息处理函数: ```c static void usbd_event_handler(uint8_t busid, uint8_t event) { switch (event) { case USBD_EVENT_RESET: break; case USBD_EVENT_CONNECTED: break; case USBD_EVENT_DISCONNECTED: break; case USBD_EVENT_RESUME: break; case USBD_EVENT_SUSPEND: break; case USBD_EVENT_CONFIGURED: req_idle = 0; usbd_ep_start_read(busid, WINUSB_OUT_EP, queue_rear_elem(&req), PACKET_SIZE); break; case USBD_EVENT_SET_REMOTE_WAKEUP: break; case USBD_EVENT_CLR_REMOTE_WAKEUP: break; default: break; } } ``` 修改端点收发函数: ```c void usbd_winusb_out(uint8_t busid, uint8_t ep, uint32_t nbytes) { // USB_LOG_RAW("actual out len:%d\r\n", nbytes); queue_push(&req); if (!queue_full(&req)) { usbd_ep_start_read(busid, WINUSB_OUT_EP, queue_rear_elem(&req), PACKET_SIZE); } else { req_idle = 1; } } void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes) { // USB_LOG_RAW("actual in len:%d\r\n", nbytes); if (!queue_empty(&resp)) { usbd_ep_start_write(busid, WINUSB_IN_EP, queue_front_elem(&resp), resp.bufsz[resp.idxo]); queue_pop(&resp); } else { resp_idle = 1; } } ``` 添加dap处理函数: ```c void dap_init(void) { extern void DAP_Setup(void); DAP_Setup(); queue_init(&req, request_buf); queue_init(&resp, response_buf); req_idle = 1; resp_idle = 1; } #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') void hexdump(const void *ptr, uint32_t buflen) { unsigned char *buf = (unsigned char *)ptr; int i, j; for (i = 0; i < buflen; i += 16) { printf("%08X:", i); for (j = 0; j < 16; j++) if (i + j < buflen) { if ((j % 8) == 0) { printf(" "); } printf("%02X ", buf[i + j]); } else printf(" "); printf(" "); for (j = 0; j < 16; j++) if (i + j < buflen) printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); printf("\n"); } } extern uint32_t DAP_ExecuteCommand(const uint8_t *request, uint8_t *response); uint8_t buf_front[PACKET_SIZE]; uint8_t buf_rear[PACKET_SIZE]; void dap_handle(void) { uint32_t n; while (!queue_empty(&req)) { n = queue_get_idxo(&req); // hexdump(queue_get_buf(&req, n), PACKET_SIZE); while (queue_get_buf(&req, n)[0] == ID_DAP_QueueCommands) { queue_get_buf(&req, n)[0] = ID_DAP_ExecuteCommands; n = (n + 1) % PACKET_COUNT; if (n == queue_get_idxi(&req)) { } } resp.bufsz[resp.idxi] = (uint16_t)DAP_ExecuteCommand(queue_front_elem(&req), queue_rear_elem(&resp)); queue_pop(&req); queue_push(&resp); if (req_idle) { if (!queue_full(&req)) { req_idle = 0; usbd_ep_start_read(0, WINUSB_OUT_EP, queue_rear_elem(&req), PACKET_SIZE); } } if (resp_idle) { if (!queue_empty(&resp)) { uint8_t *out_buf = queue_front_elem(&resp); uint32_t bufsz = resp.bufsz[resp.idxo]; queue_pop(&resp); resp_idle = 0; usbd_ep_start_write(0, WINUSB_IN_EP, out_buf, bufsz); } } } } ``` 修改main.c: ```c /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_UART4_Init(); // MX_USB_OTG_HS_PCD_Init(); /* USER CODE BEGIN 2 */ printf("CMSIS-DAP for ART-Pi2(CherryUSB).\r\n"); extern void dap_init(void); dap_init(); extern void winusbv2_init(uint8_t busid, uintptr_t reg_base); winusbv2_init(0, USB_OTG_HS_PERIPH_BASE); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ // HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); // HAL_Delay(500); // HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); // HAL_Delay(500); extern void dap_handle(void); dap_handle(); } /* USER CODE END 3 */ ``` queue.h内容: ```c #include
#include
#include
#include "DAP_config.h" #define PACKET_COUNT DAP_PACKET_COUNT #define PACKET_SIZE DAP_PACKET_SIZE __attribute__((section(".noncacheable"))) USB_MEM_ALIGNX uint8_t request_buf[PACKET_COUNT][PACKET_SIZE]; __attribute__((section(".noncacheable"))) USB_MEM_ALIGNX uint8_t response_buf[PACKET_COUNT][PACKET_SIZE]; typedef struct queue_s { uint32_t idxi; uint32_t idxo; uint32_t cnti; uint32_t cnto; uint8_t *buf[PACKET_COUNT]; uint32_t bufsz[PACKET_COUNT]; } queue_t; static queue_t req; static queue_t resp; volatile static int req_idle; volatile static int resp_idle; // #pragma GCC push_options // #pragma GCC optimize ("O2") inline static int queue_init(queue_t *q, uint8_t buf[][PACKET_SIZE]) { if (q == NULL) return -1; q->idxi = 0; q->idxo = 0; q->cnti = 0; q->cnto = 0; for (int i = 0; i < PACKET_COUNT; i++) { q->buf[i] = buf[i]; q->bufsz[i] = 0; memset(q->buf[i], 0xff, PACKET_SIZE); printf("q->buf[%d]: %p \n", i, buf[i]); } return 0; } inline static int queue_full(queue_t *q) { return (((uint32_t)(q->cnti - q->cnto)) == PACKET_COUNT); } inline static int queue_empty(queue_t *q) { return (((uint32_t)(q->cnti - q->cnto)) == 0); } inline static uint8_t * queue_front_elem(queue_t *q) { if (q == NULL) return NULL; return q->buf[q->idxo]; } inline static uint8_t * queue_rear_elem(queue_t *q) { if (q == NULL) return NULL; return q->buf[q->idxi]; } inline static uint32_t queue_get_idxi(queue_t *q) { if (q == NULL) return NULL; return q->idxi; } inline static uint32_t queue_get_idxo(queue_t *q) { if (q == NULL) return NULL; return q->idxo; } inline static uint8_t *queue_get_buf(queue_t *q, uint32_t idx) { if (q == NULL) return NULL; return q->buf[idx]; } inline static int queue_push(queue_t *q) { if (q == NULL) return -1; q->idxi = (q->idxi + 1) % PACKET_COUNT; q->cnti++; return 0; } inline static int queue_pop(queue_t *q) { if (q == NULL) return -1; q->idxo = (q->idxo + 1) % PACKET_COUNT; q->cnto++; return 0; } inline static void queue_info(queue_t* q) { printf("idxi: %d, ", q->idxi); printf("idxo: %d, ", q->idxo); printf("cnti: %d, ", q->cnti); printf("cnto: %d \n", q->cnto); } // #pragma GCC pop_options ``` ### 4、运行 
3
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
lizimu
这家伙很懒,什么也没写!
文章
11
回答
23
被采纳
3
关注TA
发私信
相关文章
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
I2C_IIC
UART
ESP8266
cubemx
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
ulog
SFUD
msh
C++_cpp
MicroPython
本月问答贡献
RTT_逍遥
9
个答案
2
次被采纳
xiaorui
3
个答案
2
次被采纳
winfeng
2
个答案
2
次被采纳
三世执戟
8
个答案
1
次被采纳
KunYi
8
个答案
1
次被采纳
本月文章贡献
catcatbing
2
篇文章
5
次点赞
lizimu
1
篇文章
5
次点赞
swet123
1
篇文章
4
次点赞
Days
1
篇文章
4
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部