0%

RP2040应用指南

PIO相关

1
2
3
4
5
6
.program squarewave
set pindirs, 1 ; Set pin to output
again:
set pins, 1 [1] ; Drive pin high and then delay for one cycle
set pins, 0 ; Drive pin low
jmp again ; Set PC to label `again`

OpenOCD烧写调试

1
~$ ../configure --enable-cmsis-dap --enable-sysfsgpio --enable-imx_gpio --enable-bcm2835gpio  --enable-xds110 --enable-ftdi --enable-stlink
  • 添加支持Pyua PY25Q32H nor flash的支持
1
2
3
4
5
6
7
8
9
10
11
12
13
~ openocd$ git diff
diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c
index bf654f9f6..ac3e1e069 100644
--- a/src/flash/nor/spi.c
+++ b/src/flash/nor/spi.c
@@ -184,6 +184,7 @@ const struct flash_device flash_devices[] = {
FLASH_ID("xtx xt25q64b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0017600b, 0x100, 0x10000, 0x800000),
FLASH_ID("xtx xt25q128b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0018600b, 0x100, 0x10000, 0x1000000),
FLASH_ID("zetta zd25q16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001560ba, 0x100, 0x10000, 0x200000),
+ FLASH_ID("pyua py25q32h", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00162085, 0x100, 0x10000, 0x400000),

/* FRAM, no erase commands, no write page or sectors */

  • 烧写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
~$ openocd -f interface/ftdi/ft232h-module-swd.cfg  -f target/rp2040.cfg -c "program blink.elf verify reset exit"
Open On-Chip Debugger 0.12.0+dev-01369-gb388f4805 (2023-11-04-10:01)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : FTDI SWD mode enabled
swd
Warn : Transport "swd" was already selected
Info : Hardware thread awareness created
Info : Hardware thread awareness created
Warn : An adapter speed is not selected in the init scripts. OpenOCD will try to run the adapter at very low speed (100 kHz).
Warn : To remove this warnings and achieve reasonable communication speed with the target, set "adapter speed" or "jtag_rclk" in the init scripts.
Info : clock speed 100 kHz
Info : SWD DPIDR 0x0bc12477, DLPIDR 0x00000001
Info : SWD DPIDR 0x0bc12477, DLPIDR 0x10000001
Info : [rp2040.core0] Cortex-M0+ r0p1 processor detected
Info : [rp2040.core0] target has 4 breakpoints, 2 watchpoints
Info : [rp2040.core1] Cortex-M0+ r0p1 processor detected
Info : [rp2040.core1] target has 4 breakpoints, 2 watchpoints
Info : starting gdb server for rp2040.core0 on 3333
Info : Listening on port 3333 for gdb connections
Warn : [rp2040.core1] target was in unknown state when halt was requested
[rp2040.core0] halted due to debug-request, current mode: Thread
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
[rp2040.core1] halted due to debug-request, current mode: Thread
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
** Programming Started **
Info : Found flash device 'win w25q16jv' (ID 0x001540ef)
Info : RP2040 B0 Flash Probe: 2097152 bytes @0x10000000, in 32 sectors

Info : Padding image section 1 at 0x10002190 with 112 bytes (bank write end alignment)
Warn : Adding extra erase range, 0x10002200 .. 0x1000ffff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked

学习理解tinyusb+pico-sdk编译工程结构

  • TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the non-ISR task function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
~$ git clone https://github.com/hathach/tinyusb

~$ cd tinyusb
~$ tinyusb$ tree -L 2 -d
.
├── docs
│   ├── assets
│   ├── contributing
│   ├── info
│   └── reference
├── examples
│   ├── build
│   ├── device
│   ├── dual
│   ├── host
│   └── typec
├── hw
│   ├── bsp
│   └── mcu
├── lib
│   ├── embedded-cli
│   ├── fatfs
│   ├── networking
│   └── SEGGER_RTT
├── src
│   ├── class
│   ├── common
│   ├── device
│   ├── host
│   ├── osal
│   ├── portable
│   └── typec
├── test
│   ├── fuzz
│   ├── hil
│   └── unit-test
└── tools
├── cmake
├── codespell
├── make
└── usb_drivers

37 directories


  • 下面以tinyusb/examples/device/cdc_msc的工程为例。
1
2
3
4
5
6
7
8
9
10
11
12
13
tinyusb/examples/device/cdc_msc$ tree
.
├── CMakeLists.txt
├── Makefile
├── skip.txt
└── src
├── main.c
├── msc_disk.c
├── tusb_config.h
└── usb_descriptors.c

2 directories, 7 files

  • 分析CMakeLists.txt文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
tinyusb/examples/device/cdc_msc$ cat -n CMakeLists.txt
1 cmake_minimum_required(VERSION 3.17)
2 set_property(GLOBAL PROPERTY USE_FOLDERS ON) # 设置全局的属性,名为:USE_FOLDERS, 值为ON。
3
4 include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
5
6 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
7 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
8
9 project(${PROJECT} C CXX ASM)
10
11 # Checks this example is valid for the family and initializes the project
12 family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) # 定义在 family_support.cmake 内的函数。通过这里调用到tinyusb/hw/bsp/rp2040/family.cmake
13
14 # Espressif has its own cmake build system
15 if(FAMILY STREQUAL "espressif")
16 return()
17 endif()
18
19 add_executable(${PROJECT})
20
21 # Example source
22 target_sources(${PROJECT} PUBLIC
23 ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
24 ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c
25 ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
26 )
27
28 # Example include
29 target_include_directories(${PROJECT} PUBLIC
30 ${CMAKE_CURRENT_SOURCE_DIR}/src
31 )
32
33 # Configure compilation flags and libraries for the example... see the corresponding function
34 # in hw/bsp/FAMILY/family.cmake for details.
35 family_configure_device_example(${PROJECT} noos) # 需要在family.cmake里扩展的函数。

  • 上面的CMakeLists.txt第4行引入其它的tinyusb/hw/bsp/family_support.cmake文件,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
tinyusb/hw/bsp$ cat family_support.cmake
include_guard(GLOBAL) # 防止重复include当前的文件。

include(CMakePrintHelpers) # Convenience functions for printing properties and variables, useful e.g. for debugging.

# TOP is path to root directory
set(TOP "${CMAKE_CURRENT_LIST_DIR}/../..") # 设置变量TOP的值。
get_filename_component(TOP ${TOP} ABSOLUTE) # cmake 内置的函数,获取`${TOP}`完全路径。

# Default to gcc
if (NOT DEFINED TOOLCHAIN)
set(TOOLCHAIN gcc)
endif ()

# FAMILY not defined, try to detect it from BOARD
if (NOT DEFINED FAMILY)
if (NOT DEFINED BOARD)
message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, espressif).
You can do this via -DFAMILY=xxx on the cmake command line")
endif ()

# Find path contains BOARD
file(GLOB BOARD_PATH LIST_DIRECTORIES true
RELATIVE ${TOP}/hw/bsp
${TOP}/hw/bsp/*/boards/${BOARD}
)
if (NOT BOARD_PATH)
message(FATAL_ERROR "Could not detect FAMILY from BOARD=${BOARD}")
endif ()

# replace / with ; so that we can get the first element as FAMILY
string(REPLACE "/" ";" BOARD_PATH ${BOARD_PATH})
list(GET BOARD_PATH 0 FAMILY)
endif ()

if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake)
message(FATAL_ERROR "Family '${FAMILY}' is not known/supported")
endif()

if (NOT FAMILY STREQUAL rp2040)
# enable LTO if supported skip rp2040
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
cmake_print_variables(IPO_SUPPORTED)
if (IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
endif()

set(WARNING_FLAGS_GNU
-Wall
-Wextra
-Werror
[...]
)

set(WARNINGS_FLAGS_IAR "")

# Filter example based on only.txt and skip.txt
function(family_filter RESULT DIR)
get_filename_component(DIR ${DIR} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})

if (EXISTS "${DIR}/only.txt")
file(READ "${DIR}/only.txt" ONLYS)
# Replace newlines with semicolon so that it is treated as a list by CMake
string(REPLACE "\n" ";" ONLYS_LINES ${ONLYS})

# For each mcu
foreach(MCU IN LISTS FAMILY_MCUS)
# For each line in only.txt
foreach(_line ${ONLYS_LINES})
# If mcu:xxx exists for this mcu or board:xxx then include
if (${_line} STREQUAL "mcu:${MCU}" OR ${_line} STREQUAL "board:${BOARD}")
set(${RESULT} 1 PARENT_SCOPE)
return()
endif()
endforeach()
endforeach()

# Didn't find it in only file so don't build
set(${RESULT} 0 PARENT_SCOPE)

elseif (EXISTS "${DIR}/skip.txt")
file(READ "${DIR}/skip.txt" SKIPS)
# Replace newlines with semicolon so that it is treated as a list by CMake
string(REPLACE "\n" ";" SKIPS_LINES ${SKIPS})

# For each mcu
foreach(MCU IN LISTS FAMILY_MCUS)
# For each line in only.txt
foreach(_line ${SKIPS_LINES})
# If mcu:xxx exists for this mcu then skip
if (${_line} STREQUAL "mcu:${MCU}")
set(${RESULT} 0 PARENT_SCOPE)
return()
endif()
endforeach()
endforeach()

# Didn't find in skip file so build
set(${RESULT} 1 PARENT_SCOPE)
else()

# Didn't find skip or only file so build
set(${RESULT} 1 PARENT_SCOPE)
endif()
endfunction()


function(family_add_subdirectory DIR)
family_filter(SHOULD_ADD "${DIR}")
if (SHOULD_ADD)
add_subdirectory(${DIR})
endif()
endfunction()


function(family_get_project_name OUTPUT_NAME DIR)
get_filename_component(SHORT_NAME ${DIR} NAME)
set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE)
endfunction()


function(family_initialize_project PROJECT DIR)
# set output suffix to .elf (skip espressif and rp2040)
if(NOT FAMILY STREQUAL "espressif" AND NOT FAMILY STREQUAL "rp2040")
set(CMAKE_EXECUTABLE_SUFFIX .elf PARENT_SCOPE)
endif()

family_filter(ALLOWED "${DIR}")
if (NOT ALLOWED)
get_filename_component(SHORT_NAME ${DIR} NAME)
message(FATAL_ERROR "${SHORT_NAME} is not supported on FAMILY=${FAMILY}")
endif()
endfunction()


#-------------------------------------------------------------
# Common Target Configure
# Most families use these settings except rp2040 and espressif
#-------------------------------------------------------------

# Add RTOS to example
function(family_add_rtos TARGET RTOS)
if (RTOS STREQUAL "freertos")
# freertos config
if (NOT TARGET freertos_config)
add_library(freertos_config INTERFACE)
target_include_directories(freertos_config INTERFACE ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${FAMILY}/FreeRTOSConfig)
# add board definition to freertos_config mostly for SystemCoreClock
target_link_libraries(freertos_config INTERFACE board_${BOARD})
endif()

# freertos kernel
if (NOT TARGET freertos_kernel)
add_subdirectory(${TOP}/lib/FreeRTOS-Kernel ${CMAKE_BINARY_DIR}/lib/freertos_kernel)
endif ()

target_link_libraries(${TARGET} PUBLIC freertos_kernel)
endif ()
endfunction()


# Add common configuration to example
function(family_configure_common TARGET RTOS)
family_add_rtos(${TARGET} ${RTOS})

string(TOUPPER ${BOARD} BOARD_UPPER)
string(REPLACE "-" "_" BOARD_UPPER ${BOARD_UPPER})
target_compile_definitions(${TARGET} PUBLIC
BOARD_${BOARD_UPPER}
)

# run size after build
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${TARGET}>
)

# Add warnings flags
target_compile_options(${TARGET} PUBLIC ${WARNING_FLAGS_${CMAKE_C_COMPILER_ID}})

# Generate linker map file
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC "LINKER:-Map=$<TARGET_FILE:${TARGET}>.map")
endif()

# ETM Trace option
if (TRACE_ETM STREQUAL "1")
target_compile_definitions(${TARGET} PUBLIC TRACE_ETM)
endif ()

# LOGGER option
if (DEFINED LOGGER)
target_compile_definitions(${TARGET} PUBLIC LOGGER_${LOGGER})

# Add segger rtt to example
if(LOGGER STREQUAL "RTT" OR LOGGER STREQUAL "rtt")
if (NOT TARGET segger_rtt)
add_library(segger_rtt STATIC ${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c)
target_include_directories(segger_rtt PUBLIC ${TOP}/lib/SEGGER_RTT/RTT)
#target_compile_definitions(segger_rtt PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL)
endif()
target_link_libraries(${TARGET} PUBLIC segger_rtt)
endif ()
endif ()
endfunction()


# Add tinyusb to example
function(family_add_tinyusb TARGET OPT_MCU RTOS)
# tinyusb target is built for each example since it depends on example's tusb_config.h
set(TINYUSB_TARGET_PREFIX ${TARGET}-)
add_library(${TARGET}-tinyusb_config INTERFACE)

# path to tusb_config.h
target_include_directories(${TARGET}-tinyusb_config INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUSB_MCU=${OPT_MCU})

if (DEFINED LOG)
target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUSB_DEBUG=${LOG})
if (LOG STREQUAL "4")
# no inline for debug level 4
target_compile_definitions(${TARGET}-tinyusb_config INTERFACE TU_ATTR_ALWAYS_INLINE=)
endif ()
endif()

if (RTOS STREQUAL "freertos")
target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUSB_OS=OPT_OS_FREERTOS)
endif ()

# tinyusb's CMakeList.txt
add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb)

if (RTOS STREQUAL "freertos")
# link tinyusb with freeRTOS kernel
target_link_libraries(${TARGET}-tinyusb PUBLIC freertos_kernel)
endif ()

# use max3421 as host controller
if (MAX3421_HOST STREQUAL "1")
target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUH_MAX3421=1)
target_sources(${TARGET}-tinyusb PUBLIC
${TOP}/src/portable/analog/max3421/hcd_max3421.c
)
endif ()

endfunction()


# Add bin/hex output
function(family_add_bin_hex TARGET)
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${TARGET}> $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.bin
COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${TARGET}> $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.hex
VERBATIM)
endfunction()


#----------------------------------
# Example Target Configure (Default rule)
# These function can be redefined in FAMILY/family.cmake
#----------------------------------

function(family_configure_example TARGET RTOS)
# empty function, should be redefined in FAMILY/family.cmake
endfunction()

# Configure device example with RTOS
function(family_configure_device_example TARGET RTOS)
family_configure_example(${TARGET} ${RTOS})
endfunction()


# Configure host example with RTOS
function(family_configure_host_example TARGET RTOS)
family_configure_example(${TARGET} ${RTOS})
endfunction()


# Configure host + device example with RTOS
function(family_configure_dual_usb_example TARGET RTOS)
family_configure_example(${TARGET} ${RTOS})
endfunction()

function(family_example_missing_dependency TARGET DEPENDENCY)
message(WARNING "${DEPENDENCY} submodule needed by ${TARGET} not found, please run 'python tools/get_deps.py ${DEPENDENCY}' to fetch it")
endfunction()

#----------------------------------
# RPI specific: refactor later
#----------------------------------
function(family_add_default_example_warnings TARGET)
target_compile_options(${TARGET} PUBLIC
-Wall
-Wextra
[...]
)

if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)
target_link_options(${TARGET} PUBLIC "LINKER:--no-warn-rwx-segments")
endif()

# GCC 10
if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0)
target_compile_options(${TARGET} PUBLIC -Wconversion)
endif()
[...]
endfunction()

#----------------------------------
# Flashing target
#----------------------------------

# Add flash pycod target
function(family_flash_pyocd TARGET)
if (NOT DEFINED PYOC)
set(PYOCD pyocd)
endif ()

add_custom_target(${TARGET}-pyocd
DEPENDS ${TARGET}
COMMAND ${PYOCD} flash -t ${PYOCD_TARGET} $<TARGET_FILE:${TARGET}>
)
endfunction()


function(family_flash_dfu_util TARGET OPTION)
if (NOT DEFINED DFU_UTIL)
set(DFU_UTIL dfu-util)
endif ()

add_custom_target(${TARGET}-dfu-util
DEPENDS ${TARGET}
COMMAND ${DFU_UTIL} -R -d ${DFU_UTIL_VID_PID} -a 0 -D $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.bin
VERBATIM
)
endfunction()

#----------------------------------
# Family specific
#----------------------------------

# family specific: can override above functions
include(${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake)
# 这里调用不同的BSP或者MCU的目录的`cmake`文件,以rp2040为例是:tinyusb/hw/bsp/rp2040/family.cmake

if (NOT FAMILY_MCUS)
set(FAMILY_MCUS ${FAMILY})
endif()

# if use max3421 as host controller, expand FAMILY_MCUS to include max3421
if (MAX3421_HOST STREQUAL "1")
set(FAMILY_MCUS ${FAMILY_MCUS} MAX3421)
endif ()

# save it in case of re-inclusion
set(FAMILY_MCUS ${FAMILY_MCUS} CACHE INTERNAL "")

ta

  • TinyUSB是一个嵌入式系统下开源跨平台的USB协议栈,以RP2040为例,它的开发实现是要依赖于pico-sdk的。

  • 编译工程

1
2
3
4
~ examples/device/video_capture$ mkdir build && cd build
~ examples/device/video_capture/build $
~ examples/device/video_capture/build $ cmake -DFAMILY=rp2040 -DPICO_SDK_PATH=/home/michael/3TB-DISK/RaspberryPi/RP2040/pico-sdk/ ../
~ examples/device/video_capture/build $ openocd -f interface/ftdi/ft232h-module-swd.cfg -f target/rp2040.cfg -c "program video_capture.elf verify reset exit"

使用TFT_eSPI(ardion)驱动ili9341 16bit并口屏

安装rp2040 bsp支持

  • 安装第三方的arduino-pico库,让Arduino IDE可以支持rp2040板子。
  • 首先在Arduino IDE -> File -> Preference -> Additional Boards Manager URLs:添加下面的链接:
1
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
  • 再打开Board Manager进行联网更新,搜索pico并且安装Raspberry Pi Pico/RP2040的包。

配置TFT_eSPI

  • 打开已经预定义好的文件:~/Arduino/libraries/TFT_eSPI/User_Setups/Setup107_RP2040_ILI9341_16bit_parallel.h,把屏幕与RP2040按照文件的线序进行连接。

  • 再打开~/Arduino/libraries/TFT_eSPI/User_Setups/User_Setup_Select.h,只打开上面这一个文件的注释。

1
#include <User_Setups/Setup107_RP2040_ILI9341_16bit_parallel.h>
  • 选择打开一个TFT_eSPI内置的测试工程。这里使用的是官方的板子,就选择Tools -> Boards -> Rasperry Pi RP2040 Boards -> Rasperry Pi Pico. 编译上传就可以看到结果,烧写过程中有可能需要手动复位BOOTSEL按键。

简单逻辑分析仪示例

  • Install Rust
1
2
3
4
~$ rustup target add thumbv6m-none-eabi
~$ rustup component add llvm-tools-preview
~$ cargo install cargo-binutils
~$ cargo install elf2uf2-rs
  • 连机编译与烧写运行
1
2
~$ git clone https://github.com/dotcypress/ula

  • Hold the BOOTSEL button while connecting your board to the computer, then run following command.
1
2
~$ cd ula
~$ cargo run --release

PulseView

  • Select Openbench Logic Sniffer & SUMP compatible protocol when connecting to μLA.

SigrokCli

  • Scan for devices
1
~$ sigrok-cli -d ols:conn=/dev/tty.usbmodem_ula_1 --scan
  • Sample two 10 MHz square waves with 90° phase shift
1
2
3
4
5
6
7
8
9
10
~$ sigrok-cli -d ols:conn=/dev/tty.usbmodem_ula_1
-O ascii:charset='_`\/'
--config samplerate=100m
--samples 70

libsigrok 0.5.2
Acquisition with 16/16 channels at 100 MHz
0:``\____/`````\___/`````\___/`````\___/`````\___/`````\___/`````\___/``
1:____/`````\____/````\____/````\____/````\____/````\____/````\____/````
2:______________________________________________________________________

LoRa通信

USB协议栈

USB结构简介

descriptor-table.svg

Descriptor Types

  • The most commonly used descriptors include:

    • Device Descriptor
    • Configuration Descriptor
    • Interface Descriptor
    • Endpoint Descriptor
    • String Descriptor
  • Every USB device must have one Device Descriptor and at least one each of the Configuration, Interface, and Endpoint Descriptors.

Device Descriptor

  • The Device Descriptor is the first descriptor read by the Host during enumeration. The purpose of the Device Descriptor is to let the Host know what specification of USB the device complies with and how many possible configurations are available on the device. Upon successful processing of the Device Descriptor, the Host will read all the Configuration Descriptors.

Configuration Descriptor

  • A device may have more than one configuration. Each device configuration is assigned a number. The Configuration Descriptor serves two purposes:

    Informs the Host as to how many interfaces (i.e., virtual devices) are in the configuration. While it is common for a configuration to offer only one interface, Devices that appear like two or more products have more than one interface.
    How much power the device will consume if this configuration is activated by the Host. If the device is capable of controlling its power consumption, it may offer more than one configuration. Each configuration will advertise how much power would be consumed if the configuration were to be activated.

Interface Descriptor

An Interface Descriptor describes the details of the function of the product. Key elements include the number of endpoints on the device and which USB device class is implemented by the endpoints. For example, if the device were a keyboard, the specified device class would be Human Interface Device (HID) and the number of endpoints would be two.

Endpoint Descriptor

  • Each endpoint on a device has its own descriptor. The descriptor provides the endpoint address (i.e., endpoint number), the size of the endpoint, and the data transfer type used to access the endpoint.
  • Endpoint 0 (EP0IN and EP0OUT) are reserved in every device for control purposes.
  • A USB device can have up to 32 endpoints (16 OUT and 16 IN). Since EP0IN and EP0OUT are set aside as control endpoints, the maximum number of endpoints available to transmit application data is 30.

String Descriptor

  • Strings Descriptors are optional human readable strings which the Host OS may display.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
~$ lsusb -v -s 001:005

Bus 001 Device 005: ID cafe:4020 TinyUSB TinyUSB Device
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 239 Miscellaneous Device
bDeviceSubClass 2
bDeviceProtocol 1 Interface Association
bMaxPacketSize0 64
idVendor 0xcafe
idProduct 0x4020
bcdDevice 1.00
iManufacturer 1 TinyUSB
iProduct 2 TinyUSB Device
iSerial 3 E6609CB2D3995B33
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x00a7
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 500mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 14 Video
bFunctionSubClass 3 Video Interface Collection
bFunctionProtocol 0
iFunction 4 TinyUSB UVC
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 14 Video
bInterfaceSubClass 1 Video Control
bInterfaceProtocol 1
iInterface 4 TinyUSB UVC
VideoControl Interface Descriptor:
bLength 13
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdUVC 1.50
wTotalLength 0x0028
dwClockFrequency 27.000000MHz
bInCollection 1
baInterfaceNr( 0) 1
VideoControl Interface Descriptor:
bLength 18
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 1
wTerminalType 0x0201 Camera Sensor
bAssocTerminal 0
iTerminal 0
wObjectiveFocalLengthMin 0
wObjectiveFocalLengthMax 0
wOcularFocalLength 0
bControlSize 3
bmControls 0x00000000
VideoControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 2
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bSourceID 1
iTerminal 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 14 Video
bInterfaceSubClass 2 Video Streaming
bInterfaceProtocol 1
iInterface 4 TinyUSB UVC
VideoStreaming Interface Descriptor:
bLength 14
bDescriptorType 36
bDescriptorSubtype 1 (INPUT_HEADER)
bNumFormats 1
wTotalLength 0x0055
bEndpointAddress 0x81 EP 1 IN
bmInfo 0
bTerminalLink 2
bStillCaptureMethod 0
bTriggerSupport 0
bTriggerUsage 0
bControlSize 1
bmaControls( 0) 0
VideoStreaming Interface Descriptor:
bLength 27
bDescriptorType 36
bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED)
bFormatIndex 1
bNumFrameDescriptors 1
guidFormat {32595559-0000-0010-8000-00aa00389b71}
bBitsPerPixel 16
bDefaultFrameIndex 1
bAspectRatioX 0
bAspectRatioY 0
bmInterlaceFlags 0x00
Interlaced stream or variable: No
Fields per frame: 2 fields
Field 1 first: No
Field pattern: Field 1 only
bCopyProtect 0
VideoStreaming Interface Descriptor:
bLength 38
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 1
bmCapabilities 0x00
Still image unsupported
wWidth 160
wHeight 120
dwMinBitRate 307200
dwMaxBitRate 7680000
dwMaxVideoFrameBufferSize 307200
dwDefaultFrameInterval 400000
bFrameIntervalType 0
dwMinFrameInterval 400000
dwMaxFrameInterval 10000000
dwFrameIntervalStep 400000
VideoStreaming Interface Descriptor:
bLength 6
bDescriptorType 36
bDescriptorSubtype 13 (COLORFORMAT)
bColorPrimaries 1 (BT.709,sRGB)
bTransferCharacteristics 1 (BT.709)
bMatrixCoefficients 4 (SMPTE 170M (BT.601))
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Device Status: 0x0000
(Bus Powered)

USB Transfer Types

Desc Interrupt Transfers Isochronous Transfers Bulk Transfers
Benefits High-reliability data transfers with a fixed response time High bandwidth High reliability with the potential for high bandwidth
Drawback Bandwidth may be limited (64 KBytes for Full-Speed USB) No CRC hardware. If a CRC is needed it must be done in software. Long packets can limit the number of devices being enumerated. Bandwidth may vary depending upon the number of interrupt endpoints enumerated and the activity of enumerated Isochronous endpoints.
Typical Use Mice, Keyboards, and Medical Devices Audio/Video streaming, serial port emulation Mass Storage and Printers
Notes Up to 90 percent of the frame can be allocated for Interrupt endpoints.The maximum length of the transfer depends upon the frame size used. Up to 90 percent of the frame can be allocated for interrupt endpoints. When not in use the bandwidth used will be released. The maximum length of the transfer depends upon the frame size used. Will take advantage of unused Isochronous bandwidth.The maximum length of the transfer depends upon the frame size used.

Linux USB手抓包分析

1
2
3
4
5
~$ lsmod | grep "usbmon"
usbmon 40960 0
usbcore 389120 12 ftdi_sio,usbserial,xhci_hcd,usbmon,usbhid,cdc_acm,usb_storage,uvcvideo,btusb,xhci_pci,uas,hid_logitech_hidpp
usb_common 16384 4 xhci_hcd,usbmon,usbcore,uvcvideo

  • 这里测试需要监听的要目标设备,是TinyUSB的设备,在Bus 3, Device 90,
1
2
~$  lsusb  | grep "TinyUSB"
Bus 003 Device 090: ID cafe:4020 TinyUSB TinyUSB Device
  • 打开wireshark, 选择usbmon3开始抓包。如下图所示,这里抓到的是错误码的UVC的包。

usbmon-capture-by-wireshark.png

  • 下面示例抓取一个正常的UVC的协议包。在Bus 3, Device 91,
1
2
~$ lsusb | grep "EM-Camera"
Bus 003 Device 091: ID 1e4e:0110 Cubeternet USB 2.0 EM-Camera2 5M

usbmon-capture-by-wireshark-uvc_ok.png

UVC相关

CC1101

联系作者